From a9462460a52ebdfc54745fa3a0ab862e2b47214d Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Sun, 21 Jul 2024 17:05:03 -0500 Subject: [PATCH 1/5] wip --- common/net/cnc/connection.go | 12 ++++++++++++ transport/internet/splithttp/dialer.go | 12 ++++++++++-- transport/internet/system_dialer.go | 6 ++++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/common/net/cnc/connection.go b/common/net/cnc/connection.go index bdae5409673b..dc69de674534 100644 --- a/common/net/cnc/connection.go +++ b/common/net/cnc/connection.go @@ -2,6 +2,7 @@ package cnc import ( "io" + gonet "net" "time" "github.com/xtls/xray-core/common" @@ -122,6 +123,17 @@ func (c *connection) WriteMultiBuffer(mb buf.MultiBuffer) error { return c.writer.WriteMultiBuffer(mb) } +// ReadFrom implements net.PacketConn +func (c *connection) ReadFrom(p []byte) (n int, addr gonet.Addr, err error) { + n, err = c.Read(p) + return n, c.remote, err +} + +// ReadFrom implements net.PacketConn +func (c *connection) WriteTo(p []byte, addr gonet.Addr) (n int, err error) { + return c.Write(p) +} + // Close implements net.Conn.Close(). func (c *connection) Close() error { common.Must(c.done.Close()) diff --git a/transport/internet/splithttp/dialer.go b/transport/internet/splithttp/dialer.go index 99558975aef5..2d9d9e5f7745 100644 --- a/transport/internet/splithttp/dialer.go +++ b/transport/internet/splithttp/dialer.go @@ -97,7 +97,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in return nil, err } - var udpConn *net.UDPConn + var udpConn internet.PacketConnWithDest var udpAddr *net.UDPAddr switch c := conn.(type) { @@ -118,7 +118,15 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in return nil, err } default: - return nil, errors.New("unsupported connection type: %T", conn) + var ok bool + udpConn, ok = c.(internet.PacketConnWithDest) + if !ok { + return nil, errors.New("unsupported connection type: ", conn) + } + udpAddr, err = net.ResolveUDPAddr("udp", c.RemoteAddr().String()) + if err != nil { + return nil, err + } } return quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg) diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index 73379e4102b7..75250779f2dd 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -221,3 +221,9 @@ func RegisterDialerController(ctl control.Func) error { dialer.controllers = append(dialer.controllers, ctl) return nil } + + +type PacketConnWithDest interface { + net.PacketConn + net.Conn +} From ecb08e8df14b59f2c949554ebca021450db88018 Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:37:55 -0500 Subject: [PATCH 2/5] wip --- transport/internet/splithttp/dialer.go | 8 ++----- transport/internet/system_dialer.go | 30 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/transport/internet/splithttp/dialer.go b/transport/internet/splithttp/dialer.go index 2d9d9e5f7745..8d10d419c52a 100644 --- a/transport/internet/splithttp/dialer.go +++ b/transport/internet/splithttp/dialer.go @@ -97,7 +97,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in return nil, err } - var udpConn internet.PacketConnWithDest + var udpConn net.PacketConn var udpAddr *net.UDPAddr switch c := conn.(type) { @@ -118,11 +118,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in return nil, err } default: - var ok bool - udpConn, ok = c.(internet.PacketConnWithDest) - if !ok { - return nil, errors.New("unsupported connection type: ", conn) - } + udpConn = &internet.FakePacketConn{c} udpAddr, err = net.ResolveUDPAddr("udp", c.RemoteAddr().String()) if err != nil { return nil, err diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index 75250779f2dd..2d114dee1868 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -4,6 +4,7 @@ import ( "context" "syscall" "time" + "math/rand" "github.com/sagernet/sing/common/control" "github.com/xtls/xray-core/common/errors" @@ -223,7 +224,30 @@ func RegisterDialerController(ctl control.Func) error { } -type PacketConnWithDest interface { - net.PacketConn - net.Conn + +type FakePacketConn struct { + net.Conn +} + +func (c *FakePacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { + n, err = c.Read(p) + return n, c.RemoteAddr(), err } + +func (c *FakePacketConn) WriteTo(p []byte, _ net.Addr) (n int, err error) { + return c.Write(p) +} + +func (c *FakePacketConn) LocalAddr() net.Addr { + return &net.TCPAddr{ + IP: net.IP{byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256)), byte(rand.Intn(256))}, + Port: rand.Intn(65536), + } +} + +func (c *FakePacketConn) SetReadBuffer(bytes int) error { + // do nothing, this function is only there to suppress quic-go printing + // random warnings about UDP buffers to stdout + return nil +} + From 23577d84c5a58a1568683faa7ad763205312df11 Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:38:06 -0500 Subject: [PATCH 3/5] formatting --- transport/internet/system_dialer.go | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index 2d114dee1868..52b1e830d0b5 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -2,9 +2,9 @@ package internet import ( "context" + "math/rand" "syscall" "time" - "math/rand" "github.com/sagernet/sing/common/control" "github.com/xtls/xray-core/common/errors" @@ -49,7 +49,7 @@ func hasBindAddr(sockopt *SocketConfig) bool { } func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { - errors.LogDebug(ctx, "dialing to " + dest.String()) + errors.LogDebug(ctx, "dialing to "+dest.String()) if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) { srcAddr := resolveSrcAddr(net.Network_UDP, src) @@ -223,8 +223,6 @@ func RegisterDialerController(ctl control.Func) error { return nil } - - type FakePacketConn struct { net.Conn } @@ -246,8 +244,7 @@ func (c *FakePacketConn) LocalAddr() net.Addr { } func (c *FakePacketConn) SetReadBuffer(bytes int) error { - // do nothing, this function is only there to suppress quic-go printing - // random warnings about UDP buffers to stdout - return nil + // do nothing, this function is only there to suppress quic-go printing + // random warnings about UDP buffers to stdout + return nil } - From 5c0fd5ab14c8ba48ba90843d58f806cb6a037dd5 Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:39:37 -0500 Subject: [PATCH 4/5] cnc connection no longer needs to be a Packetconn --- common/net/cnc/connection.go | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/common/net/cnc/connection.go b/common/net/cnc/connection.go index dc69de674534..bdae5409673b 100644 --- a/common/net/cnc/connection.go +++ b/common/net/cnc/connection.go @@ -2,7 +2,6 @@ package cnc import ( "io" - gonet "net" "time" "github.com/xtls/xray-core/common" @@ -123,17 +122,6 @@ func (c *connection) WriteMultiBuffer(mb buf.MultiBuffer) error { return c.writer.WriteMultiBuffer(mb) } -// ReadFrom implements net.PacketConn -func (c *connection) ReadFrom(p []byte) (n int, addr gonet.Addr, err error) { - n, err = c.Read(p) - return n, c.remote, err -} - -// ReadFrom implements net.PacketConn -func (c *connection) WriteTo(p []byte, addr gonet.Addr) (n int, err error) { - return c.Write(p) -} - // Close implements net.Conn.Close(). func (c *connection) Close() error { common.Must(c.done.Close()) From e2ac036dc7d428b48b002f2329b348731afb1184 Mon Sep 17 00:00:00 2001 From: mmmray <142015632+mmmray@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:03:28 -0500 Subject: [PATCH 5/5] dialerProxy: do not cancel connection when Dial context is cancelled --- transport/internet/dialer.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/transport/internet/dialer.go b/transport/internet/dialer.go index 989bfa03e3eb..8ab51551b99b 100644 --- a/transport/internet/dialer.go +++ b/transport/internet/dialer.go @@ -111,7 +111,7 @@ func canLookupIP(ctx context.Context, dst net.Destination, sockopt *SocketConfig } func redirect(ctx context.Context, dst net.Destination, obt string) net.Conn { - errors.LogInfo(ctx, "redirecting request " + dst.String() + " to " + obt) + errors.LogInfo(ctx, "redirecting request "+dst.String()+" to "+obt) h := obm.GetHandler(obt) outbounds := session.OutboundsFromContext(ctx) ctx = session.ContextWithOutbounds(ctx, append(outbounds, &session.Outbound{ @@ -123,10 +123,16 @@ func redirect(ctx context.Context, dst net.Destination, obt string) net.Conn { ur, uw := pipe.New(pipe.OptionsFromContext(ctx)...) dr, dw := pipe.New(pipe.OptionsFromContext(ctx)...) - go h.Dispatch(ctx, &transport.Link{Reader: ur, Writer: dw}) + go h.Dispatch(context.WithoutCancel(ctx), &transport.Link{Reader: ur, Writer: dw}) + var readerOpt cnc.ConnectionOption + if dst.Network == net.Network_TCP { + readerOpt = cnc.ConnectionOutputMulti(dr) + } else { + readerOpt = cnc.ConnectionOutputMultiUDP(dr) + } nc := cnc.NewConnection( cnc.ConnectionInputMulti(uw), - cnc.ConnectionOutputMulti(dr), + readerOpt, cnc.ConnectionOnClose(common.ChainedClosable{uw, dw}), ) return nc @@ -150,7 +156,7 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig ips, err := lookupIP(dest.Address.String(), sockopt.DomainStrategy, src) if err == nil && len(ips) > 0 { dest.Address = net.IPAddress(ips[dice.Roll(len(ips))]) - errors.LogInfo(ctx, "replace destination with " + dest.String()) + errors.LogInfo(ctx, "replace destination with "+dest.String()) } else if err != nil { errors.LogWarningInner(ctx, err, "failed to resolve ip") }