Browse Source

Improve UDP domain destination NAT

世界 2 năm trước cách đây
mục cha
commit
35f03f092d
7 tập tin đã thay đổi với 29 bổ sung98 xóa
  1. 3 2
      common/dialer/resolve.go
  2. 0 84
      common/dialer/resolve_conn.go
  3. 2 2
      go.mod
  4. 4 4
      go.sum
  5. 8 1
      outbound/default.go
  6. 8 3
      outbound/vless.go
  7. 4 2
      outbound/vmess.go

+ 3 - 2
common/dialer/resolve.go

@@ -9,6 +9,7 @@ import (
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/log"
 	"github.com/sagernet/sing-dns"
+	"github.com/sagernet/sing/common/bufio"
 	M "github.com/sagernet/sing/common/metadata"
 	N "github.com/sagernet/sing/common/network"
 )
@@ -68,11 +69,11 @@ func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksadd
 	if err != nil {
 		return nil, err
 	}
-	conn, err := N.ListenSerial(ctx, d.dialer, destination, addresses)
+	conn, destinationAddress, err := N.ListenSerial(ctx, d.dialer, destination, addresses)
 	if err != nil {
 		return nil, err
 	}
-	return NewResolvePacketConn(ctx, d.router, d.strategy, conn), nil
+	return bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, M.SocksaddrFrom(destinationAddress, destination.Port)), nil
 }
 
 func (d *ResolveDialer) Upstream() any {

+ 0 - 84
common/dialer/resolve_conn.go

@@ -1,84 +0,0 @@
-package dialer
-
-import (
-	"context"
-	"net"
-
-	"github.com/sagernet/sing-box/adapter"
-	"github.com/sagernet/sing-dns"
-	"github.com/sagernet/sing/common"
-	"github.com/sagernet/sing/common/buf"
-	M "github.com/sagernet/sing/common/metadata"
-	N "github.com/sagernet/sing/common/network"
-)
-
-func NewResolvePacketConn(ctx context.Context, router adapter.Router, strategy dns.DomainStrategy, conn net.PacketConn) N.NetPacketConn {
-	if udpConn, ok := conn.(*net.UDPConn); ok {
-		return &ResolveUDPConn{udpConn, ctx, router, strategy}
-	} else {
-		return &ResolvePacketConn{conn, ctx, router, strategy}
-	}
-}
-
-type ResolveUDPConn struct {
-	*net.UDPConn
-	ctx      context.Context
-	router   adapter.Router
-	strategy dns.DomainStrategy
-}
-
-func (w *ResolveUDPConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
-	n, addr, err := w.ReadFromUDPAddrPort(buffer.FreeBytes())
-	if err != nil {
-		return M.Socksaddr{}, err
-	}
-	buffer.Truncate(n)
-	return M.SocksaddrFromNetIP(addr), nil
-}
-
-func (w *ResolveUDPConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
-	defer buffer.Release()
-	if destination.IsFqdn() {
-		addresses, err := w.router.Lookup(w.ctx, destination.Fqdn, w.strategy)
-		if err != nil {
-			return err
-		}
-		return common.Error(w.UDPConn.WriteToUDPAddrPort(buffer.Bytes(), M.SocksaddrFrom(addresses[0], destination.Port).AddrPort()))
-	}
-	return common.Error(w.UDPConn.WriteToUDPAddrPort(buffer.Bytes(), destination.AddrPort()))
-}
-
-func (w *ResolveUDPConn) Upstream() any {
-	return w.UDPConn
-}
-
-type ResolvePacketConn struct {
-	net.PacketConn
-	ctx      context.Context
-	router   adapter.Router
-	strategy dns.DomainStrategy
-}
-
-func (w *ResolvePacketConn) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
-	_, addr, err := buffer.ReadPacketFrom(w)
-	if err != nil {
-		return M.Socksaddr{}, err
-	}
-	return M.SocksaddrFromNet(addr), err
-}
-
-func (w *ResolvePacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
-	defer buffer.Release()
-	if destination.IsFqdn() {
-		addresses, err := w.router.Lookup(w.ctx, destination.Fqdn, w.strategy)
-		if err != nil {
-			return err
-		}
-		return common.Error(w.WriteTo(buffer.Bytes(), M.SocksaddrFrom(addresses[0], destination.Port).UDPAddr()))
-	}
-	return common.Error(w.WriteTo(buffer.Bytes(), destination.UDPAddr()))
-}
-
-func (w *ResolvePacketConn) Upstream() any {
-	return w.PacketConn
-}

