diff --git a/common/dialer/default.go b/common/dialer/default.go index f4148f36..4bf51997 100644 --- a/common/dialer/default.go +++ b/common/dialer/default.go @@ -13,12 +13,11 @@ import ( E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/tfo-go" ) type DefaultDialer struct { - dialer4 tfo.Dialer - dialer6 tfo.Dialer + dialer4 tcpDialer + dialer6 tcpDialer udpDialer4 net.Dialer udpDialer6 net.Dialer udpListener net.ListenConfig @@ -94,14 +93,22 @@ func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDi udpAddr6 = M.SocksaddrFrom(bindAddr, 0).String() } if options.TCPMultiPath { - if !multipathTCPAvailable { + if !go121Available { return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.") } setMultiPathTCP(&dialer4) } + tcpDialer4, err := newTCPDialer(dialer4, options.TCPFastOpen) + if err != nil { + return nil, err + } + tcpDialer6, err := newTCPDialer(dialer6, options.TCPFastOpen) + if err != nil { + return nil, err + } return &DefaultDialer{ - tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen}, - tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen}, + tcpDialer4, + tcpDialer6, udpDialer4, udpDialer6, listener, diff --git a/common/dialer/default_go1.20.go b/common/dialer/default_go1.20.go new file mode 100644 index 00000000..8c3507c2 --- /dev/null +++ b/common/dialer/default_go1.20.go @@ -0,0 +1,15 @@ +//go:build go1.20 + +package dialer + +import ( + "net" + + "github.com/sagernet/tfo-go" +) + +type tcpDialer = tfo.Dialer + +func newTCPDialer(dialer net.Dialer, tfoEnabled bool) (tcpDialer, error) { + return tfo.Dialer{Dialer: dialer, DisableTFO: !tfoEnabled}, nil +} diff --git a/common/dialer/default_go1.21.go b/common/dialer/default_go1.21.go index 360826c8..6ecb5b25 100644 --- a/common/dialer/default_go1.21.go +++ b/common/dialer/default_go1.21.go @@ -4,7 +4,7 @@ package dialer import "net" -const multipathTCPAvailable = true +const go121Available = true func setMultiPathTCP(dialer *net.Dialer) { dialer.SetMultipathTCP(true) diff --git a/common/dialer/default_nongo1.20.go b/common/dialer/default_nongo1.20.go new file mode 100644 index 00000000..21502424 --- /dev/null +++ b/common/dialer/default_nongo1.20.go @@ -0,0 +1,18 @@ +//go:build !go1.20 + +package dialer + +import ( + "net" + + E "github.com/sagernet/sing/common/exceptions" +) + +type tcpDialer = net.Dialer + +func newTCPDialer(dialer net.Dialer, tfoEnabled bool) (tcpDialer, error) { + if tfoEnabled { + return dialer, E.New("TCP Fast Open requires go1.20, please recompile your binary.") + } + return dialer, nil +} diff --git a/common/dialer/default_nongo1.21.go b/common/dialer/default_nongo1.21.go index 6e564673..386d50dd 100644 --- a/common/dialer/default_nongo1.21.go +++ b/common/dialer/default_nongo1.21.go @@ -6,7 +6,7 @@ import ( "net" ) -const multipathTCPAvailable = false +const go121Available = false func setMultiPathTCP(dialer *net.Dialer) { } diff --git a/common/dialer/tfo.go b/common/dialer/tfo.go index 0d4646cf..2e3eb9b3 100644 --- a/common/dialer/tfo.go +++ b/common/dialer/tfo.go @@ -1,3 +1,5 @@ +//go:build go1.20 + package dialer import ( @@ -25,7 +27,7 @@ type slowOpenConn struct { err error } -func DialSlowContext(dialer *tfo.Dialer, ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { +func DialSlowContext(dialer *tcpDialer, ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { if dialer.DisableTFO || N.NetworkName(network) != N.NetworkTCP { switch N.NetworkName(network) { case N.NetworkTCP, N.NetworkUDP: @@ -61,6 +63,7 @@ func (c *slowOpenConn) Write(b []byte) (n int, err error) { if c.conn == nil { c.conn, err = c.dialer.DialContext(c.ctx, c.network, c.destination.String(), b) if err != nil { + c.conn = nil c.err = E.Cause(err, "dial tcp fast open") } close(c.create) diff --git a/common/dialer/tfo_stub.go b/common/dialer/tfo_stub.go new file mode 100644 index 00000000..144902e5 --- /dev/null +++ b/common/dialer/tfo_stub.go @@ -0,0 +1,20 @@ +//go:build !go1.20 + +package dialer + +import ( + "context" + "net" + + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" +) + +func DialSlowContext(dialer *tcpDialer, ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { + switch N.NetworkName(network) { + case N.NetworkTCP, N.NetworkUDP: + return dialer.DialContext(ctx, network, destination.String()) + default: + return dialer.DialContext(ctx, network, destination.AddrString()) + } +} diff --git a/go.mod b/go.mod index 3c76de0f..eaab69da 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/sagernet/sing-box -go 1.18 +go 1.20 require ( berty.tech/go-libtor v1.0.385 @@ -34,7 +34,7 @@ require ( github.com/sagernet/sing-tun v0.1.12-0.20230812113806-10d98f26797a github.com/sagernet/sing-vmess v0.1.7 github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 - github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 + github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f diff --git a/go.sum b/go.sum index b4b1b389..136624bd 100644 --- a/go.sum +++ b/go.sum @@ -131,8 +131,8 @@ github.com/sagernet/sing-vmess v0.1.7 h1:TM8FFLsXmlXH9XT8/oDgc6PC5BOzrg6OzyEe01i github.com/sagernet/sing-vmess v0.1.7/go.mod h1:1qkC1L1T2sxnS/NuO6HU72S8TkltV+EXoKGR29m/Yss= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= -github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE= -github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9/go.mod h1:FUyTEc5ye5NjKnDTDMuiLF2M6T4BE6y6KZuax//UCEg= +github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 h1:Px+hN4Vzgx+iCGVnWH5A8eR7JhNnIV3rGQmBxA7cw6Q= +github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M= github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4= github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM= github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs= diff --git a/inbound/default_tcp.go b/inbound/default_tcp.go index 8de81ba4..ef01bfac 100644 --- a/inbound/default_tcp.go +++ b/inbound/default_tcp.go @@ -10,24 +10,26 @@ import ( E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" - "github.com/sagernet/tfo-go" ) func (a *myInboundAdapter) ListenTCP() (net.Listener, error) { var err error bindAddr := M.SocksaddrFrom(a.listenOptions.Listen.Build(), a.listenOptions.ListenPort) var tcpListener net.Listener - if !a.listenOptions.TCPFastOpen { - var listenConfig net.ListenConfig - if a.listenOptions.TCPMultiPath { - if !multipathTCPAvailable { - return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.") - } - setMultiPathTCP(&listenConfig) + var listenConfig net.ListenConfig + if a.listenOptions.TCPMultiPath { + if !go121Available { + return nil, E.New("MultiPath TCP requires go1.21, please recompile your binary.") } - tcpListener, err = listenConfig.Listen(a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) + setMultiPathTCP(&listenConfig) + } + if a.listenOptions.TCPFastOpen { + if !go120Available { + return nil, E.New("TCP Fast Open requires go1.20, please recompile your binary.") + } + tcpListener, err = listenTFO(listenConfig, a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) } else { - tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr()) + tcpListener, err = listenConfig.Listen(a.ctx, M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.String()) } if err == nil { a.logger.Info("tcp server started at ", tcpListener.Addr()) diff --git a/inbound/default_tcp_go1.20.go b/inbound/default_tcp_go1.20.go new file mode 100644 index 00000000..ee3731ec --- /dev/null +++ b/inbound/default_tcp_go1.20.go @@ -0,0 +1,18 @@ +//go:build go1.20 + +package inbound + +import ( + "context" + "net" + + "github.com/sagernet/tfo-go" +) + +const go120Available = true + +func listenTFO(listenConfig net.ListenConfig, ctx context.Context, network string, address string) (net.Listener, error) { + var tfoConfig tfo.ListenConfig + tfoConfig.ListenConfig = listenConfig + return tfoConfig.Listen(ctx, network, address) +} diff --git a/inbound/default_tcp_go1.21.go b/inbound/default_tcp_go1.21.go index 1352e056..906818cb 100644 --- a/inbound/default_tcp_go1.21.go +++ b/inbound/default_tcp_go1.21.go @@ -4,7 +4,7 @@ package inbound import "net" -const multipathTCPAvailable = true +const go121Available = true func setMultiPathTCP(listenConfig *net.ListenConfig) { listenConfig.SetMultipathTCP(true) diff --git a/inbound/default_tcp_nongo1.20.go b/inbound/default_tcp_nongo1.20.go new file mode 100644 index 00000000..e7a026bc --- /dev/null +++ b/inbound/default_tcp_nongo1.20.go @@ -0,0 +1,15 @@ +//go:build !go1.20 + +package inbound + +import ( + "context" + "net" + "os" +) + +const go120Available = false + +func listenTFO(listenConfig net.ListenConfig, ctx context.Context, network string, address string) (net.Listener, error) { + return nil, os.ErrInvalid +} diff --git a/inbound/default_tcp_nongo1.21.go b/inbound/default_tcp_nongo1.21.go index 62dc5b9f..d19adb19 100644 --- a/inbound/default_tcp_nongo1.21.go +++ b/inbound/default_tcp_nongo1.21.go @@ -4,7 +4,7 @@ package inbound import "net" -const multipathTCPAvailable = false +const go121Available = false func setMultiPathTCP(listenConfig *net.ListenConfig) { } diff --git a/test/go.mod b/test/go.mod index 988fca1f..55fdd31f 100644 --- a/test/go.mod +++ b/test/go.mod @@ -1,6 +1,6 @@ module test -go 1.18 +go 1.20 require github.com/sagernet/sing-box v0.0.0 @@ -78,7 +78,7 @@ require ( github.com/sagernet/sing-tun v0.1.12-0.20230812113806-10d98f26797a // indirect github.com/sagernet/sing-vmess v0.1.7 // indirect github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect - github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect + github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 // indirect github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e // indirect github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f // indirect diff --git a/test/go.sum b/test/go.sum index 6eb121e5..555e28cb 100644 --- a/test/go.sum +++ b/test/go.sum @@ -123,8 +123,7 @@ github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2 h1:dnkKrzapqtAwjTS github.com/sagernet/gvisor v0.0.0-20230627031050-1ab0276e0dd2/go.mod h1:1JUiV7nGuf++YFm9eWZ8q2lrwHmhcUGzptMl/vL1+LA= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/quic-go v0.0.0-20230809023643-d720ed35ac2b h1:+hpCW1zw03nnJDx+5tF9ETb6bKl2VSftv4KMGZAHC2Q= -github.com/sagernet/quic-go v0.0.0-20230809023643-d720ed35ac2b/go.mod h1:w+nln6f/ZtyPpGbFxmgd5iYFVMmgS+gpD5hu5GAqC1I= +github.com/sagernet/quic-go v0.0.0-20230811130919-d6f54a117913 h1:4dyzZWAEo9BNQN7yJsVSiN/Pm1hmUfkGJdEyWMkUnVE= github.com/sagernet/quic-go v0.0.0-20230811130919-d6f54a117913/go.mod h1:w+nln6f/ZtyPpGbFxmgd5iYFVMmgS+gpD5hu5GAqC1I= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= @@ -135,8 +134,7 @@ github.com/sagernet/sing v0.2.10-0.20230807080248-4db0062caa0a/go.mod h1:9uOZwWk github.com/sagernet/sing v0.2.10-0.20230820051732-fabfb87d9f29/go.mod h1:9uOZwWkhT2Z2WldolLxX34s+1svAX4i4vvz5hy8u1MA= github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659 h1:1DAKccGNqTYJ8nsBR765FS0LVBVXfuFlFAHqKsGN3EI= github.com/sagernet/sing-dns v0.1.9-0.20230731012726-ad50da89b659/go.mod h1:W7GHTZFS8RkoLI3bA2LFY27/0E+uoQESWtMFLepO/JA= -github.com/sagernet/sing-mux v0.1.3-0.20230803070305-ea4a972acd21 h1:IQ7oBBKz+lwIqwI9IMStlQ9YSUu3eKJmNTip0aLbvOI= -github.com/sagernet/sing-mux v0.1.3-0.20230803070305-ea4a972acd21/go.mod h1:TKxqIvfQQgd36jp2tzsPavGjYTVZilV+atip1cssjIY= +github.com/sagernet/sing-mux v0.1.3-0.20230811111955-dc1639b5204c h1:35/FowAvt3Z62mck0TXzVc4jS5R5CWq62qcV2P1cp0I= github.com/sagernet/sing-mux v0.1.3-0.20230811111955-dc1639b5204c/go.mod h1:TKxqIvfQQgd36jp2tzsPavGjYTVZilV+atip1cssjIY= github.com/sagernet/sing-shadowsocks v0.2.4 h1:s/CqXlvFAZhlIoHWUwPw5CoNnQ9Ibki9pckjuugtVfY= github.com/sagernet/sing-shadowsocks v0.2.4/go.mod h1:80fNKP0wnqlu85GZXV1H1vDPC/2t+dQbFggOw4XuFUM= @@ -144,23 +142,19 @@ github.com/sagernet/sing-shadowsocks2 v0.1.3 h1:WXoLvCFi5JTFBRYorf1YePGYIQyJ/zbs github.com/sagernet/sing-shadowsocks2 v0.1.3/go.mod h1:DOhJc/cLeqRv0wuePrQso+iUmDxOnWF4eT/oMcRzYFw= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.1.12-0.20230808120247-47ab78d303db h1:jOwG+7u4NtQVwXj5pFnGeNnDoa2cv83O5x4NLKN8y/c= -github.com/sagernet/sing-tun v0.1.12-0.20230808120247-47ab78d303db/go.mod h1:XsyIVKd/Qp+2SdLZWGbavHtcpE7J7XU3S1zJmcoj9Ck= -github.com/sagernet/sing-tun v0.1.12-0.20230811070056-38478f5fbcd2/go.mod h1:XsyIVKd/Qp+2SdLZWGbavHtcpE7J7XU3S1zJmcoj9Ck= -github.com/sagernet/sing-tun v0.1.12-0.20230812113214-bc5a1f835a28/go.mod h1:XsyIVKd/Qp+2SdLZWGbavHtcpE7J7XU3S1zJmcoj9Ck= +github.com/sagernet/sing-tun v0.1.12-0.20230812113806-10d98f26797a h1:YZ20/ohB4wDQlOd2SMaL+qnAoWyM2yuXIUOVjUqj87U= github.com/sagernet/sing-tun v0.1.12-0.20230812113806-10d98f26797a/go.mod h1:XsyIVKd/Qp+2SdLZWGbavHtcpE7J7XU3S1zJmcoj9Ck= github.com/sagernet/sing-vmess v0.1.7 h1:TM8FFLsXmlXH9XT8/oDgc6PC5BOzrg6OzyEe01is2r4= github.com/sagernet/sing-vmess v0.1.7/go.mod h1:1qkC1L1T2sxnS/NuO6HU72S8TkltV+EXoKGR29m/Yss= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= -github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE= -github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9/go.mod h1:FUyTEc5ye5NjKnDTDMuiLF2M6T4BE6y6KZuax//UCEg= +github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6 h1:Px+hN4Vzgx+iCGVnWH5A8eR7JhNnIV3rGQmBxA7cw6Q= +github.com/sagernet/tfo-go v0.0.0-20230816093905-5a5c285d44a6/go.mod h1:zovq6vTvEM6ECiqE3Eeb9rpIylPpamPcmrJ9tv0Bt0M= github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4= github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM= github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs= github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY= -github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2dKX7EQP++1JLNtw4C2TNxd4/ov8YUpOPOSo= -github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0= +github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f h1:Kvo8w8Y9lzFGB/7z09MJ3TR99TFtfI/IuY87Ygcycho= github.com/sagernet/wireguard-go v0.0.0-20230807125731-5d4a7ef2dc5f/go.mod h1:mySs0abhpc/gLlvhoq7HP1RzOaRmIXVeZGCh++zoApk= github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg= github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s=