From 270a080b553cadeb0d9f231f8565acae3be8edc9 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 11 Oct 2023 10:55:12 +0800 Subject: [PATCH] fix: sing listener panic --- adapter/inbound/http.go | 5 ++-- adapter/inbound/https.go | 5 ++-- adapter/inbound/packet.go | 18 ++------------ adapter/inbound/socket.go | 9 ++++--- constant/adapters.go | 17 ++++++++++++++ constant/tunnel.go | 6 +++-- listener/inner/tcp.go | 3 +-- listener/shadowsocks/udp.go | 2 +- listener/sing/context.go | 9 ++++++- listener/sing/sing.go | 47 ++++++++++++++++++++++++------------- listener/tuic/server.go | 9 ++++--- listener/tunnel/tcp.go | 6 ++--- listener/tunnel/udp.go | 8 +++---- tunnel/tunnel.go | 14 ++++++----- 14 files changed, 91 insertions(+), 67 deletions(-) diff --git a/adapter/inbound/http.go b/adapter/inbound/http.go index 93ec2373..15376606 100644 --- a/adapter/inbound/http.go +++ b/adapter/inbound/http.go @@ -4,12 +4,11 @@ import ( "net" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/context" "github.com/Dreamacro/clash/transport/socks5" ) // NewHTTP receive normal http request and return HTTPContext -func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Addition) *context.ConnContext { +func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Addition) (net.Conn, *C.Metadata) { metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = C.HTTP @@ -17,5 +16,5 @@ func NewHTTP(target socks5.Addr, source net.Addr, conn net.Conn, additions ...Ad for _, addition := range additions { addition.Apply(metadata) } - return context.NewConnContext(conn, metadata) + return conn, metadata } diff --git a/adapter/inbound/https.go b/adapter/inbound/https.go index 26f93a45..7353fe59 100644 --- a/adapter/inbound/https.go +++ b/adapter/inbound/https.go @@ -5,16 +5,15 @@ import ( "net/http" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/context" ) // NewHTTPS receive CONNECT request and return ConnContext -func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) *context.ConnContext { +func NewHTTPS(request *http.Request, conn net.Conn, additions ...Addition) (net.Conn, *C.Metadata) { metadata := parseHTTPAddr(request) metadata.Type = C.HTTPS additions = append(additions, WithSrcAddr(conn.RemoteAddr()), WithInAddr(conn.LocalAddr())) for _, addition := range additions { addition.Apply(metadata) } - return context.NewConnContext(conn, metadata) + return conn, metadata } diff --git a/adapter/inbound/packet.go b/adapter/inbound/packet.go index d481ec09..f211f7a5 100644 --- a/adapter/inbound/packet.go +++ b/adapter/inbound/packet.go @@ -5,19 +5,8 @@ import ( "github.com/Dreamacro/clash/transport/socks5" ) -// PacketAdapter is a UDP Packet adapter for socks/redir/tun -type PacketAdapter struct { - C.UDPPacket - metadata *C.Metadata -} - -// Metadata returns destination metadata -func (s *PacketAdapter) Metadata() *C.Metadata { - return s.metadata -} - // NewPacket is PacketAdapter generator -func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions ...Addition) C.PacketAdapter { +func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions ...Addition) (C.UDPPacket, *C.Metadata) { metadata := parseSocksAddr(target) metadata.NetWork = C.UDP metadata.Type = source @@ -29,8 +18,5 @@ func NewPacket(target socks5.Addr, packet C.UDPPacket, source C.Type, additions addition.Apply(metadata) } - return &PacketAdapter{ - packet, - metadata, - } + return packet, metadata } diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index 5892bebc..65dbe0a2 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -6,12 +6,11 @@ import ( "strconv" C "github.com/Dreamacro/clash/constant" - "github.com/Dreamacro/clash/context" "github.com/Dreamacro/clash/transport/socks5" ) // NewSocket receive TCP inbound and return ConnContext -func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Addition) *context.ConnContext { +func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Addition) (net.Conn, *C.Metadata) { metadata := parseSocksAddr(target) metadata.NetWork = C.TCP metadata.Type = source @@ -20,10 +19,10 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Ad addition.Apply(metadata) } - return context.NewConnContext(conn, metadata) + return conn, metadata } -func NewInner(conn net.Conn, address string) *context.ConnContext { +func NewInner(conn net.Conn, address string) (net.Conn, *C.Metadata) { metadata := &C.Metadata{} metadata.NetWork = C.TCP metadata.Type = C.INNER @@ -40,5 +39,5 @@ func NewInner(conn net.Conn, address string) *context.ConnContext { } } - return context.NewConnContext(conn, metadata) + return conn, metadata } diff --git a/constant/adapters.go b/constant/adapters.go index 33b9a44f..ad50a8ab 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -252,6 +252,23 @@ type PacketAdapter interface { Metadata() *Metadata } +type packetAdapter struct { + UDPPacket + metadata *Metadata +} + +// Metadata returns destination metadata +func (s *packetAdapter) Metadata() *Metadata { + return s.metadata +} + +func NewPacketAdapter(packet UDPPacket, metadata *Metadata) PacketAdapter { + return &packetAdapter{ + packet, + metadata, + } +} + type WriteBack interface { WriteBack(b []byte, addr net.Addr) (n int, err error) } diff --git a/constant/tunnel.go b/constant/tunnel.go index 39f8936a..7c9d08e2 100644 --- a/constant/tunnel.go +++ b/constant/tunnel.go @@ -1,10 +1,12 @@ package constant +import "net" + type Tunnel interface { // HandleTCPConn will handle a tcp connection blocking - HandleTCPConn(connCtx ConnContext) + HandleTCPConn(conn net.Conn, metadata *Metadata) // HandleUDPPacket will handle a udp packet nonblocking - HandleUDPPacket(packet PacketAdapter) + HandleUDPPacket(packet UDPPacket, metadata *Metadata) // NatTable return nat table NatTable() NatTable } diff --git a/listener/inner/tcp.go b/listener/inner/tcp.go index 4a54a82f..cbd27cd6 100644 --- a/listener/inner/tcp.go +++ b/listener/inner/tcp.go @@ -20,7 +20,6 @@ func HandleTcp(address string) (conn net.Conn, err error) { } // executor Parsed conn1, conn2 := net.Pipe() - context := inbound.NewInner(conn2, address) - go tunnel.HandleTCPConn(context) + go tunnel.HandleTCPConn(inbound.NewInner(conn2, address)) return conn1, nil } diff --git a/listener/shadowsocks/udp.go b/listener/shadowsocks/udp.go index cc055853..53f5549a 100644 --- a/listener/shadowsocks/udp.go +++ b/listener/shadowsocks/udp.go @@ -67,7 +67,7 @@ func handleSocksUDP(pc net.PacketConn, tunnel C.Tunnel, buf []byte, put func(), } return } - target := socks5.ParseAddr(tgtAddr.String()) + target := tgtAddr payload := buf[len(tgtAddr):] packet := &packet{ diff --git a/listener/sing/context.go b/listener/sing/context.go index a500e4a4..32b2a161 100644 --- a/listener/sing/context.go +++ b/listener/sing/context.go @@ -26,7 +26,7 @@ func getAdditions(ctx context.Context) []inbound.Addition { return nil } -func combineAdditions(ctx context.Context, additions []inbound.Addition) []inbound.Addition { +func combineAdditions(ctx context.Context, additions []inbound.Addition, extraAdditions ...inbound.Addition) []inbound.Addition { additionsCloned := false if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 { additions = slices.Clone(additions) @@ -40,5 +40,12 @@ func combineAdditions(ctx context.Context, additions []inbound.Addition) []inbou } additions = append(additions, inbound.WithInUser(user)) } + if len(extraAdditions) > 0 { + if !additionsCloned { + additions = slices.Clone(additions) + additionsCloned = true + } + additions = append(additions, extraAdditions...) + } return additions } diff --git a/listener/sing/sing.go b/listener/sing/sing.go index a9bee564..301dc783 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -12,7 +12,6 @@ import ( N "github.com/Dreamacro/clash/common/net" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" - "github.com/Dreamacro/clash/transport/socks5" vmess "github.com/metacubex/sing-vmess" mux "github.com/sagernet/sing-mux" @@ -85,15 +84,26 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta if h.IsSpecialFqdn(metadata.Destination.Fqdn) { return h.ParseSpecialFqdn(ctx, conn, metadata) } - target := socks5.ParseAddr(metadata.Destination.String()) if deadline.NeedAdditionalReadDeadline(conn) { conn = N.NewDeadlineConn(conn) // conn from sing should check NeedAdditionalReadDeadline } - connCtx := inbound.NewSocket(target, conn, h.Type, combineAdditions(ctx, h.Additions)...) - inbound.WithSrcAddr(metadata.Source.TCPAddr()).Apply(connCtx.Metadata()) // set srcAddr from sing's metadata - h.Tunnel.HandleTCPConn(connCtx) // this goroutine must exit after conn unused + cMetadata := &C.Metadata{ + NetWork: C.TCP, + Type: h.Type, + Host: metadata.Destination.Fqdn, + DstIP: metadata.Destination.Addr, + DstPort: metadata.Destination.Port, + SrcIP: metadata.Source.Addr, + SrcPort: metadata.Source.Port, + } + additions := combineAdditions(ctx, h.Additions, inbound.WithInAddr(conn.LocalAddr())) + for _, addition := range additions { + addition.Apply(cMetadata) + } + + h.Tunnel.HandleTCPConn(conn, cMetadata) // this goroutine must exit after conn unused return nil } @@ -138,8 +148,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. } return err } - target := socks5.ParseAddr(dest.String()) - packet := &packet{ + cPacket := &packet{ conn: &conn2, mutex: &mutex, rAddr: metadata.Source.UDPAddr(), @@ -147,7 +156,21 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. buff: buff, } - h.Tunnel.HandleUDPPacket(inbound.NewPacket(target, packet, h.Type, combineAdditions(ctx, h.Additions)...)) + cMetadata := &C.Metadata{ + NetWork: C.UDP, + Type: h.Type, + Host: dest.Fqdn, + DstIP: dest.Addr, + DstPort: dest.Port, + SrcIP: metadata.Source.Addr, + SrcPort: metadata.Source.Port, + } + additions := combineAdditions(ctx, h.Additions, inbound.WithInAddr(conn.LocalAddr())) + for _, addition := range additions { + addition.Apply(cMetadata) + } + + h.Tunnel.HandleUDPPacket(cPacket, cMetadata) } return nil } @@ -215,11 +238,3 @@ func (c *packet) Drop() { func (c *packet) InAddr() net.Addr { return c.lAddr } - -func (c *packet) SetNatTable(natTable C.NatTable) { - // no need -} - -func (c *packet) SetUdpInChan(in chan<- C.PacketAdapter) { - // no need -} diff --git a/listener/tuic/server.go b/listener/tuic/server.go index 70cf4a01..544f1328 100644 --- a/listener/tuic/server.go +++ b/listener/tuic/server.go @@ -94,19 +94,18 @@ func New(config LC.TuicServer, tunnel C.Tunnel, additions ...inbound.Addition) ( newAdditions = slices.Clone(additions) newAdditions = append(newAdditions, _additions...) } - connCtx := inbound.NewSocket(addr, conn, C.TUIC, newAdditions...) - metadata := sing.ConvertMetadata(connCtx.Metadata()) - if h.IsSpecialFqdn(metadata.Destination.Fqdn) { + conn, metadata := inbound.NewSocket(addr, conn, C.TUIC, newAdditions...) + if h.IsSpecialFqdn(metadata.Host) { go func() { // ParseSpecialFqdn will block, so open a new goroutine _ = h.ParseSpecialFqdn( sing.WithAdditions(context.Background(), newAdditions...), conn, - metadata, + sing.ConvertMetadata(metadata), ) }() return nil } - go tunnel.HandleTCPConn(connCtx) + go tunnel.HandleTCPConn(conn, metadata) return nil } handleUdpFn := func(addr socks5.Addr, packet C.UDPPacket, _additions ...inbound.Addition) error { diff --git a/listener/tunnel/tcp.go b/listener/tunnel/tcp.go index 8cc527fb..dd2059db 100644 --- a/listener/tunnel/tcp.go +++ b/listener/tunnel/tcp.go @@ -36,9 +36,9 @@ func (l *Listener) Close() error { func (l *Listener) handleTCP(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { N.TCPKeepAlive(conn) - ctx := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...) - ctx.Metadata().SpecialProxy = l.proxy - tunnel.HandleTCPConn(ctx) + conn, metadata := inbound.NewSocket(l.target, conn, C.TUNNEL, additions...) + metadata.SpecialProxy = l.proxy + tunnel.HandleTCPConn(conn, metadata) } func New(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { diff --git a/listener/tunnel/udp.go b/listener/tunnel/udp.go index c2f1dcc3..38b779c4 100644 --- a/listener/tunnel/udp.go +++ b/listener/tunnel/udp.go @@ -70,13 +70,13 @@ func NewUDP(addr, target, proxy string, tunnel C.Tunnel, additions ...inbound.Ad } func (l *PacketConn) handleUDP(pc net.PacketConn, tunnel C.Tunnel, buf []byte, addr net.Addr, additions ...inbound.Addition) { - packet := &packet{ + cPacket := &packet{ pc: pc, rAddr: addr, payload: buf, } - ctx := inbound.NewPacket(l.target, packet, C.TUNNEL, additions...) - ctx.Metadata().SpecialProxy = l.proxy - tunnel.HandleUDPPacket(ctx) + packet, metadata := inbound.NewPacket(l.target, cPacket, C.TUNNEL, additions...) + metadata.SpecialProxy = l.proxy + tunnel.HandleUDPPacket(packet, metadata) } diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index 1e73a833..13bf6d8c 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -53,13 +53,15 @@ type tunnel struct{} var Tunnel C.Tunnel = tunnel{} -func (t tunnel) HandleTCPConn(connCtx C.ConnContext) { +func (t tunnel) HandleTCPConn(conn net.Conn, metadata *C.Metadata) { + connCtx := icontext.NewConnContext(conn, metadata) handleTCPConn(connCtx) } -func (t tunnel) HandleUDPPacket(packet C.PacketAdapter) { +func (t tunnel) HandleUDPPacket(packet C.UDPPacket, metadata *C.Metadata) { + packetAdapter := C.NewPacketAdapter(packet, metadata) select { - case udpQueue <- packet: + case udpQueue <- packetAdapter: default: } } @@ -274,7 +276,7 @@ func preHandleMetadata(metadata *C.Metadata) error { return nil } -func resolveMetadata(ctx C.PlainContext, metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err error) { +func resolveMetadata(metadata *C.Metadata) (proxy C.Proxy, rule C.Rule, err error) { if metadata.SpecialProxy != "" { var exist bool proxy, exist = proxies[metadata.SpecialProxy] @@ -369,7 +371,7 @@ func handleUDPConn(packet C.PacketAdapter) { }() pCtx := icontext.NewPacketConnContext(metadata) - proxy, rule, err := resolveMetadata(pCtx, metadata) + proxy, rule, err := resolveMetadata(metadata) if err != nil { log.Warnln("[UDP] Parse metadata failed: %s", err.Error()) return @@ -477,7 +479,7 @@ func handleTCPConn(connCtx C.ConnContext) { }() } - proxy, rule, err := resolveMetadata(connCtx, metadata) + proxy, rule, err := resolveMetadata(metadata) if err != nil { log.Warnln("[Metadata] parse failed: %s", err.Error()) return