@@ -15,7 +15,7 @@ import (
15
15
"github.com/sagernet/sing/common/logger"
16
16
M "github.com/sagernet/sing/common/metadata"
17
17
N "github.com/sagernet/sing/common/network"
18
- "github.com/sagernet/sing/common/udpnat "
18
+ "github.com/sagernet/sing/common/udpnat2 "
19
19
)
20
20
21
21
var 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 {
34
34
inet6ServerAddress netip.Addr
35
35
inet6Address netip.Addr
36
36
broadcastAddr netip.Addr
37
- udpTimeout int64
37
+ udpTimeout time. Duration
38
38
tcpListener net.Listener
39
39
tcpListener6 net.Listener
40
40
tcpPort uint16
41
41
tcpPort6 uint16
42
42
tcpNat * TCPNat
43
- udpNat * udpnat.Service [netip. AddrPort ]
43
+ udpNat * udpnat.Service
44
44
bindInterface bool
45
45
interfaceFinder control.InterfaceFinder
46
46
frontHeadroom int
@@ -151,8 +151,8 @@ func (s *System) start() error {
151
151
s .tcpPort6 = M .SocksaddrFromNet (tcpListener .Addr ()).Port
152
152
go s .acceptLoop (tcpListener )
153
153
}
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 )
156
156
return nil
157
157
}
158
158
@@ -354,7 +354,11 @@ func (s *System) processIPv4TCP(packet clashtcpip.IPv4Packet, header clashtcpip.
354
354
packet .SetDestinationIP (session .Source .Addr ())
355
355
header .SetDestinationPort (session .Source .Port ())
356
356
} 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
+ }
358
362
packet .SetSourceIP (s .inet4Address )
359
363
header .SetSourcePort (natPort )
360
364
packet .SetDestinationIP (s .inet4ServerAddress )
@@ -385,7 +389,11 @@ func (s *System) processIPv6TCP(packet clashtcpip.IPv6Packet, header clashtcpip.
385
389
packet .SetDestinationIP (session .Source .Addr ())
386
390
header .SetDestinationPort (session .Source .Port ())
387
391
} 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
+ }
389
397
packet .SetSourceIP (s .inet6Address )
390
398
header .SetSourcePort (natPort )
391
399
packet .SetDestinationIP (s .inet6ServerAddress )
@@ -409,56 +417,61 @@ func (s *System) processIPv4UDP(packet clashtcpip.IPv4Packet, header clashtcpip.
409
417
if ! header .Valid () {
410
418
return E .New ("ipv4: udp: invalid packet" )
411
419
}
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 () {
415
423
return nil
416
424
}
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 () {
419
436
return nil
420
437
}
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 )
422
451
headerLen := packet .HeaderLen () + clashtcpip .UDPHeaderSize
423
452
headerCopy := make ([]byte , headerLen )
424
453
copy (headerCopy , packet [:headerLen ])
425
- return & systemUDPPacketWriter4 {
454
+ writer = & systemUDPPacketWriter4 {
426
455
s .tun ,
427
456
s .frontHeadroom + PacketOffset ,
428
457
headerCopy ,
429
- source ,
458
+ source . AddrPort () ,
430
459
s .txChecksumOffload ,
431
460
}
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
451
464
headerCopy := make ([]byte , headerLen )
452
465
copy (headerCopy , packet [:headerLen ])
453
- return & systemUDPPacketWriter6 {
466
+ writer = & systemUDPPacketWriter6 {
454
467
s .tun ,
455
468
s .frontHeadroom + PacketOffset ,
456
469
headerCopy ,
457
- source ,
470
+ source . AddrPort () ,
458
471
s .txChecksumOffload ,
459
472
}
460
- })
461
- return nil
473
+ }
474
+ return true , s . ctx , writer , nil
462
475
}
463
476
464
477
func (s * System ) processIPv4ICMP (packet clashtcpip.IPv4Packet , header clashtcpip.ICMPPacket ) error {
0 commit comments