add interface xnet.SrcAddr/DstAddr

This commit is contained in:
ginuerzh
2025-08-03 10:15:53 +08:00
parent 79203e407c
commit f71351f5ef
42 changed files with 518 additions and 295 deletions
+14
View File
@@ -58,6 +58,20 @@ func (c *serverConn) Metadata() metadata.Metadata {
return nil
}
func (c *serverConn) SrcAddr() net.Addr {
if sc, ok := c.Conn.(xnet.SrcAddr); ok {
return sc.SrcAddr()
}
return nil
}
func (c *serverConn) DstAddr() net.Addr {
if sc, ok := c.Conn.(xnet.DstAddr); ok {
return sc.DstAddr()
}
return nil
}
func (c *serverConn) CloseRead() error {
if sc, ok := c.Conn.(xio.CloseRead); ok {
return sc.CloseRead()
+5 -1
View File
@@ -51,11 +51,15 @@ func (p *grpcPlugin) Authenticate(ctx context.Context, user, password string, op
return "", false
}
var clientAddr string
if v := ctxvalue.SrcAddrFromContext(ctx); v != nil {
clientAddr = v.String()
}
r, err := p.client.Authenticate(ctx,
&proto.AuthenticateRequest{
Username: user,
Password: password,
Client: string(ctxvalue.ClientAddrFromContext(ctx)),
Client: clientAddr,
})
if err != nil {
p.log.Error(err)
+6 -1
View File
@@ -53,10 +53,15 @@ func (p *httpPlugin) Authenticate(ctx context.Context, user, password string, op
return
}
var clientAddr string
if v := ctxvalue.SrcAddrFromContext(ctx); v != nil {
clientAddr = v.String()
}
rb := httpPluginRequest{
Username: user,
Password: password,
Client: string(ctxvalue.ClientAddrFromContext(ctx)),
Client: clientAddr,
}
v, err := json.Marshal(&rb)
if err != nil {
+40 -20
View File
@@ -115,15 +115,34 @@ func BuildConfigFromCmd(serviceList, nodeList []string) (*config.Config, error)
}
if v := mdutil.GetString(md, "interface"); v != "" {
hopConfig.Interface = v
m["hop.interface"] = v
delete(m, "interface")
}
if v := mdutil.GetInt(md, "so_mark"); v > 0 {
hopConfig.SockOpts = &config.SockOptsConfig{
Mark: v,
}
m["hop.so_mark"] = v
delete(m, "so_mark")
}
if v := mdutil.GetInt(md, "proxyProtocol"); v > 0 {
m["hop.proxyProtocol"] = v
delete(m, "proxyProtocol")
}
hopMd := map[string]any{}
for k, v := range m {
if strings.HasPrefix(k, "node.") ||
strings.HasPrefix(k, "connector.") ||
strings.HasPrefix(k, "dialer.") {
continue
}
if s, found := strings.CutPrefix(k, "hop."); found {
hopMd[s] = v
delete(m, k)
continue
}
hopMd[k] = v
}
hopConfig.Metadata = hopMd
nodeConfig, err := buildNodeConfig(url, m)
if err != nil {
@@ -144,22 +163,6 @@ func BuildConfigFromCmd(serviceList, nodeList []string) (*config.Config, error)
}
hopConfig.Nodes = nodes
hopMd := map[string]any{}
for k, v := range m {
if strings.HasPrefix(k, "node.") ||
strings.HasPrefix(k, "connector.") ||
strings.HasPrefix(k, "dialer.") {
continue
}
if s, found := strings.CutPrefix(k, "hop."); found {
hopMd[s] = v
continue
}
hopMd[k] = v
}
hopConfig.Metadata = hopMd
chain.Hops = append(chain.Hops, hopConfig)
}
@@ -501,6 +504,23 @@ func buildServiceConfig(url *url.URL) ([]*config.ServiceConfig, error) {
m["service.interface"] = v
delete(m, "interface")
}
if v := mdutil.GetInt(md, "so_mark"); v > 0 {
m["service.so_mark"] = v
delete(m, "so_mark")
}
if v := mdutil.GetInt(md, "proxyProtocol"); v > 0 {
m["service.proxyProtocol"] = v
delete(m, "proxyProtocol")
}
if v := mdutil.GetString(md, "netns"); v != "" {
m["service.netns"] = v
delete(m, "netns")
}
if v := mdutil.GetString(md, "netns.out"); v != "" {
m["service.netns.out"] = v
delete(m, "netns.out")
}
selector := parseSelector(m)
serviceMd := map[string]any{}
+23 -18
View File
@@ -507,21 +507,23 @@ type ChainGroupConfig struct {
}
type HopConfig struct {
Name string `json:"name"`
Interface string `yaml:",omitempty" json:"interface,omitempty"`
SockOpts *SockOptsConfig `yaml:"sockopts,omitempty" json:"sockopts,omitempty"`
Selector *SelectorConfig `yaml:",omitempty" json:"selector,omitempty"`
Bypass string `yaml:",omitempty" json:"bypass,omitempty"`
Bypasses []string `yaml:",omitempty" json:"bypasses,omitempty"`
Resolver string `yaml:",omitempty" json:"resolver,omitempty"`
Hosts string `yaml:",omitempty" json:"hosts,omitempty"`
Nodes []*NodeConfig `yaml:",omitempty" json:"nodes,omitempty"`
Reload time.Duration `yaml:",omitempty" json:"reload,omitempty"`
File *FileLoader `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisLoader `yaml:",omitempty" json:"redis,omitempty"`
HTTP *HTTPLoader `yaml:"http,omitempty" json:"http,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
Metadata map[string]any `yaml:",omitempty" json:"metadata,omitempty"`
Name string `json:"name"`
// Deprecated: use metadata.interface instead
Interface string `yaml:",omitempty" json:"interface,omitempty"`
// Deprecated: use metadata.so_mark instead
SockOpts *SockOptsConfig `yaml:"sockopts,omitempty" json:"sockopts,omitempty"`
Selector *SelectorConfig `yaml:",omitempty" json:"selector,omitempty"`
Bypass string `yaml:",omitempty" json:"bypass,omitempty"`
Bypasses []string `yaml:",omitempty" json:"bypasses,omitempty"`
Resolver string `yaml:",omitempty" json:"resolver,omitempty"`
Hosts string `yaml:",omitempty" json:"hosts,omitempty"`
Nodes []*NodeConfig `yaml:",omitempty" json:"nodes,omitempty"`
Reload time.Duration `yaml:",omitempty" json:"reload,omitempty"`
File *FileLoader `yaml:",omitempty" json:"file,omitempty"`
Redis *RedisLoader `yaml:",omitempty" json:"redis,omitempty"`
HTTP *HTTPLoader `yaml:"http,omitempty" json:"http,omitempty"`
Plugin *PluginConfig `yaml:",omitempty" json:"plugin,omitempty"`
Metadata map[string]any `yaml:",omitempty" json:"metadata,omitempty"`
}
type NodeConfig struct {
@@ -534,9 +536,12 @@ type NodeConfig struct {
Hosts string `yaml:",omitempty" json:"hosts,omitempty"`
Connector *ConnectorConfig `yaml:",omitempty" json:"connector,omitempty"`
Dialer *DialerConfig `yaml:",omitempty" json:"dialer,omitempty"`
Interface string `yaml:",omitempty" json:"interface,omitempty"`
Netns string `yaml:",omitempty" json:"netns,omitempty"`
SockOpts *SockOptsConfig `yaml:"sockopts,omitempty" json:"sockopts,omitempty"`
// Deprecated: use metadata.interface instead
Interface string `yaml:",omitempty" json:"interface,omitempty"`
// Deprecated: use metadata.netns instead
Netns string `yaml:",omitempty" json:"netns,omitempty"`
// Deprecated: use metadata.so_mark instead
SockOpts *SockOptsConfig `yaml:"sockopts,omitempty" json:"sockopts,omitempty"`
// Deprecated: use matcher instead
Filter *NodeFilterConfig `yaml:",omitempty" json:"filter,omitempty"`
Matcher *NodeMatcherConfig `yaml:",omitempty" json:"matcher,omitempty"`
+52 -9
View File
@@ -50,6 +50,8 @@ func ParseHop(cfg *config.HopConfig, log logger.Logger) (hop.Hop, error) {
}
}
var ppv int
var soMark int
ifce := cfg.Interface
var netns string
if cfg.Metadata != nil {
@@ -57,7 +59,16 @@ func ParseHop(cfg *config.HopConfig, log logger.Logger) (hop.Hop, error) {
if v := mdutil.GetString(md, parsing.MDKeyInterface); v != "" {
ifce = v
}
netns = mdutil.GetString(md, "netns")
if cfg.SockOpts != nil {
soMark = cfg.SockOpts.Mark
}
if v := mdutil.GetInt(md, parsing.MDKeySoMark); v > 0 {
soMark = v
}
ppv = mdutil.GetInt(md, parsing.MDKeyProxyProtocol)
netns = mdutil.GetString(md, parsing.MDKeyNetns)
}
var nodes []*chain.Node
@@ -66,21 +77,53 @@ func ParseHop(cfg *config.HopConfig, log logger.Logger) (hop.Hop, error) {
continue
}
m := v.Metadata
if m == nil {
m = map[string]any{}
v.Metadata = m
}
md := metadata.NewMetadata(m)
if v.Resolver == "" {
v.Resolver = cfg.Resolver
}
if v.Hosts == "" {
v.Hosts = cfg.Hosts
}
if v.Interface == "" {
v.Interface = ifce
}
if v.Netns == "" {
v.Netns = netns
}
if v.SockOpts == nil {
v.SockOpts = cfg.SockOpts
if !md.IsExists(parsing.MDKeyInterface) {
// inherit from hop
if ifce != "" {
m[parsing.MDKeyInterface] = ifce
}
// node level
if v.Interface != "" {
m[parsing.MDKeyInterface] = v.Interface
}
}
if !md.IsExists(parsing.MDKeySoMark) {
// inherit from hop
if soMark != 0 {
m[parsing.MDKeySoMark] = soMark
}
// node level
if v.SockOpts != nil && v.SockOpts.Mark != 0 {
m[parsing.MDKeySoMark] = v.SockOpts.Mark
}
}
if !md.IsExists(parsing.MDKeyProxyProtocol) && ppv > 0 {
// inherit from hop
m[parsing.MDKeyProxyProtocol] = ppv
}
if !md.IsExists(parsing.MDKeyNetns) {
// inherit from hop
if netns != "" {
m[parsing.MDKeyNetns] = netns
}
// node level
if v.Netns != "" {
m[parsing.MDKeyNetns] = v.Name
}
}
if v.Connector == nil {
+7 -16
View File
@@ -10,7 +10,6 @@ import (
"github.com/go-gost/core/connector"
"github.com/go-gost/core/dialer"
"github.com/go-gost/core/logger"
"github.com/go-gost/core/metadata"
xauth "github.com/go-gost/x/auth"
xbypass "github.com/go-gost/x/bypass"
xchain "github.com/go-gost/x/chain"
@@ -65,11 +64,6 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
return nil, err
}
var nm metadata.Metadata
if cfg.Metadata != nil {
nm = mdx.NewMetadata(cfg.Metadata)
}
connectorLogger := nodeLogger.WithFields(map[string]any{
"kind": "connector",
})
@@ -105,10 +99,7 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
return nil, err
}
var ppv int
if nm != nil {
ppv = mdutil.GetInt(nm, parsing.MDKeyProxyProtocol)
}
md := mdx.NewMetadata(cfg.Metadata)
dialerLogger := nodeLogger.WithFields(map[string]any{
"kind": "dialer",
@@ -120,7 +111,7 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
dialer.AuthOption(auth_parser.Info(cfg.Dialer.Auth)),
dialer.TLSConfigOption(tlsConfig),
dialer.LoggerOption(dialerLogger),
dialer.ProxyProtocolOption(ppv),
dialer.ProxyProtocolOption(mdutil.GetInt(md, parsing.MDKeyProxyProtocol)),
)
} else {
return nil, fmt.Errorf("unregistered dialer: %s", cfg.Dialer.Type)
@@ -135,16 +126,16 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
}
var sockOpts *chain.SockOpts
if cfg.SockOpts != nil {
if v := mdutil.GetInt(md, parsing.MDKeySoMark); v != 0 {
sockOpts = &chain.SockOpts{
Mark: cfg.SockOpts.Mark,
Mark: v,
}
}
tr := xchain.NewTransport(d, cr,
chain.AddrTransportOption(cfg.Addr),
chain.InterfaceTransportOption(cfg.Interface),
chain.NetnsTransportOption(cfg.Netns),
chain.InterfaceTransportOption(mdutil.GetString(md, parsing.MDKeyInterface)),
chain.NetnsTransportOption(mdutil.GetString(md, parsing.MDKeyNetns)),
chain.SockOptsTransportOption(sockOpts),
)
@@ -153,7 +144,7 @@ func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.No
chain.BypassNodeOption(xbypass.BypassGroup(bypass_parser.List(cfg.Bypass, cfg.Bypasses...)...)),
chain.ResoloverNodeOption(registry.ResolverRegistry().Get(cfg.Resolver)),
chain.HostMapperNodeOption(registry.HostsRegistry().Get(cfg.Hosts)),
chain.MetadataNodeOption(nm),
chain.MetadataNodeOption(md),
chain.NetworkNodeOption(cfg.Network),
}
+3 -3
View File
@@ -77,9 +77,9 @@ func (c *routerConnector) Connect(ctx context.Context, conn net.Conn, network, a
})
}
srcAddr := conn.LocalAddr().String()
if v := ctxvalue.ClientAddrFromContext(ctx); v != "" {
srcAddr = string(v)
srcAddr := conn.RemoteAddr().String()
if v := ctxvalue.SrcAddrFromContext(ctx); v != nil {
srcAddr = v.String()
}
af := &relay.AddrFeature{}
+3 -3
View File
@@ -73,9 +73,9 @@ func (c *tunnelConnector) Connect(ctx context.Context, conn net.Conn, network, a
})
}
srcAddr := conn.LocalAddr().String()
if v := ctxvalue.ClientAddrFromContext(ctx); v != "" {
srcAddr = string(v)
srcAddr := conn.RemoteAddr().String()
if v := ctxvalue.SrcAddrFromContext(ctx); v != nil {
srcAddr = v.String()
}
af := &relay.AddrFeature{}
+60 -16
View File
@@ -3,18 +3,21 @@ package ctx
import (
"bytes"
"context"
"net"
"github.com/go-gost/core/logger"
)
type ClientAddr string
func (a ClientAddr) String() string {
return string(a)
}
// clientAddrKey saves the client address.
type clientAddrKey struct{}
type ClientAddr string
var (
keyClientAddr clientAddrKey
)
var keyClientAddr clientAddrKey
func ContextWithClientAddr(ctx context.Context, addr ClientAddr) context.Context {
return context.WithValue(ctx, keyClientAddr, addr)
@@ -25,9 +28,43 @@ func ClientAddrFromContext(ctx context.Context) ClientAddr {
return v
}
// sidKey saves the session ID.
type sidKey struct{}
type Sid string
type (
srcAddrKey struct{}
dstAddrKey struct{}
)
var (
keySrcAddr srcAddrKey
keyDstAddr dstAddrKey
)
func ContextWithSrcAddr(ctx context.Context, addr net.Addr) context.Context {
return context.WithValue(ctx, keySrcAddr, addr)
}
func SrcAddrFromContext(ctx context.Context) net.Addr {
v, _ := ctx.Value(keySrcAddr).(net.Addr)
return v
}
func ContextWithDstAddr(ctx context.Context, addr net.Addr) context.Context {
return context.WithValue(ctx, keyDstAddr, addr)
}
func DstAddrFromContext(ctx context.Context) net.Addr {
v, _ := ctx.Value(keyDstAddr).(net.Addr)
return v
}
type (
Sid string
// sidKey saves the session ID.
sidKey struct{}
)
func (s Sid) String() string {
return string(s)
}
var (
keySid sidKey
@@ -42,12 +79,13 @@ func SidFromContext(ctx context.Context) Sid {
return v
}
// hashKey saves the hash source for Selector.
type hashKey struct{}
type Hash struct {
Source string
}
type (
// hashKey saves the hash source for Selector.
hashKey struct{}
Hash struct {
Source string
}
)
var (
clientHashKey = &hashKey{}
@@ -64,8 +102,14 @@ func HashFromContext(ctx context.Context) *Hash {
return nil
}
type clientIDKey struct{}
type ClientID string
type (
ClientID string
clientIDKey struct{}
)
func (s ClientID) String() string {
return string(s)
}
var (
keyClientID = &clientIDKey{}
+2 -2
View File
@@ -1,6 +1,6 @@
module github.com/go-gost/x
go 1.23.1
go 1.24
toolchain go1.24.5
@@ -25,7 +25,7 @@ require (
github.com/mitchellh/go-homedir v1.1.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pion/dtls/v2 v2.2.6
github.com/pires/go-proxyproto v0.7.0
github.com/pires/go-proxyproto v0.8.1
github.com/prometheus/client_golang v1.19.1
github.com/quic-go/quic-go v0.53.0
github.com/quic-go/webtransport-go v0.9.0
+2
View File
@@ -162,6 +162,8 @@ github.com/pion/udp/v2 v2.0.1 h1:xP0z6WNux1zWEjhC7onRA3EwwSliXqu1ElUZAQhUP54=
github.com/pion/udp/v2 v2.0.1/go.mod h1:B7uvTMP00lzWdyMr/1PVZXtV3wpPIxBRd4Wl6AksXn8=
github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs=
github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4=
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+2 -6
View File
@@ -148,12 +148,8 @@ func (h *dnsHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr)
}
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
+7 -1
View File
@@ -10,6 +10,7 @@ import (
"github.com/go-gost/core/handler"
md "github.com/go-gost/core/metadata"
"github.com/go-gost/core/recorder"
ctxvalue "github.com/go-gost/x/ctx"
xrecorder "github.com/go-gost/x/recorder"
"github.com/go-gost/x/registry"
)
@@ -65,7 +66,13 @@ func (h *fileHandler) Init(md md.Metadata) (err error) {
}
func (h *fileHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error {
var clientAddr string
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
clientAddr = srcAddr.String()
}
h.options.Logger.WithFields(map[string]any{
"client": clientAddr,
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
}).Infof("%s - %s", conn.RemoteAddr(), conn.LocalAddr())
@@ -101,7 +108,6 @@ func (h *fileHandler) handleFunc(w http.ResponseWriter, r *http.Request) {
},
Time: start,
}
ro.ClientIP, _, _ = net.SplitHostPort(r.RemoteAddr)
log := h.options.Logger.WithFields(map[string]any{
"remote": r.RemoteAddr,
+21 -13
View File
@@ -16,6 +16,7 @@ import (
"github.com/go-gost/core/recorder"
ctxvalue "github.com/go-gost/x/ctx"
xnet "github.com/go-gost/x/internal/net"
"github.com/go-gost/x/internal/net/proxyproto"
"github.com/go-gost/x/internal/util/forwarder"
"github.com/go-gost/x/internal/util/sniffing"
tls_util "github.com/go-gost/x/internal/util/tls"
@@ -89,22 +90,16 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr)
} else {
ctx = ctxvalue.ContextWithClientAddr(ctx, ctxvalue.ClientAddr(conn.RemoteAddr().String()))
}
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"sid": ro.SID,
"client": ro.ClientIP,
"network": ro.Network,
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"sid": ro.SID,
"client": ro.ClientIP,
})
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
@@ -157,6 +152,13 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
var buf bytes.Buffer
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", address)
ro.Route = buf.String()
cc = proxyproto.WrapClientConn(
h.md.proxyProtocol,
ctxvalue.SrcAddrFromContext(ctx),
ctxvalue.DstAddrFromContext(ctx),
cc)
return cc, err
}
sniffer := &forwarder.Sniffer{
@@ -246,6 +248,12 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
}
defer cc.Close()
cc = proxyproto.WrapClientConn(
h.md.proxyProtocol,
ctxvalue.SrcAddrFromContext(ctx),
ctxvalue.DstAddrFromContext(ctx),
cc)
log = log.WithFields(map[string]any{"src": cc.LocalAddr().String(), "dst": cc.RemoteAddr().String()})
ro.Src = cc.LocalAddr().String()
ro.Dst = cc.RemoteAddr().String()
+2
View File
@@ -15,6 +15,7 @@ import (
type metadata struct {
readTimeout time.Duration
httpKeepalive bool
proxyProtocol int
sniffing bool
sniffingTimeout time.Duration
@@ -34,6 +35,7 @@ func (h *forwardHandler) parseMetadata(md mdata.Metadata) (err error) {
}
h.md.httpKeepalive = mdutil.GetBool(md, "http.keepalive")
h.md.proxyProtocol = mdutil.GetInt(md, "proxyProtocol")
h.md.sniffing = mdutil.GetBool(md, "sniffing")
h.md.sniffingTimeout = mdutil.GetDuration(md, "sniffing.timeout")
+14 -35
View File
@@ -6,7 +6,6 @@ import (
"context"
"errors"
"net"
"strconv"
"time"
"github.com/go-gost/core/chain"
@@ -91,15 +90,8 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr)
} else {
ctx = ctxvalue.ContextWithClientAddr(ctx, ctxvalue.ClientAddr(conn.RemoteAddr().String()))
}
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
@@ -166,6 +158,13 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
var buf bytes.Buffer
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", address)
ro.Route = buf.String()
cc = proxyproto.WrapClientConn(
h.md.proxyProtocol,
ctxvalue.SrcAddrFromContext(ctx),
ctxvalue.DstAddrFromContext(ctx),
cc)
return cc, err
}
sniffer := &forwarder.Sniffer{
@@ -260,7 +259,11 @@ func (h *forwardHandler) Handle(ctx context.Context, conn net.Conn, opts ...hand
ro.Src = cc.LocalAddr().String()
ro.Dst = cc.RemoteAddr().String()
cc = proxyproto.WrapClientConn(h.md.proxyProtocol, conn.RemoteAddr(), convertAddr(conn.LocalAddr()), cc)
cc = proxyproto.WrapClientConn(
h.md.proxyProtocol,
ctxvalue.SrcAddrFromContext(ctx),
ctxvalue.DstAddrFromContext(ctx),
cc)
t := time.Now()
log.Infof("%s <-> %s", conn.RemoteAddr(), target.Addr)
@@ -284,27 +287,3 @@ func (h *forwardHandler) checkRateLimit(addr net.Addr) bool {
return true
}
func convertAddr(addr net.Addr) net.Addr {
host, sp, _ := net.SplitHostPort(addr.String())
ip := net.ParseIP(host)
port, _ := strconv.Atoi(sp)
if ip == nil || ip.Equal(net.IPv6zero) {
ip = net.IPv4zero
}
switch addr.Network() {
case "tcp", "tcp4", "tcp6":
return &net.TCPAddr{
IP: ip,
Port: port,
}
default:
return &net.UDPAddr{
IP: ip,
Port: port,
}
}
}
+2 -17
View File
@@ -133,12 +133,8 @@ func (h *httpHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr)
}
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
@@ -516,16 +512,6 @@ func (h *httpHandler) proxyRoundTrip(ctx context.Context, rw io.ReadWriteCloser,
Header: req.Header.Clone(),
},
}
if clientIP := xhttp.GetClientIP(req); clientIP != nil {
ro.ClientIP = clientIP.String()
}
clientAddr := ro.RemoteAddr
if ro.ClientIP != "" {
if _, port, _ := net.SplitHostPort(ro.RemoteAddr); port != "" {
clientAddr = net.JoinHostPort(ro.ClientIP, port)
}
}
// HTTP/1.0
http10 := req.ProtoMajor == 1 && req.ProtoMinor == 0
@@ -579,7 +565,6 @@ func (h *httpHandler) proxyRoundTrip(ctx context.Context, rw io.ReadWriteCloser,
}
}
ctx = ctxvalue.ContextWithClientAddr(ctx, ctxvalue.ClientAddr(clientAddr))
ctx = ctx_internal.ContextWithRecorderObject(ctx, ro)
ctx = ctxvalue.ContextWithLogger(ctx, log)
+3 -1
View File
@@ -108,7 +108,9 @@ func (h *http2Handler) Handle(ctx context.Context, conn net.Conn, opts ...handle
Time: start,
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String())
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
"remote": conn.RemoteAddr().String(),
+4 -15
View File
@@ -15,15 +15,7 @@ type metadata struct {
}
func (h *http3Handler) parseMetadata(md mdata.Metadata) error {
const (
header = "header"
probeResistKey = "probeResistance"
probeResistKeyX = "probe_resist"
knock = "knock"
hash = "hash"
)
if m := mdutil.GetStringMapString(md, header); len(m) > 0 {
if m := mdutil.GetStringMapString(md, "header"); len(m) > 0 {
hd := http.Header{}
for k, v := range m {
hd.Add(k, v)
@@ -31,20 +23,17 @@ func (h *http3Handler) parseMetadata(md mdata.Metadata) error {
h.md.header = hd
}
pr := mdutil.GetString(md, probeResistKey)
if pr == "" {
pr = mdutil.GetString(md, probeResistKeyX)
}
pr := mdutil.GetString(md, "probeResistance", "probe_resist")
if pr != "" {
if ss := strings.SplitN(pr, ":", 2); len(ss) == 2 {
h.md.probeResistance = &probeResistance{
Type: ss[0],
Value: ss[1],
Knock: mdutil.GetString(md, knock),
Knock: mdutil.GetString(md, "knock"),
}
}
}
h.md.hash = mdutil.GetString(md, hash)
h.md.hash = mdutil.GetString(md, "hash")
return nil
}
+6 -2
View File
@@ -81,13 +81,17 @@ func (h *redirectHandler) Handle(ctx context.Context, conn net.Conn, opts ...han
Time: start,
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP, _, _ = net.SplitHostPort(conn.RemoteAddr().String())
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
"network": ro.Network,
"remote": conn.RemoteAddr().String(),
"local": conn.LocalAddr().String(),
"sid": ctxvalue.SidFromContext(ctx),
"network": ro.Network,
"client": ro.ClientIP,
})
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
+2 -6
View File
@@ -112,12 +112,8 @@ func (h *relayHandler) Handle(ctx context.Context, conn net.Conn, opts ...handle
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr)
}
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
+3 -6
View File
@@ -81,12 +81,8 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
SID: string(ctxvalue.SidFromContext(ctx)),
}
ro.ClientIP = conn.RemoteAddr().String()
if clientAddr := ctxvalue.ClientAddrFromContext(ctx); clientAddr != "" {
ro.ClientIP = string(clientAddr)
}
if h, _, _ := net.SplitHostPort(ro.ClientIP); h != "" {
ro.ClientIP = h
if srcAddr := ctxvalue.SrcAddrFromContext(ctx); srcAddr != nil {
ro.ClientIP = srcAddr.String()
}
log := h.options.Logger.WithFields(map[string]any{
@@ -131,6 +127,7 @@ func (h *sniHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.
var buf bytes.Buffer
cc, err := h.options.Router.Dial(ctxvalue.ContextWithBuffer(ctx, &buf), "tcp", address)
ro.Route = buf.String()
return cc, err
}
dialTLS := func(ctx context.Context, network, address string, cfg *tls.Config) (net.Conn, error) {
+6 -2
View File
@@ -26,8 +26,12 @@ type RemoteAddr interface {
RemoteAddr() net.Addr
}
type ClientAddr interface {
ClientAddr() net.Addr
type SrcAddr interface {
SrcAddr() net.Addr
}
type DstAddr interface {
DstAddr() net.Addr
}
// tcpraw.TCPConn
+3 -3
View File
@@ -69,13 +69,13 @@ func pipeBuffer(dst io.ReadWriteCloser, src io.ReadWriteCloser, bufferSize int)
if cw, ok := dst.(xio.CloseWrite); ok {
if e := cw.CloseWrite(); e == xio.ErrUnsupported {
dst.Close()
} else {
// Set TCP half-close timeout.
xio.SetReadDeadline(dst, time.Now().Add(tcpWaitTimeout))
}
} else {
dst.Close()
}
// Set TCP half-close timeout.
xio.SetReadDeadline(dst, time.Now().Add(tcpWaitTimeout))
return err
}
+59 -1
View File
@@ -2,6 +2,7 @@ package proxyproto
import (
"net"
"strconv"
xio "github.com/go-gost/x/internal/io"
proxyproto "github.com/pires/go-proxyproto"
@@ -11,6 +12,28 @@ type serverConn struct {
net.Conn
}
func (c *serverConn) RemoteAddr() net.Addr {
if conn, ok := c.Conn.(*proxyproto.Conn); ok {
return conn.Raw().RemoteAddr()
}
return c.Conn.RemoteAddr()
}
func (c *serverConn) LocalAddr() net.Addr {
if conn, ok := c.Conn.(*proxyproto.Conn); ok {
return conn.Raw().LocalAddr()
}
return c.Conn.LocalAddr()
}
func (c *serverConn) SrcAddr() net.Addr {
return c.Conn.RemoteAddr()
}
func (c *serverConn) DstAddr() net.Addr {
return c.Conn.LocalAddr()
}
func (c *serverConn) CloseRead() error {
if sc, ok := c.Conn.(xio.CloseRead); ok {
return sc.CloseRead()
@@ -36,7 +59,14 @@ func (c *serverConn) CloseWrite() error {
}
func WrapClientConn(ppv int, src, dst net.Addr, c net.Conn) net.Conn {
if ppv <= 0 {
if ppv <= 0 || c == nil {
return c
}
if src = convertAddr(src); src == nil {
return c
}
if dst = convertAddr(dst); dst == nil {
return c
}
@@ -44,3 +74,31 @@ func WrapClientConn(ppv int, src, dst net.Addr, c net.Conn) net.Conn {
header.WriteTo(c)
return c
}
func convertAddr(addr net.Addr) net.Addr {
if addr == nil {
return nil
}
host, sp, _ := net.SplitHostPort(addr.String())
ip := net.ParseIP(host)
port, _ := strconv.Atoi(sp)
if ip == nil || ip.Equal(net.IPv6zero) {
ip = net.IPv4zero
}
switch addr.Network() {
case "tcp", "tcp4", "tcp6":
return &net.TCPAddr{
IP: ip,
Port: port,
}
default:
return &net.UDPAddr{
IP: ip,
Port: port,
}
}
}
+26 -9
View File
@@ -5,6 +5,7 @@ import (
"sync"
"time"
xio "github.com/go-gost/x/internal/io"
xnet "github.com/go-gost/x/internal/net"
"github.com/gorilla/websocket"
)
@@ -13,14 +14,16 @@ type WebsocketConn interface {
net.Conn
WriteMessage(int, []byte) error
ReadMessage() (int, []byte, error)
xnet.ClientAddr
xnet.SrcAddr
xio.CloseRead
xio.CloseWrite
}
type websocketConn struct {
*websocket.Conn
rb []byte
clientAddr net.Addr
mux sync.Mutex
rb []byte
srcAddr net.Addr
mux sync.Mutex
}
func Conn(conn *websocket.Conn) WebsocketConn {
@@ -29,10 +32,10 @@ func Conn(conn *websocket.Conn) WebsocketConn {
}
}
func ConnWithClientAddr(conn *websocket.Conn, clientAddr net.Addr) WebsocketConn {
func ConnWithSrcAddr(conn *websocket.Conn, srcAddr net.Addr) WebsocketConn {
return &websocketConn{
Conn: conn,
clientAddr: clientAddr,
Conn: conn,
srcAddr: srcAddr,
}
}
@@ -77,6 +80,20 @@ func (c *websocketConn) SetWriteDeadline(t time.Time) error {
return c.Conn.SetWriteDeadline(t)
}
func (c *websocketConn) ClientAddr() net.Addr {
return c.clientAddr
func (c *websocketConn) SrcAddr() net.Addr {
return c.srcAddr
}
func (c *websocketConn) CloseRead() error {
if sc, ok := c.Conn.NetConn().(xio.CloseRead); ok {
return sc.CloseRead()
}
return xio.ErrUnsupported
}
func (c *websocketConn) CloseWrite() error {
if sc, ok := c.Conn.NetConn().(xio.CloseWrite); ok {
return sc.CloseWrite()
}
return xio.ErrUnsupported
}
+9 -9
View File
@@ -8,9 +8,9 @@ import (
)
type conn struct {
session *wt.Session
stream *wt.Stream
clientAddr net.Addr
session *wt.Session
stream *wt.Stream
srcAddr net.Addr
}
func Conn(session *wt.Session, stream *wt.Stream) net.Conn {
@@ -20,11 +20,11 @@ func Conn(session *wt.Session, stream *wt.Stream) net.Conn {
}
}
func ConnWithClientAddr(session *wt.Session, stream *wt.Stream, clientAddr net.Addr) net.Conn {
func ConnWithSrcAddr(session *wt.Session, stream *wt.Stream, srcAddr net.Addr) net.Conn {
return &conn{
session: session,
stream: stream,
clientAddr: clientAddr,
session: session,
stream: stream,
srcAddr: srcAddr,
}
}
@@ -48,8 +48,8 @@ func (c *conn) RemoteAddr() net.Addr {
return c.session.RemoteAddr()
}
func (c *conn) ClientAddr() net.Addr {
return c.clientAddr
func (c *conn) SrcAddr() net.Addr {
return c.srcAddr
}
func (c *conn) SetDeadline(t time.Time) error {
+10 -3
View File
@@ -107,9 +107,16 @@ func (c *limitConn) Metadata() metadata.Metadata {
return nil
}
func (c *limitConn) ClientAddr() net.Addr {
if sc, ok := c.Conn.(xnet.ClientAddr); ok {
return sc.ClientAddr()
func (c *limitConn) SrcAddr() net.Addr {
if sc, ok := c.Conn.(xnet.SrcAddr); ok {
return sc.SrcAddr()
}
return nil
}
func (c *limitConn) DstAddr() net.Addr {
if sc, ok := c.Conn.(xnet.DstAddr); ok {
return sc.DstAddr()
}
return nil
}
+7 -10
View File
@@ -3,7 +3,6 @@ package http2
import (
"errors"
"net"
"net/http"
"time"
mdata "github.com/go-gost/core/metadata"
@@ -11,13 +10,11 @@ import (
// a dummy HTTP2 server conn used by HTTP2 handler
type conn struct {
md mdata.Metadata
r *http.Request
w http.ResponseWriter
laddr net.Addr
raddr net.Addr
clientAddr net.Addr
closed chan struct{}
md mdata.Metadata
laddr net.Addr
raddr net.Addr
srcAddr net.Addr
closed chan struct{}
}
func (c *conn) Read(b []byte) (n int, err error) {
@@ -45,8 +42,8 @@ func (c *conn) RemoteAddr() net.Addr {
return c.raddr
}
func (c *conn) ClientAddr() net.Addr {
return c.clientAddr
func (c *conn) SrcAddr() net.Addr {
return c.srcAddr
}
func (c *conn) SetDeadline(t time.Time) error {
+3 -3
View File
@@ -14,7 +14,7 @@ type conn struct {
w io.Writer
remoteAddr net.Addr
localAddr net.Addr
clientAddr net.Addr
srcAddr net.Addr
closed chan struct{}
}
@@ -50,8 +50,8 @@ func (c *conn) RemoteAddr() net.Addr {
return c.remoteAddr
}
func (c *conn) ClientAddr() net.Addr {
return c.clientAddr
func (c *conn) SrcAddr() net.Addr {
return c.srcAddr
}
func (c *conn) SetDeadline(t time.Time) error {
+15 -6
View File
@@ -157,7 +157,17 @@ func (l *h2Listener) Close() (err error) {
}
func (l *h2Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
if l.logger.IsLevelEnabled(logger.TraceLevel) {
clientIP := xhttp.GetClientIP(r)
cip := ""
if clientIP != nil {
cip = clientIP.String()
}
log := l.logger.WithFields(map[string]any{
"local": l.addr.String(),
"remote": r.RemoteAddr,
"client": cip,
})
if log.IsLevelEnabled(logger.TraceLevel) {
dump, _ := httputil.DumpRequest(r, false)
l.logger.Trace(string(dump))
}
@@ -195,14 +205,13 @@ func (l *h2Listener) upgrade(w http.ResponseWriter, r *http.Request) (*conn, err
remoteAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
if remoteAddr == nil {
remoteAddr = &net.TCPAddr{
IP: net.IPv4zero,
Port: 0,
IP: net.IPv4zero,
}
}
var clientAddr net.Addr
var srcAddr net.Addr
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
clientAddr = &net.IPAddr{IP: clientIP}
srcAddr = &net.TCPAddr{IP: clientIP}
}
return &conn{
@@ -210,7 +219,7 @@ func (l *h2Listener) upgrade(w http.ResponseWriter, r *http.Request) (*conn, err
w: flushWriter{w},
localAddr: l.addr,
remoteAddr: remoteAddr,
clientAddr: clientAddr,
srcAddr: srcAddr,
closed: make(chan struct{}),
}, nil
}
+16 -8
View File
@@ -139,21 +139,29 @@ func (l *http2Listener) Close() (err error) {
}
func (l *http2Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
raddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
remoteAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
if remoteAddr == nil {
remoteAddr = &net.TCPAddr{
IP: net.IPv4zero,
}
}
var srcAddr net.Addr
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
srcAddr = &net.TCPAddr{IP: clientIP}
}
conn := &conn{
laddr: l.addr,
raddr: raddr,
closed: make(chan struct{}),
laddr: l.addr,
raddr: remoteAddr,
srcAddr: srcAddr,
closed: make(chan struct{}),
md: mdx.NewMetadata(map[string]any{
"r": r,
"w": w,
}),
}
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
conn.clientAddr = &net.IPAddr{IP: clientIP}
}
select {
case l.cqueue <- conn:
default:
+7 -7
View File
@@ -10,11 +10,11 @@ import (
// a dummy HTTP3 server conn used by HTTP3 handler
type conn struct {
md mdata.Metadata
laddr net.Addr
raddr net.Addr
clientAddr net.Addr
closed chan struct{}
md mdata.Metadata
laddr net.Addr
raddr net.Addr
srcAddr net.Addr
closed chan struct{}
}
func (c *conn) Read(b []byte) (n int, err error) {
@@ -42,8 +42,8 @@ func (c *conn) RemoteAddr() net.Addr {
return c.raddr
}
func (c *conn) ClientAddr() net.Addr {
return c.clientAddr
func (c *conn) SrcAddr() net.Addr {
return c.srcAddr
}
func (c *conn) SetDeadline(t time.Time) error {
+8 -3
View File
@@ -125,10 +125,15 @@ func (l *http3Listener) Close() (err error) {
}
func (l *http3Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
raddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
remoteAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr)
if remoteAddr == nil {
remoteAddr = &net.TCPAddr{
IP: net.IPv4zero,
}
}
conn := &conn{
laddr: l.addr,
raddr: raddr,
raddr: remoteAddr,
closed: make(chan struct{}),
md: mdx.NewMetadata(map[string]any{
"r": r,
@@ -137,7 +142,7 @@ func (l *http3Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
}
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
conn.clientAddr = &net.IPAddr{IP: clientIP}
conn.srcAddr = &net.UDPAddr{IP: clientIP}
}
select {
+5 -5
View File
@@ -176,15 +176,15 @@ func (l *wtListener) upgrade(w http.ResponseWriter, r *http.Request) {
return
}
var clientAddr net.Addr
var srcAddr net.Addr
if clientIP != nil {
clientAddr = &net.IPAddr{IP: clientIP}
srcAddr = &net.UDPAddr{IP: clientIP}
}
l.mux(s, clientAddr, log)
l.mux(s, srcAddr, log)
}
func (l *wtListener) mux(s *wt.Session, clientAddr net.Addr, log logger.Logger) (err error) {
func (l *wtListener) mux(s *wt.Session, srcAddr net.Addr, log logger.Logger) (err error) {
defer func() {
if err != nil {
s.CloseWithError(1, err.Error())
@@ -202,7 +202,7 @@ func (l *wtListener) mux(s *wt.Session, clientAddr net.Addr, log logger.Logger)
}
select {
case l.cqueue <- wt_util.ConnWithClientAddr(s, stream, clientAddr):
case l.cqueue <- wt_util.ConnWithSrcAddr(s, stream, srcAddr):
default:
stream.Close()
l.logger.Warnf("connection queue is full, stream %v discarded", stream.StreamID())
+9 -9
View File
@@ -184,15 +184,15 @@ func (l *mwsListener) upgrade(w http.ResponseWriter, r *http.Request) {
return
}
var clientAddr net.Addr
var srcAddr net.Addr
if clientIP != nil {
clientAddr = &net.IPAddr{IP: clientIP}
srcAddr = &net.TCPAddr{IP: clientIP}
}
l.mux(ws_util.Conn(conn), clientAddr, log)
l.mux(ws_util.Conn(conn), srcAddr, log)
}
func (l *mwsListener) mux(conn net.Conn, clientAddr net.Addr, log logger.Logger) {
func (l *mwsListener) mux(conn net.Conn, srcAddr net.Addr, log logger.Logger) {
defer conn.Close()
session, err := mux.ServerSession(conn, l.md.muxCfg)
@@ -210,7 +210,7 @@ func (l *mwsListener) mux(conn net.Conn, clientAddr net.Addr, log logger.Logger)
}
select {
case l.cqueue <- &connWithClientAddr{Conn: stream, clientAddr: clientAddr}:
case l.cqueue <- &connWithSrcAddr{Conn: stream, srcAddr: srcAddr}:
default:
stream.Close()
log.Warnf("connection queue is full, client %s discarded", stream.RemoteAddr())
@@ -218,11 +218,11 @@ func (l *mwsListener) mux(conn net.Conn, clientAddr net.Addr, log logger.Logger)
}
}
type connWithClientAddr struct {
type connWithSrcAddr struct {
net.Conn
clientAddr net.Addr
srcAddr net.Addr
}
func (c *connWithClientAddr) ClientAddr() net.Addr {
return c.clientAddr
func (c *connWithSrcAddr) SrcAddr() net.Addr {
return c.srcAddr
}
+3 -3
View File
@@ -179,13 +179,13 @@ func (l *wsListener) upgrade(w http.ResponseWriter, r *http.Request) {
return
}
var clientAddr net.Addr
var srcAddr net.Addr
if clientIP != nil {
clientAddr = &net.IPAddr{IP: clientIP}
srcAddr = &net.TCPAddr{IP: clientIP}
}
select {
case l.cqueue <- ws_util.ConnWithClientAddr(conn, clientAddr):
case l.cqueue <- ws_util.ConnWithSrcAddr(conn, srcAddr):
default:
conn.Close()
log.Warnf("connection queue is full, client %s discarded", conn.RemoteAddr())
+1 -1
View File
@@ -9,7 +9,7 @@ import (
type mapMetadata map[string]any
func NewMetadata(m map[string]any) metadata.Metadata {
if len(m) == 0 {
if m == nil {
return nil
}
md := make(map[string]any)
+10 -3
View File
@@ -81,9 +81,16 @@ func (c *serverConn) Metadata() metadata.Metadata {
return nil
}
func (c *serverConn) ClientAddr() net.Addr {
if sc, ok := c.Conn.(xnet.ClientAddr); ok {
return sc.ClientAddr()
func (c *serverConn) SrcAddr() net.Addr {
if sc, ok := c.Conn.(xnet.SrcAddr); ok {
return sc.SrcAddr()
}
return nil
}
func (c *serverConn) DstAddr() net.Addr {
if sc, ok := c.Conn.(xnet.DstAddr); ok {
return sc.DstAddr()
}
return nil
}
+10 -3
View File
@@ -83,9 +83,16 @@ func (c *conn) Metadata() metadata.Metadata {
return nil
}
func (c *conn) ClientAddr() net.Addr {
if sc, ok := c.Conn.(xnet.ClientAddr); ok {
return sc.ClientAddr()
func (c *conn) SrcAddr() net.Addr {
if sc, ok := c.Conn.(xnet.SrcAddr); ok {
return sc.SrcAddr()
}
return nil
}
func (c *conn) DstAddr() net.Addr {
if sc, ok := c.Conn.(xnet.DstAddr); ok {
return sc.DstAddr()
}
return nil
}
+27 -15
View File
@@ -206,26 +206,38 @@ func (s *defaultService) Serve() error {
s.setState(StateReady)
}
clientAddr := conn.RemoteAddr().String()
if ca, ok := conn.(xnet.ClientAddr); ok {
if addr := ca.ClientAddr(); addr != nil {
clientAddr = addr.String()
}
}
clientIP := clientAddr
if h, _, _ := net.SplitHostPort(clientAddr); h != "" {
clientIP = h
}
sid := xid.New().String()
ctx := ctxvalue.ContextWithSid(ctx, ctxvalue.Sid(sid))
ctx = ctxvalue.ContextWithClientAddr(ctx, ctxvalue.ClientAddr(clientAddr))
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: clientIP})
log := s.options.logger.WithFields(map[string]any{
"sid": sid,
})
srcAddr := conn.RemoteAddr()
if a, ok := conn.(xnet.SrcAddr); ok {
if addr := a.SrcAddr(); addr != nil {
srcAddr = addr
}
}
ctx = ctxvalue.ContextWithSrcAddr(ctx, srcAddr)
clientAddr := srcAddr.String()
ctx = ctxvalue.ContextWithClientAddr(ctx, ctxvalue.ClientAddr(clientAddr))
dstAddr := conn.LocalAddr()
if a, ok := conn.(xnet.DstAddr); ok {
if addr := a.DstAddr(); addr != nil {
dstAddr = addr
}
}
ctx = ctxvalue.ContextWithDstAddr(ctx, dstAddr)
clientIP := clientAddr
if h, _, _ := net.SplitHostPort(clientIP); h != "" {
clientIP = h
}
ctx = ctxvalue.ContextWithHash(ctx, &ctxvalue.Hash{Source: clientIP})
for _, rec := range s.options.recorders {
if rec.Record == recorder.RecorderServiceClientAddress {
if err := rec.Recorder.Record(ctx, []byte(clientIP)); err != nil {
@@ -235,9 +247,9 @@ func (s *defaultService) Serve() error {
}
}
if s.options.admission != nil &&
!s.options.admission.Admit(ctx, clientAddr) {
!s.options.admission.Admit(ctx, srcAddr.String()) {
conn.Close()
log.Debugf("admission: %s is denied", clientAddr)
log.Debugf("admission: %s is denied", srcAddr)
continue
}