+ 2 - 2
go.mod

@@ -25,8 +25,8 @@ require (
 	github.com/sagernet/gomobile v0.0.0-20221130124640-349ebaa752ca
 	github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
 	github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f
-	github.com/sagernet/sing v0.2.1
-	github.com/sagernet/sing-dns v0.1.5-0.20230331013337-06044a57b1da
+	github.com/sagernet/sing v0.2.2-0.20230402035613-6d63c1a7dca5
+	github.com/sagernet/sing-dns v0.1.5-0.20230402033314-a752be02978d
 	github.com/sagernet/sing-shadowsocks v0.2.0
 	github.com/sagernet/sing-shadowtls v0.1.0
 	github.com/sagernet/sing-tun v0.1.4-0.20230326080954-8848c0e4cbab

+ 4 - 4
go.sum

@@ -111,10 +111,10 @@ github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f h1:plVtFF9NVw5Py4
 github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
 github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
 github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
-github.com/sagernet/sing v0.2.1 h1:r0STYeyfKBBtoAHsBtW1dQonxG+3Qidde7/1VAMhdn8=
-github.com/sagernet/sing v0.2.1/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
-github.com/sagernet/sing-dns v0.1.5-0.20230331013337-06044a57b1da h1:pZV4DRBArbgkajeCZWn3VqwLF+Wl7HOlAt5aSJuuKDk=
-github.com/sagernet/sing-dns v0.1.5-0.20230331013337-06044a57b1da/go.mod h1:8x+rlRnPE/5/IagjlAUqR9TceRYRL2WyqmP5QYK3dkI=
+github.com/sagernet/sing v0.2.2-0.20230402035613-6d63c1a7dca5 h1:UB1vAmu7/4ya2FzX2lwIAs0bRPcWQPY5kSCBK4RLi2g=
+github.com/sagernet/sing v0.2.2-0.20230402035613-6d63c1a7dca5/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
+github.com/sagernet/sing-dns v0.1.5-0.20230402033314-a752be02978d h1:1x2TMcIw/HMjC5kCMDSyOYbx+2MICk//kjni9gx7Xwk=
+github.com/sagernet/sing-dns v0.1.5-0.20230402033314-a752be02978d/go.mod h1:69PNSHyEmXdjf6C+bXBOdr2GQnPeEyWjIzo/MV8gmz8=
 github.com/sagernet/sing-shadowsocks v0.2.0 h1:ILDWL7pwWfkPLEbviE/MyCgfjaBmJY/JVVY+5jhSb58=
 github.com/sagernet/sing-shadowsocks v0.2.0/go.mod h1:ysYzszRLpNzJSorvlWRMuzU6Vchsp7sd52q+JNY4axw=
 github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=

+ 8 - 1
outbound/default.go

@@ -3,6 +3,7 @@ package outbound
 import (
 	"context"
 	"net"
+	"net/netip"
 	"os"
 	"runtime"
 	"time"
@@ -56,15 +57,21 @@ func NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata a
 func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn, metadata adapter.InboundContext) error {
 	ctx = adapter.WithContext(ctx, &metadata)
 	var outConn net.PacketConn
+	var destinationAddress netip.Addr
 	var err error
 	if len(metadata.DestinationAddresses) > 0 {
-		outConn, err = N.ListenSerial(ctx, this, metadata.Destination, metadata.DestinationAddresses)
+		outConn, destinationAddress, err = N.ListenSerial(ctx, this, metadata.Destination, metadata.DestinationAddresses)
 	} else {
 		outConn, err = this.ListenPacket(ctx, metadata.Destination)
 	}
 	if err != nil {
 		return N.HandshakeFailure(conn, err)
 	}
+	if destinationAddress.IsValid() {
+		if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
+			natConn.UpdateDestination(destinationAddress)
+		}
+	}
 	switch metadata.Protocol {
 	case C.ProtocolSTUN:
 		ctx, conn = canceler.NewPacketConn(ctx, conn, C.STUNTimeout)

+ 8 - 3
outbound/vless.go

@@ -12,7 +12,6 @@ import (
 	"github.com/sagernet/sing-box/option"
 	"github.com/sagernet/sing-box/transport/v2ray"
 	"github.com/sagernet/sing-box/transport/vless"
-	"github.com/sagernet/sing-dns"
 	"github.com/sagernet/sing-vmess/packetaddr"
 	"github.com/sagernet/sing/common"
 	"github.com/sagernet/sing/common/bufio"
@@ -105,11 +104,14 @@ func (h *VLESS) DialContext(ctx context.Context, network string, destination M.S
 		if h.xudp {
 			return h.client.DialEarlyXUDPPacketConn(conn, destination)
 		} else if h.packetAddr {
+			if destination.IsFqdn() {
+				return nil, E.New("packetaddr: domain destination is not supported")
+			}
 			packetConn, err := h.client.DialEarlyPacketConn(conn, M.Socksaddr{Fqdn: packetaddr.SeqPacketMagicAddress})
 			if err != nil {
 				return nil, err
 			}
-			return &bufio.BindPacketConn{PacketConn: dialer.NewResolvePacketConn(ctx, h.router, dns.DomainStrategyAsIS, packetaddr.NewConn(packetConn, destination)), Addr: destination}, nil
+			return &bufio.BindPacketConn{PacketConn: packetaddr.NewConn(packetConn, destination), Addr: destination}, nil
 		} else {
 			return h.client.DialEarlyPacketConn(conn, destination)
 		}
@@ -140,11 +142,14 @@ func (h *VLESS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.
 	if h.xudp {
 		return h.client.DialEarlyXUDPPacketConn(conn, destination)
 	} else if h.packetAddr {
+		if destination.IsFqdn() {
+			return nil, E.New("packetaddr: domain destination is not supported")
+		}
 		conn, err := h.client.DialEarlyPacketConn(conn, M.Socksaddr{Fqdn: packetaddr.SeqPacketMagicAddress})
 		if err != nil {
 			return nil, err
 		}
-		return dialer.NewResolvePacketConn(ctx, h.router, dns.DomainStrategyAsIS, packetaddr.NewConn(conn, destination)), nil
+		return packetaddr.NewConn(conn, destination), nil
 	} else {
 		return h.client.DialEarlyPacketConn(conn, destination)
 	}

+ 4 - 2
outbound/vmess.go

@@ -12,7 +12,6 @@ import (
 	"github.com/sagernet/sing-box/log"
 	"github.com/sagernet/sing-box/option"
 	"github.com/sagernet/sing-box/transport/v2ray"
-	"github.com/sagernet/sing-dns"
 	"github.com/sagernet/sing-vmess"
 	"github.com/sagernet/sing-vmess/packetaddr"
 	"github.com/sagernet/sing/common"
@@ -188,7 +187,10 @@ func (h *vmessDialer) ListenPacket(ctx context.Context, destination M.Socksaddr)
 		return nil, err
 	}
 	if h.packetAddr {
-		return dialer.NewResolvePacketConn(ctx, h.router, dns.DomainStrategyAsIS, packetaddr.NewConn(h.client.DialEarlyPacketConn(conn, M.Socksaddr{Fqdn: packetaddr.SeqPacketMagicAddress}), destination)), nil
+		if destination.IsFqdn() {
+			return nil, E.New("packetaddr: domain destination is not supported")
+		}
+		return packetaddr.NewConn(h.client.DialEarlyPacketConn(conn, M.Socksaddr{Fqdn: packetaddr.SeqPacketMagicAddress}), destination), nil
 	} else if h.xudp {
 		return h.client.DialEarlyXUDPPacketConn(conn, destination), nil
 	} else {