diff --git a/common/dialer/default.go b/common/dialer/default.go index 3ef22da9..8deba164 100644 --- a/common/dialer/default.go +++ b/common/dialer/default.go @@ -10,6 +10,7 @@ import ( "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/conntrack" + "github.com/sagernet/sing-box/common/listener" C "github.com/sagernet/sing-box/constant" "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/option" @@ -35,6 +36,7 @@ type DefaultDialer struct { udpListener net.ListenConfig udpAddr4 string udpAddr6 string + netns string networkManager adapter.NetworkManager networkStrategy *C.NetworkStrategy defaultNetworkStrategy bool @@ -198,6 +200,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial udpListener: listener, udpAddr4: udpAddr4, udpAddr6: udpAddr6, + netns: options.NetNs, networkManager: networkManager, networkStrategy: networkStrategy, defaultNetworkStrategy: defaultNetworkStrategy, @@ -214,19 +217,21 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address return nil, E.New("domain not resolved") } if d.networkStrategy == nil { - switch N.NetworkName(network) { - case N.NetworkUDP: - if !address.IsIPv6() { - return trackConn(d.udpDialer4.DialContext(ctx, network, address.String())) - } else { - return trackConn(d.udpDialer6.DialContext(ctx, network, address.String())) + return trackConn(listener.ListenNetworkNamespace[net.Conn](d.netns, func() (net.Conn, error) { + switch N.NetworkName(network) { + case N.NetworkUDP: + if !address.IsIPv6() { + return d.udpDialer4.DialContext(ctx, network, address.String()) + } else { + return d.udpDialer6.DialContext(ctx, network, address.String()) + } } - } - if !address.IsIPv6() { - return trackConn(DialSlowContext(&d.dialer4, ctx, network, address)) - } else { - return trackConn(DialSlowContext(&d.dialer6, ctx, network, address)) - } + if !address.IsIPv6() { + return DialSlowContext(&d.dialer4, ctx, network, address) + } else { + return DialSlowContext(&d.dialer6, ctx, network, address) + } + })) } else { return d.DialParallelInterface(ctx, network, address, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay) } @@ -282,13 +287,15 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { if d.networkStrategy == nil { - if destination.IsIPv6() { - return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6)) - } else if destination.IsIPv4() && !destination.Addr.IsUnspecified() { - return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP+"4", d.udpAddr4)) - } else { - return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4)) - } + return trackPacketConn(listener.ListenNetworkNamespace[net.PacketConn](d.netns, func() (net.PacketConn, error) { + if destination.IsIPv6() { + return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6) + } else if destination.IsIPv4() && !destination.Addr.IsUnspecified() { + return d.udpListener.ListenPacket(ctx, N.NetworkUDP+"4", d.udpAddr4) + } else { + return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4) + } + })) } else { return d.ListenSerialInterfacePacket(ctx, destination, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay) } diff --git a/common/listener/listener.go b/common/listener/listener.go index 289f15c5..8a4cad34 100644 --- a/common/listener/listener.go +++ b/common/listener/listener.go @@ -4,6 +4,8 @@ import ( "context" "net" "net/netip" + "runtime" + "strings" "sync/atomic" "github.com/sagernet/sing-box/adapter" @@ -14,6 +16,8 @@ import ( "github.com/sagernet/sing/common/logger" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" + + "github.com/vishvananda/netns" ) type Listener struct { @@ -135,3 +139,30 @@ func (l *Listener) UDPConn() *net.UDPConn { func (l *Listener) ListenOptions() option.ListenOptions { return l.listenOptions } + +func ListenNetworkNamespace[T any](nameOrPath string, block func() (T, error)) (T, error) { + if nameOrPath != "" { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + currentNs, err := netns.Get() + if err != nil { + return common.DefaultValue[T](), E.Cause(err, "get current netns") + } + defer netns.Set(currentNs) + var targetNs netns.NsHandle + if strings.HasPrefix(nameOrPath, "/") { + targetNs, err = netns.GetFromPath(nameOrPath) + } else { + targetNs, err = netns.GetFromName(nameOrPath) + } + if err != nil { + return common.DefaultValue[T](), E.Cause(err, "get netns ", nameOrPath) + } + defer targetNs.Close() + err = netns.Set(targetNs) + if err != nil { + return common.DefaultValue[T](), E.Cause(err, "set netns to ", nameOrPath) + } + } + return block() +} diff --git a/common/listener/listener_tcp.go b/common/listener/listener_tcp.go index 646d4017..c5995fad 100644 --- a/common/listener/listener_tcp.go +++ b/common/listener/listener_tcp.go @@ -16,9 +16,12 @@ import ( ) func (l *Listener) ListenTCP() (net.Listener, error) { + //nolint:staticcheck + if l.listenOptions.ProxyProtocol || l.listenOptions.ProxyProtocolAcceptNoHeader { + return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0") + } var err error bindAddr := M.SocksaddrFrom(l.listenOptions.Listen.Build(netip.AddrFrom4([4]byte{127, 0, 0, 1})), l.listenOptions.ListenPort) - var tcpListener net.Listener var listenConfig net.ListenConfig if l.listenOptions.TCPKeepAlive >= 0 { keepIdle := time.Duration(l.listenOptions.TCPKeepAlive) @@ -37,20 +40,19 @@ func (l *Listener) ListenTCP() (net.Listener, error) { } setMultiPathTCP(&listenConfig) } - if l.listenOptions.TCPFastOpen { - var tfoConfig tfo.ListenConfig - tfoConfig.ListenConfig = listenConfig - tcpListener, err = tfoConfig.Listen(l.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) - } else { - tcpListener, err = listenConfig.Listen(l.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) - } - if err == nil { - l.logger.Info("tcp server started at ", tcpListener.Addr()) - } - //nolint:staticcheck - if l.listenOptions.ProxyProtocol || l.listenOptions.ProxyProtocolAcceptNoHeader { - return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0") + tcpListener, err := ListenNetworkNamespace[net.Listener](l.listenOptions.NetNs, func() (net.Listener, error) { + if l.listenOptions.TCPFastOpen { + var tfoConfig tfo.ListenConfig + tfoConfig.ListenConfig = listenConfig + return tfoConfig.Listen(l.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) + } else { + return listenConfig.Listen(l.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) + } + }) + if err != nil { + return nil, err } + l.logger.Info("tcp server started at ", tcpListener.Addr()) l.tcpListener = tcpListener return tcpListener, err } diff --git a/common/listener/listener_udp.go b/common/listener/listener_udp.go index 10d6dc38..d8b117a3 100644 --- a/common/listener/listener_udp.go +++ b/common/listener/listener_udp.go @@ -1,6 +1,7 @@ package listener import ( + "context" "net" "net/netip" "os" @@ -24,7 +25,9 @@ func (l *Listener) ListenUDP() (net.PacketConn, error) { if !udpFragment { lc.Control = control.Append(lc.Control, control.DisableUDPFragment()) } - udpConn, err := lc.ListenPacket(l.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String()) + udpConn, err := ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) { + return lc.ListenPacket(l.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String()) + }) if err != nil { return nil, err } @@ -34,6 +37,12 @@ func (l *Listener) ListenUDP() (net.PacketConn, error) { return udpConn, err } +func (l *Listener) ListenPacket(listenConfig net.ListenConfig, ctx context.Context, network string, address string) (net.PacketConn, error) { + return ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) { + return listenConfig.ListenPacket(ctx, network, address) + }) +} + func (l *Listener) UDPAddr() M.Socksaddr { return l.udpAddr } diff --git a/docs/configuration/shared/dial.md b/docs/configuration/shared/dial.md index 7f0bf251..f7507531 100644 --- a/docs/configuration/shared/dial.md +++ b/docs/configuration/shared/dial.md @@ -5,7 +5,8 @@ icon: material/new-box !!! quote "Changes in sing-box 1.12.0" :material-plus: [domain_resolver](#domain_resolver) - :material-delete-clock: [domain_strategy](#domain_strategy) + :material-delete-clock: [domain_strategy](#domain_strategy) + :material-plus: [netns](#netns) !!! quote "Changes in sing-box 1.11.0" @@ -18,24 +19,25 @@ icon: material/new-box ```json { - "detour": "upstream-out", - "bind_interface": "en0", - "inet4_bind_address": "0.0.0.0", - "inet6_bind_address": "::", - "routing_mark": 1234, + "detour": "", + "bind_interface": "", + "inet4_bind_address": "", + "inet6_bind_address": "", + "routing_mark": 0, "reuse_addr": false, - "connect_timeout": "5s", + "connect_timeout": "", "tcp_fast_open": false, "tcp_multi_path": false, "udp_fragment": false, + "netns": "", "domain_resolver": "", // or {} - "network_strategy": "default", + "network_strategy": "", "network_type": [], "fallback_network_type": [], - "fallback_delay": "300ms", + "fallback_delay": "", // Deprecated - "domain_strategy": "prefer_ipv6" + "domain_strategy": "" } ``` @@ -75,6 +77,15 @@ Set netfilter routing mark. Reuse listener address. +#### connect_timeout + +Connect timeout, in golang's Duration format. + +A duration string is a possibly signed sequence of +decimal numbers, each with optional fraction and a unit suffix, +such as "300ms", "-1.5h" or "2h45m". +Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". + #### tcp_fast_open Enable TCP Fast Open. @@ -91,14 +102,15 @@ Enable TCP Multi Path. Enable UDP fragmentation. -#### connect_timeout +#### netns -Connect timeout, in golang's Duration format. +!!! question "Since sing-box 1.12.0" -A duration string is a possibly signed sequence of -decimal numbers, each with optional fraction and a unit suffix, -such as "300ms", "-1.5h" or "2h45m". -Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". +!!! quote "" + + Only supported on Linux. + +Set network namespace, name or path. #### domain_resolver diff --git a/docs/configuration/shared/dial.zh.md b/docs/configuration/shared/dial.zh.md index 4a7d9562..5abd6ad9 100644 --- a/docs/configuration/shared/dial.zh.md +++ b/docs/configuration/shared/dial.zh.md @@ -5,7 +5,8 @@ icon: material/new-box !!! quote "sing-box 1.12.0 中的更改" :material-plus: [domain_resolver](#domain_resolver) - :material-delete-clock: [domain_strategy](#domain_strategy) + :material-delete-clock: [domain_strategy](#domain_strategy) + :material-plus: [netns](#netns) !!! quote "sing-box 1.11.0 中的更改" @@ -18,25 +19,26 @@ icon: material/new-box ```json { - "detour": "upstream-out", - "bind_interface": "en0", - "inet4_bind_address": "0.0.0.0", - "inet6_bind_address": "::", - "routing_mark": 1234, + "detour": "", + "bind_interface": "", + "inet4_bind_address": "", + "inet6_bind_address": "", + "routing_mark": 0, "reuse_addr": false, - "connect_timeout": "5s", + "connect_timeout": "", "tcp_fast_open": false, "tcp_multi_path": false, "udp_fragment": false, + "netns": "", "domain_resolver": "", // 或 {} "network_strategy": "", "network_type": [], "fallback_network_type": [], - "fallback_delay": "300ms", + "fallback_delay": "", // 废弃的 - "domain_strategy": "prefer_ipv6" + "domain_strategy": "" } ``` @@ -76,6 +78,13 @@ icon: material/new-box 重用监听地址。 +#### connect_timeout + +连接超时,采用 golang 的 Duration 格式。 + +持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。 +有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。 + #### tcp_fast_open 启用 TCP Fast Open。 @@ -92,12 +101,15 @@ icon: material/new-box 启用 UDP 分段。 -#### connect_timeout +#### netns -连接超时,采用 golang 的 Duration 格式。 +!!! question "自 sing-box 1.12.0 起" -持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。 -有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。 +!!! quote "" + + 仅支持 Linux。 + +设置网络命名空间,名称或路径。 #### domain_resolver diff --git a/docs/configuration/shared/listen.md b/docs/configuration/shared/listen.md index 3e1b000f..ab6d07ce 100644 --- a/docs/configuration/shared/listen.md +++ b/docs/configuration/shared/listen.md @@ -1,7 +1,11 @@ --- -icon: material/delete-clock +icon: material/new-box --- +!!! quote "Changes in sing-box 1.12.0" + + :material-plus: [netns](#netns) + !!! quote "Changes in sing-box 1.11.0" :material-delete-clock: [sniff](#sniff) @@ -14,17 +18,18 @@ icon: material/delete-clock ```json { - "listen": "::", - "listen_port": 5353, + "listen": "", + "listen_port": 0, "tcp_fast_open": false, "tcp_multi_path": false, "udp_fragment": false, - "udp_timeout": "5m", - "detour": "another-in", + "udp_timeout": "", + "netns": "", + "detour": "", "sniff": false, "sniff_override_destination": false, - "sniff_timeout": "300ms", - "domain_strategy": "prefer_ipv6", + "sniff_timeout": "", + "domain_strategy": "", "udp_disable_domain_unmapping": false } ``` @@ -72,6 +77,16 @@ UDP NAT expiration time. `5m` will be used by default. +#### netns + +!!! question "Since sing-box 1.12.0" + +!!! quote "" + + Only supported on Linux. + +Set network namespace, name or path. + #### detour If set, connections will be forwarded to the specified inbound. diff --git a/docs/configuration/shared/listen.zh.md b/docs/configuration/shared/listen.zh.md index 4f8ca9d6..bc67ac98 100644 --- a/docs/configuration/shared/listen.zh.md +++ b/docs/configuration/shared/listen.zh.md @@ -1,7 +1,11 @@ --- -icon: material/delete-clock +icon: material/new-box --- +!!! quote "Changes in sing-box 1.12.0" + + :material-plus: [netns](#netns) + !!! quote "sing-box 1.11.0 中的更改" :material-delete-clock: [sniff](#sniff) @@ -14,17 +18,18 @@ icon: material/delete-clock ```json { - "listen": "::", - "listen_port": 5353, + "listen": "", + "listen_port": 0, "tcp_fast_open": false, "tcp_multi_path": false, "udp_fragment": false, - "udp_timeout": "5m", - "detour": "another-in", + "udp_timeout": "", + "netns": "", + "detour": "", "sniff": false, "sniff_override_destination": false, - "sniff_timeout": "300ms", - "domain_strategy": "prefer_ipv6", + "sniff_timeout": "", + "domain_strategy": "", "udp_disable_domain_unmapping": false } ``` @@ -73,6 +78,16 @@ UDP NAT 过期时间。 默认使用 `5m`。 +#### netns + +!!! question "自 sing-box 1.12.0 起" + +!!! quote "" + + 仅支持 Linux。 + +设置网络命名空间,名称或路径。 + #### detour 如果设置,连接将被转发到指定的入站。 diff --git a/go.mod b/go.mod index bb9fe336..9e223edf 100644 --- a/go.mod +++ b/go.mod @@ -41,6 +41,7 @@ require ( github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 + github.com/vishvananda/netns v0.0.4 go.uber.org/zap v1.27.0 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba golang.org/x/crypto v0.33.0 @@ -122,7 +123,6 @@ require ( github.com/tailscale/peercred v0.0.0-20250107143737-35a0c7bd7edc // indirect github.com/tailscale/web-client-prebuilt v0.0.0-20250124233751-d4cd19a26976 // indirect github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect - github.com/vishvananda/netns v0.0.4 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/blake3 v0.2.4 // indirect go.uber.org/multierr v1.11.0 // indirect diff --git a/option/inbound.go b/option/inbound.go index 1cf16ff6..b704c7e3 100644 --- a/option/inbound.go +++ b/option/inbound.go @@ -68,6 +68,7 @@ type ListenOptions struct { UDPFragment *bool `json:"udp_fragment,omitempty"` UDPFragmentDefault bool `json:"-"` UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"` + NetNs string `json:"netns,omitempty"` // Deprecated: removed ProxyProtocol bool `json:"proxy_protocol,omitempty"` diff --git a/option/outbound.go b/option/outbound.go index 4abc597c..1b852d26 100644 --- a/option/outbound.go +++ b/option/outbound.go @@ -77,6 +77,7 @@ type DialerOptions struct { TCPMultiPath bool `json:"tcp_multi_path,omitempty"` UDPFragment *bool `json:"udp_fragment,omitempty"` UDPFragmentDefault bool `json:"-"` + NetNs string `json:"netns,omitempty"` DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"` NetworkStrategy *NetworkStrategy `json:"network_strategy,omitempty"` NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"` diff --git a/option/simple.go b/option/simple.go index 5fda30ef..f244ba18 100644 --- a/option/simple.go +++ b/option/simple.go @@ -7,13 +7,15 @@ import ( type SocksInboundOptions struct { ListenOptions - Users []auth.User `json:"users,omitempty"` + Users []auth.User `json:"users,omitempty"` + DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"` } type HTTPMixedInboundOptions struct { ListenOptions - Users []auth.User `json:"users,omitempty"` - SetSystemProxy bool `json:"set_system_proxy,omitempty"` + Users []auth.User `json:"users,omitempty"` + DomainResolver *DomainResolveOptions `json:"domain_resolver,omitempty"` + SetSystemProxy bool `json:"set_system_proxy,omitempty"` InboundTLSOptionsContainer } diff --git a/protocol/mixed/inbound.go b/protocol/mixed/inbound.go index b675a536..fe84aa01 100644 --- a/protocol/mixed/inbound.go +++ b/protocol/mixed/inbound.go @@ -85,7 +85,7 @@ func (h *Inbound) newConnection(ctx context.Context, conn net.Conn, metadata ada } switch headerBytes[0] { case socks4.Version, socks5.Version: - return socks.HandleConnectionEx(ctx, conn, reader, h.authenticator, adapter.NewUpstreamHandlerEx(metadata, h.newUserConnection, h.streamUserPacketConnection), metadata.Source, onClose) + return socks.HandleConnectionEx(ctx, conn, reader, h.authenticator, adapter.NewUpstreamHandlerEx(metadata, h.newUserConnection, h.streamUserPacketConnection), h.listener, metadata.Source, onClose) default: return http.HandleConnectionEx(ctx, conn, reader, h.authenticator, adapter.NewUpstreamHandlerEx(metadata, h.newUserConnection, h.streamUserPacketConnection), metadata.Source, onClose) } diff --git a/protocol/redirect/tproxy.go b/protocol/redirect/tproxy.go index 7860e173..f9a455e1 100644 --- a/protocol/redirect/tproxy.go +++ b/protocol/redirect/tproxy.go @@ -121,40 +121,48 @@ func (t *TProxy) NewPacketEx(buffer *buf.Buffer, oob []byte, source M.Socksaddr) t.udpNat.NewPacket([][]byte{buffer.Bytes()}, source, M.SocksaddrFromNetIP(destination), nil) } -type tproxyPacketWriter struct { - ctx context.Context - source netip.AddrPort - destination M.Socksaddr - conn *net.UDPConn -} - func (t *TProxy) preparePacketConnection(source M.Socksaddr, destination M.Socksaddr, userData any) (bool, context.Context, N.PacketWriter, N.CloseHandlerFunc) { ctx := log.ContextWithNewID(t.ctx) - writer := &tproxyPacketWriter{ctx: ctx, source: source.AddrPort(), destination: destination} + writer := &tproxyPacketWriter{ + ctx: ctx, + listener: t.listener, + source: source.AddrPort(), + destination: destination, + } return true, ctx, writer, func(it error) { common.Close(common.PtrOrNil(writer.conn)) } } +type tproxyPacketWriter struct { + ctx context.Context + listener *listener.Listener + source netip.AddrPort + destination M.Socksaddr + conn *net.UDPConn +} + func (w *tproxyPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { defer buffer.Release() - conn := w.conn - if w.destination == destination && conn != nil { - _, err := conn.WriteToUDPAddrPort(buffer.Bytes(), w.source) - if err != nil { - w.conn = nil + if w.listener.ListenOptions().NetNs == "" { + conn := w.conn + if w.destination == destination && conn != nil { + _, err := conn.WriteToUDPAddrPort(buffer.Bytes(), w.source) + if err != nil { + w.conn = nil + } + return err } - return err } - var listener net.ListenConfig - listener.Control = control.Append(listener.Control, control.ReuseAddr()) - listener.Control = control.Append(listener.Control, redir.TProxyWriteBack()) - packetConn, err := listener.ListenPacket(w.ctx, "udp", destination.String()) + var listenConfig net.ListenConfig + listenConfig.Control = control.Append(listenConfig.Control, control.ReuseAddr()) + listenConfig.Control = control.Append(listenConfig.Control, redir.TProxyWriteBack()) + packetConn, err := w.listener.ListenPacket(listenConfig, w.ctx, "udp", destination.String()) if err != nil { return err } udpConn := packetConn.(*net.UDPConn) - if w.destination == destination { + if w.listener.ListenOptions().NetNs == "" && w.destination == destination { w.conn = udpConn } else { defer udpConn.Close() diff --git a/protocol/socks/inbound.go b/protocol/socks/inbound.go index 820c7bbb..6b828152 100644 --- a/protocol/socks/inbound.go +++ b/protocol/socks/inbound.go @@ -62,7 +62,7 @@ func (h *Inbound) Close() error { } func (h *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) { - err := socks.HandleConnectionEx(ctx, conn, std_bufio.NewReader(conn), h.authenticator, adapter.NewUpstreamHandlerEx(metadata, h.newUserConnection, h.streamUserPacketConnection), metadata.Source, onClose) + err := socks.HandleConnectionEx(ctx, conn, std_bufio.NewReader(conn), h.authenticator, adapter.NewUpstreamHandlerEx(metadata, h.newUserConnection, h.streamUserPacketConnection), h.listener, metadata.Source, onClose) N.CloseOnHandshakeFailure(conn, onClose, err) if err != nil { if E.IsClosedOrCanceled(err) { diff --git a/protocol/tor/proxy.go b/protocol/tor/proxy.go index feab7971..6b7db7c3 100644 --- a/protocol/tor/proxy.go +++ b/protocol/tor/proxy.go @@ -99,7 +99,7 @@ func (l *ProxyListener) acceptLoop() { } func (l *ProxyListener) accept(ctx context.Context, conn *net.TCPConn) error { - return socks.HandleConnectionEx(ctx, conn, std_bufio.NewReader(conn), l.authenticator, l, M.SocksaddrFromNet(conn.RemoteAddr()), nil) + return socks.HandleConnectionEx(ctx, conn, std_bufio.NewReader(conn), l.authenticator, l, nil, M.SocksaddrFromNet(conn.RemoteAddr()), nil) } func (l *ProxyListener) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {