diff --git a/common/dialer/resolve.go b/common/dialer/resolve.go index 99633e2d..66b86097 100644 --- a/common/dialer/resolve.go +++ b/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 { diff --git a/common/dialer/resolve_conn.go b/common/dialer/resolve_conn.go deleted file mode 100644 index 7fe011ff..00000000 --- a/common/dialer/resolve_conn.go +++ /dev/null @@ -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 -} diff --git a/go.mod b/go.mod index cb1c4cd0..40ce9ecd 100644 --- a/go.mod +++ b/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 diff --git a/go.sum b/go.sum index 4ab4c74b..b776372e 100644 --- a/go.sum +++ b/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= diff --git a/outbound/default.go b/outbound/default.go index 005b9da9..2f147a41 100644 --- a/outbound/default.go +++ b/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) diff --git a/outbound/vless.go b/outbound/vless.go index 6d0af0ee..ac5eb02d 100644 --- a/outbound/vless.go +++ b/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) } diff --git a/outbound/vmess.go b/outbound/vmess.go index 07e035ab..cb6ba40f 100644 --- a/outbound/vmess.go +++ b/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 { diff --git a/route/router.go b/route/router.go index 7a132521..55738e79 100644 --- a/route/router.go +++ b/route/router.go @@ -784,7 +784,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m } } if originAddress.IsValid() { - conn = fakeip.NewNATPacketConn(conn, originAddress, metadata.Destination) + conn = bufio.NewNATPacketConn(&bufio.FallbackPacketConn{PacketConn: conn}, originAddress, metadata.Destination) } return detour.NewPacketConnection(ctx, conn, metadata) } diff --git a/transport/fakeip/packet.go b/transport/fakeip/packet.go deleted file mode 100644 index 748d56f4..00000000 --- a/transport/fakeip/packet.go +++ /dev/null @@ -1,42 +0,0 @@ -package fakeip - -import ( - "github.com/sagernet/sing/common/buf" - M "github.com/sagernet/sing/common/metadata" - N "github.com/sagernet/sing/common/network" -) - -var _ N.PacketConn = (*NATPacketConn)(nil) - -type NATPacketConn struct { - N.PacketConn - origin M.Socksaddr - destination M.Socksaddr -} - -func NewNATPacketConn(conn N.PacketConn, origin M.Socksaddr, destination M.Socksaddr) *NATPacketConn { - return &NATPacketConn{ - PacketConn: conn, - origin: origin, - destination: destination, - } -} - -func (c *NATPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { - destination, err = c.PacketConn.ReadPacket(buffer) - if destination == c.origin { - destination = c.destination - } - return -} - -func (c *NATPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { - if destination == c.destination { - destination = c.origin - } - return c.PacketConn.WritePacket(buffer, destination) -} - -func (c *NATPacketConn) Upstream() any { - return c.PacketConn -}