diff --git a/box.go b/box.go index 0475e427..e6d64b1f 100644 --- a/box.go +++ b/box.go @@ -29,6 +29,7 @@ type Box struct { logger log.ContextLogger logFile *os.File clashServer adapter.ClashServer + done chan struct{} } func New(ctx context.Context, options option.Options) (*Box, error) { @@ -161,6 +162,7 @@ func New(ctx context.Context, options option.Options) (*Box, error) { logger: logFactory.NewLogger(""), logFile: logFile, clashServer: clashServer, + done: make(chan struct{}), }, nil } @@ -189,6 +191,12 @@ func (s *Box) Start() error { } func (s *Box) Close() error { + select { + case <-s.done: + return os.ErrClosed + default: + close(s.done) + } for _, in := range s.inbounds { in.Close() } diff --git a/cmd/sing-box/cmd_run.go b/cmd/sing-box/cmd_run.go index 81476f73..649f1979 100644 --- a/cmd/sing-box/cmd_run.go +++ b/cmd/sing-box/cmd_run.go @@ -2,6 +2,7 @@ package main import ( "context" + "net/http" "os" "os/signal" "syscall" @@ -10,6 +11,7 @@ import ( "github.com/sagernet/sing-box/common/json" "github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing/common/debug" E "github.com/sagernet/sing/common/exceptions" "github.com/spf13/cobra" @@ -55,6 +57,12 @@ func run0() error { cancel() return E.Cause(err, "start service") } + if debug.Enabled { + http.HandleFunc("/debug/close", func(writer http.ResponseWriter, request *http.Request) { + cancel() + instance.Close() + }) + } osSignals := make(chan os.Signal, 1) signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM) <-osSignals diff --git a/common/mux/protocol.go b/common/mux/protocol.go index dcda3f07..ad99cd6b 100644 --- a/common/mux/protocol.go +++ b/common/mux/protocol.go @@ -12,9 +12,9 @@ import ( M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" "github.com/sagernet/sing/common/rw" + "github.com/sagernet/smux" "github.com/hashicorp/yamux" - "github.com/xtaci/smux" ) var Destination = M.Socksaddr{ @@ -43,7 +43,7 @@ func ParseProtocol(name string) (Protocol, error) { func (p Protocol) newServer(conn net.Conn) (abstractSession, error) { switch p { case ProtocolSMux: - session, err := smux.Server(conn, nil) + session, err := smux.Server(wrapSMuxConn(conn), nil) if err != nil { return nil, err } @@ -58,7 +58,7 @@ func (p Protocol) newServer(conn net.Conn) (abstractSession, error) { func (p Protocol) newClient(conn net.Conn) (abstractSession, error) { switch p { case ProtocolSMux: - session, err := smux.Client(conn, nil) + session, err := smux.Client(wrapSMuxConn(conn), nil) if err != nil { return nil, err } @@ -201,6 +201,31 @@ func ReadStreamResponse(reader io.Reader) (*StreamResponse, error) { return &response, nil } +type smuxTCPConn struct { + *net.TCPConn +} + +func wrapSMuxConn(originConn net.Conn) net.Conn { + switch conn := originConn.(type) { + case *net.TCPConn: + return &smuxTCPConn{conn} + } + return originConn +} + +func (w *smuxTCPConn) WriteBuffers(v [][]byte) (n int, err error) { + buffers := net.Buffers(v) + writeN, err := buffers.WriteTo(w.TCPConn) + if err != nil { + return + } + return int(writeN), nil +} + +func (w *smuxTCPConn) Upstream() any { + return w.TCPConn +} + type wrapStream struct { net.Conn } diff --git a/common/mux/session.go b/common/mux/session.go index da1b8b65..afae7723 100644 --- a/common/mux/session.go +++ b/common/mux/session.go @@ -7,8 +7,7 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/bufio" - - "github.com/xtaci/smux" + "github.com/sagernet/smux" ) type abstractSession interface { diff --git a/go.mod b/go.mod index fc97c382..4be98bba 100644 --- a/go.mod +++ b/go.mod @@ -15,14 +15,14 @@ require ( github.com/logrusorgru/aurora v2.0.3+incompatible github.com/lucas-clemente/quic-go v0.28.1 github.com/oschwald/maxminddb-golang v1.10.0 - github.com/sagernet/sing v0.0.0-20220811152014-735372ab3ccf + github.com/sagernet/sing v0.0.0-20220812041020-13f394e2021c github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91 github.com/sagernet/sing-shadowsocks v0.0.0-20220811135826-7e47fd1a99d9 github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 + github.com/sagernet/smux v0.0.0-20220812032842-6d45eecb473e github.com/spf13/cobra v1.5.0 github.com/stretchr/testify v1.8.0 - github.com/xtaci/smux v1.5.16 go.uber.org/atomic v1.10.0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa golang.org/x/net v0.0.0-20220811182439-13a9a731de15 diff --git a/go.sum b/go.sum index 5a21013c..0d24e3db 100644 --- a/go.sum +++ b/go.sum @@ -152,8 +152,9 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 h1:hE+vtsjBCCPmxkRz9jZA+CicHgVkDT6H+Av5ZzskVxs= github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/sing v0.0.0-20220811152014-735372ab3ccf h1:k8ZXdBb5D6JqDTgwLAw4cazapPcLYbcJNxSFUvUff+s= -github.com/sagernet/sing v0.0.0-20220811152014-735372ab3ccf/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= +github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM= +github.com/sagernet/sing v0.0.0-20220812041020-13f394e2021c h1:/HDyukJrLGbr/eXyhpzPv2FGnXJeNj/bvQ/3GSYJhTo= +github.com/sagernet/sing v0.0.0-20220812041020-13f394e2021c/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91 h1:jxt2PYixIkK2i7nUGW3f+PzJagEZcbNyQddBWGuqNnw= github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91/go.mod h1:T77zZdE2Cm6VqnFumrpwsq+kxYsbq+vWDhmjtdSl/oM= github.com/sagernet/sing-shadowsocks v0.0.0-20220811135826-7e47fd1a99d9 h1:/FFNyglfOlk1x6NWhBWI+bc/kVQc7SFOSYAJ2m7FwHc= @@ -162,6 +163,8 @@ github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d h1:AQpkoUiF8FxYV github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d/go.mod h1:gWwYd53AqXl+Y+q6WlXUc6PkqU28sfu5VTQhyeEIFbw= github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 h1:2hLETh97+S4WnfMR27XyC7QVU1SH7FTNoCznP229YJU= github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps= +github.com/sagernet/smux v0.0.0-20220812032842-6d45eecb473e h1:x+COm0plODjqCs8ypUbI8IJ6kclhNirmCsaVbnBXDoA= +github.com/sagernet/smux v0.0.0-20220812032842-6d45eecb473e/go.mod h1:WFWe+7nAIPcVfJTonJwe8dRIX7JAV2Hc0/p5+X55nM4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -204,8 +207,6 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/xtaci/smux v1.5.16 h1:FBPYOkW8ZTjLKUM4LI4xnnuuDC8CQ/dB04HD519WoEk= -github.com/xtaci/smux v1.5.16/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= @@ -284,6 +285,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/outbound/default.go b/outbound/default.go index 6f339e6d..4b357f8a 100644 --- a/outbound/default.go +++ b/outbound/default.go @@ -92,15 +92,9 @@ func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn, if err != nil { return N.HandshakeFailure(conn, err) } - if metadata.Protocol != "" { - switch metadata.Protocol { - case C.ProtocolQUIC: - ctx, conn = canceler.NewPacketConn(ctx, conn, C.QUICTimeout) - case C.ProtocolDNS: - ctx, conn = canceler.NewPacketConn(ctx, conn, C.DNSTimeout) - case C.ProtocolSTUN: - ctx, conn = canceler.NewPacketConn(ctx, conn, C.STUNTimeout) - } + switch metadata.Protocol { + case C.ProtocolSTUN: + ctx, conn = canceler.NewPacketConn(ctx, conn, C.STUNTimeout) } return bufio.CopyPacketConn(ctx, conn, bufio.NewPacketConn(outConn)) } @@ -117,15 +111,11 @@ func connectPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketCo if err != nil { return N.HandshakeFailure(conn, err) } - if metadata.Protocol != "" { - switch metadata.Protocol { - case C.ProtocolQUIC: - ctx, conn = canceler.NewPacketConn(ctx, conn, C.QUICTimeout) - case C.ProtocolDNS: - ctx, conn = canceler.NewPacketConn(ctx, conn, C.DNSTimeout) - case C.ProtocolSTUN: - ctx, conn = canceler.NewPacketConn(ctx, conn, C.STUNTimeout) - } + switch metadata.Protocol { + case C.ProtocolQUIC: + ctx, conn = canceler.NewPacketConn(ctx, conn, C.QUICTimeout) + case C.ProtocolDNS: + ctx, conn = canceler.NewPacketConn(ctx, conn, C.DNSTimeout) } return bufio.CopyPacketConn(ctx, conn, bufio.NewUnbindPacketConn(outConn)) } diff --git a/outbound/dns.go b/outbound/dns.go index 44372fff..07806f20 100644 --- a/outbound/dns.go +++ b/outbound/dns.go @@ -144,5 +144,5 @@ func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metada group.Cleanup(func() { conn.Close() }) - return group.Run(ctx) + return group.Run(fastClose) } diff --git a/test/go.mod b/test/go.mod index e80f717c..e8fcb948 100644 --- a/test/go.mod +++ b/test/go.mod @@ -10,7 +10,7 @@ require ( github.com/docker/docker v20.10.17+incompatible github.com/docker/go-connections v0.4.0 github.com/gofrs/uuid v4.2.0+incompatible - github.com/sagernet/sing v0.0.0-20220811152014-735372ab3ccf + github.com/sagernet/sing v0.0.0-20220812041020-13f394e2021c github.com/sagernet/sing-shadowsocks v0.0.0-20220811135826-7e47fd1a99d9 github.com/spyzhov/ajson v0.7.1 github.com/stretchr/testify v1.8.0 @@ -56,9 +56,9 @@ require ( github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91 // indirect github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d // indirect github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 // indirect + github.com/sagernet/smux v0.0.0-20220812032842-6d45eecb473e // indirect github.com/sirupsen/logrus v1.8.1 // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect - github.com/xtaci/smux v1.5.16 // indirect go.uber.org/atomic v1.10.0 // indirect golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect golang.org/x/mod v0.5.1 // indirect diff --git a/test/go.sum b/test/go.sum index ff9e2fb7..9b6cf1fb 100644 --- a/test/go.sum +++ b/test/go.sum @@ -174,8 +174,9 @@ github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805 h1:hE+vtsjBCCPmxkRz9jZA+CicHgVkDT6H+Av5ZzskVxs= github.com/sagernet/netlink v0.0.0-20220803045538-bdac49abf805/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/sing v0.0.0-20220811152014-735372ab3ccf h1:k8ZXdBb5D6JqDTgwLAw4cazapPcLYbcJNxSFUvUff+s= -github.com/sagernet/sing v0.0.0-20220811152014-735372ab3ccf/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= +github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM= +github.com/sagernet/sing v0.0.0-20220812041020-13f394e2021c h1:/HDyukJrLGbr/eXyhpzPv2FGnXJeNj/bvQ/3GSYJhTo= +github.com/sagernet/sing v0.0.0-20220812041020-13f394e2021c/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91 h1:jxt2PYixIkK2i7nUGW3f+PzJagEZcbNyQddBWGuqNnw= github.com/sagernet/sing-dns v0.0.0-20220803121532-9e1ffb850d91/go.mod h1:T77zZdE2Cm6VqnFumrpwsq+kxYsbq+vWDhmjtdSl/oM= github.com/sagernet/sing-shadowsocks v0.0.0-20220811135826-7e47fd1a99d9 h1:/FFNyglfOlk1x6NWhBWI+bc/kVQc7SFOSYAJ2m7FwHc= @@ -184,6 +185,8 @@ github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d h1:AQpkoUiF8FxYV github.com/sagernet/sing-tun v0.0.0-20220808133432-d378b6ca536d/go.mod h1:gWwYd53AqXl+Y+q6WlXUc6PkqU28sfu5VTQhyeEIFbw= github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 h1:2hLETh97+S4WnfMR27XyC7QVU1SH7FTNoCznP229YJU= github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps= +github.com/sagernet/smux v0.0.0-20220812032842-6d45eecb473e h1:x+COm0plODjqCs8ypUbI8IJ6kclhNirmCsaVbnBXDoA= +github.com/sagernet/smux v0.0.0-20220812032842-6d45eecb473e/go.mod h1:WFWe+7nAIPcVfJTonJwe8dRIX7JAV2Hc0/p5+X55nM4= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -228,8 +231,6 @@ github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49u github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/xtaci/smux v1.5.16 h1:FBPYOkW8ZTjLKUM4LI4xnnuuDC8CQ/dB04HD519WoEk= -github.com/xtaci/smux v1.5.16/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -315,6 +316,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=