add interface xnet.SrcAddr/DstAddr
This commit is contained in:
@@ -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
@@ -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
@@ -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
@@ -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{}
|
||||
|
||||
@@ -508,7 +508,9 @@ type ChainGroupConfig struct {
|
||||
|
||||
type HopConfig struct {
|
||||
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"`
|
||||
@@ -534,8 +536,11 @@ type NodeConfig struct {
|
||||
Hosts string `yaml:",omitempty" json:"hosts,omitempty"`
|
||||
Connector *ConnectorConfig `yaml:",omitempty" json:"connector,omitempty"`
|
||||
Dialer *DialerConfig `yaml:",omitempty" json:"dialer,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"`
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
|
||||
@@ -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{}
|
||||
|
||||
@@ -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{}
|
||||
|
||||
+56
-12
@@ -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
|
||||
}
|
||||
|
||||
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.
|
||||
type sidKey struct{}
|
||||
type Sid string
|
||||
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
|
||||
}
|
||||
|
||||
type (
|
||||
// hashKey saves the hash source for Selector.
|
||||
type hashKey struct{}
|
||||
|
||||
type Hash struct {
|
||||
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{}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,18 +90,12 @@ 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{
|
||||
"network": ro.Network,
|
||||
"remote": conn.RemoteAddr().String(),
|
||||
"local": conn.LocalAddr().String(),
|
||||
"sid": ro.SID,
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+23
-6
@@ -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,13 +14,15 @@ 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
|
||||
srcAddr net.Addr
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
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
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
type conn struct {
|
||||
session *wt.Session
|
||||
stream *wt.Stream
|
||||
clientAddr net.Addr
|
||||
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,
|
||||
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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package http2
|
||||
import (
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
mdata "github.com/go-gost/core/metadata"
|
||||
@@ -12,11 +11,9 @@ 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
|
||||
srcAddr net.Addr
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -196,13 +206,12 @@ func (l *h2Listener) upgrade(w http.ResponseWriter, r *http.Request) (*conn, err
|
||||
if remoteAddr == nil {
|
||||
remoteAddr = &net.TCPAddr{
|
||||
IP: net.IPv4zero,
|
||||
Port: 0,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -139,10 +139,22 @@ 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,
|
||||
raddr: remoteAddr,
|
||||
srcAddr: srcAddr,
|
||||
closed: make(chan struct{}),
|
||||
md: mdx.NewMetadata(map[string]any{
|
||||
"r": r,
|
||||
@@ -150,10 +162,6 @@ func (l *http2Listener) handleFunc(w http.ResponseWriter, r *http.Request) {
|
||||
}),
|
||||
}
|
||||
|
||||
if clientIP := xhttp.GetClientIP(r); clientIP != nil {
|
||||
conn.clientAddr = &net.IPAddr{IP: clientIP}
|
||||
}
|
||||
|
||||
select {
|
||||
case l.cqueue <- conn:
|
||||
default:
|
||||
|
||||
@@ -13,7 +13,7 @@ type conn struct {
|
||||
md mdata.Metadata
|
||||
laddr net.Addr
|
||||
raddr net.Addr
|
||||
clientAddr net.Addr
|
||||
srcAddr net.Addr
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user