@@ -15,7 +15,7 @@ import (
1515 "github.com/sagernet/sing/common/logger"
1616 M "github.com/sagernet/sing/common/metadata"
1717 N "github.com/sagernet/sing/common/network"
18- "github.com/sagernet/sing/common/udpnat "
18+ "github.com/sagernet/sing/common/udpnat2 "
1919)
2020
2121var ErrIncludeAllNetworks = E .New ("`system` and `mixed` stack are not available when `includeAllNetworks` is enabled. See https://github.com/SagerNet/sing-tun/issues/25" )
@@ -34,13 +34,13 @@ type System struct {
3434 inet6ServerAddress netip.Addr
3535 inet6Address netip.Addr
3636 broadcastAddr netip.Addr
37- udpTimeout int64
37+ udpTimeout time. Duration
3838 tcpListener net.Listener
3939 tcpListener6 net.Listener
4040 tcpPort uint16
4141 tcpPort6 uint16
4242 tcpNat * TCPNat
43- udpNat * udpnat.Service [netip. AddrPort ]
43+ udpNat * udpnat.Service
4444 bindInterface bool
4545 interfaceFinder control.InterfaceFinder
4646 frontHeadroom int
@@ -151,8 +151,8 @@ func (s *System) start() error {
151151 s .tcpPort6 = M .SocksaddrFromNet (tcpListener .Addr ()).Port
152152 go s .acceptLoop (tcpListener )
153153 }
154- s .tcpNat = NewNat (s .ctx , time . Second * time . Duration ( s .udpTimeout ) )
155- s .udpNat = udpnat .NewEx [netip. AddrPort ] (s .udpTimeout , s .handler )
154+ s .tcpNat = NewNat (s .ctx , s .udpTimeout )
155+ s .udpNat = udpnat .New (s .handler , s .preparePacketConnection , s . udpTimeout )
156156 return nil
157157}
158158
@@ -354,7 +354,11 @@ func (s *System) processIPv4TCP(packet clashtcpip.IPv4Packet, header clashtcpip.
354354 packet .SetDestinationIP (session .Source .Addr ())
355355 header .SetDestinationPort (session .Source .Port ())
356356 } else {
357- natPort := s .tcpNat .Lookup (source , destination )
357+ natPort , err := s .tcpNat .Lookup (source , destination , s .handler )
358+ if err != nil {
359+ // TODO: implement rejects
360+ return nil
361+ }
358362 packet .SetSourceIP (s .inet4Address )
359363 header .SetSourcePort (natPort )
360364 packet .SetDestinationIP (s .inet4ServerAddress )
@@ -385,7 +389,11 @@ func (s *System) processIPv6TCP(packet clashtcpip.IPv6Packet, header clashtcpip.
385389 packet .SetDestinationIP (session .Source .Addr ())
386390 header .SetDestinationPort (session .Source .Port ())
387391 } else {
388- natPort := s .tcpNat .Lookup (source , destination )
392+ natPort , err := s .tcpNat .Lookup (source , destination , s .handler )
393+ if err != nil {
394+ // TODO: implement rejects
395+ return nil
396+ }
389397 packet .SetSourceIP (s .inet6Address )
390398 header .SetSourcePort (natPort )
391399 packet .SetDestinationIP (s .inet6ServerAddress )
@@ -409,56 +417,61 @@ func (s *System) processIPv4UDP(packet clashtcpip.IPv4Packet, header clashtcpip.
409417 if ! header .Valid () {
410418 return E .New ("ipv4: udp: invalid packet" )
411419 }
412- source := netip . AddrPortFrom (packet .SourceIP (), header .SourcePort ())
413- destination := netip . AddrPortFrom (packet .DestinationIP (), header .DestinationPort ())
414- if ! destination .Addr () .IsGlobalUnicast () {
420+ source := M . SocksaddrFrom (packet .SourceIP (), header .SourcePort ())
421+ destination := M . SocksaddrFrom (packet .DestinationIP (), header .DestinationPort ())
422+ if ! destination .Addr .IsGlobalUnicast () {
415423 return nil
416424 }
417- data := buf .As (header .Payload ())
418- if data .Len () == 0 {
425+ s .udpNat .NewPacket ([][]byte {header .Payload ()}, source , destination , packet )
426+ return nil
427+ }
428+
429+ func (s * System ) processIPv6UDP (packet clashtcpip.IPv6Packet , header clashtcpip.UDPPacket ) error {
430+ if ! header .Valid () {
431+ return E .New ("ipv6: udp: invalid packet" )
432+ }
433+ source := M .SocksaddrFrom (packet .SourceIP (), header .SourcePort ())
434+ destination := M .SocksaddrFrom (packet .DestinationIP (), header .DestinationPort ())
435+ if ! destination .Addr .IsGlobalUnicast () {
419436 return nil
420437 }
421- s .udpNat .NewPacketEx (s .ctx , source , data .ToOwned (), M .SocksaddrFromNetIP (source ), M .SocksaddrFromNetIP (destination ), func (natConn N.PacketConn ) N.PacketWriter {
438+ s .udpNat .NewPacket ([][]byte {header .Payload ()}, source , destination , packet )
439+ return nil
440+ }
441+
442+ func (s * System ) preparePacketConnection (source M.Socksaddr , destination M.Socksaddr , userData any ) (bool , context.Context , N.PacketWriter , N.CloseHandlerFunc ) {
443+ pErr := s .handler .PrepareConnection (source , destination )
444+ if pErr != nil {
445+ // TODO: implement ICMP port unreachable
446+ return false , nil , nil , nil
447+ }
448+ var writer N.PacketWriter
449+ if source .IsIPv4 () {
450+ packet := userData .(clashtcpip.IPv4Packet )
422451 headerLen := packet .HeaderLen () + clashtcpip .UDPHeaderSize
423452 headerCopy := make ([]byte , headerLen )
424453 copy (headerCopy , packet [:headerLen ])
425- return & systemUDPPacketWriter4 {
454+ writer = & systemUDPPacketWriter4 {
426455 s .tun ,
427456 s .frontHeadroom + PacketOffset ,
428457 headerCopy ,
429- source ,
458+ source . AddrPort () ,
430459 s .txChecksumOffload ,
431460 }
432- })
433- return nil
434- }
435-
436- func (s * System ) processIPv6UDP (packet clashtcpip.IPv6Packet , header clashtcpip.UDPPacket ) error {
437- if ! header .Valid () {
438- return E .New ("ipv6: udp: invalid packet" )
439- }
440- source := netip .AddrPortFrom (packet .SourceIP (), header .SourcePort ())
441- destination := netip .AddrPortFrom (packet .DestinationIP (), header .DestinationPort ())
442- if ! destination .Addr ().IsGlobalUnicast () {
443- return nil
444- }
445- data := buf .As (header .Payload ())
446- if data .Len () == 0 {
447- return nil
448- }
449- s .udpNat .NewPacketEx (s .ctx , source , data .ToOwned (), M .SocksaddrFromNetIP (source ), M .SocksaddrFromNetIP (destination ), func (natConn N.PacketConn ) N.PacketWriter {
450- headerLen := len (packet ) - int (header .Length ()) + clashtcpip .UDPHeaderSize
461+ } else {
462+ packet := userData .(clashtcpip.IPv6Packet )
463+ headerLen := len (packet ) - int (packet .PayloadLength ()) + clashtcpip .UDPHeaderSize
451464 headerCopy := make ([]byte , headerLen )
452465 copy (headerCopy , packet [:headerLen ])
453- return & systemUDPPacketWriter6 {
466+ writer = & systemUDPPacketWriter6 {
454467 s .tun ,
455468 s .frontHeadroom + PacketOffset ,
456469 headerCopy ,
457- source ,
470+ source . AddrPort () ,
458471 s .txChecksumOffload ,
459472 }
460- })
461- return nil
473+ }
474+ return true , s . ctx , writer , nil
462475}
463476
464477func (s * System ) processIPv4ICMP (packet clashtcpip.IPv4Packet , header clashtcpip.ICMPPacket ) error {
0 commit comments