@@ -22,30 +22,32 @@ import (
2222var ErrIncludeAllNetworks = E .New ("`system` and `mixed` stack are not available when `includeAllNetworks` is enabled. See https://github.com/SagerNet/sing-tun/issues/25" )
2323
2424type System struct {
25- ctx context.Context
26- tun Tun
27- tunName string
28- mtu int
29- handler Handler
30- logger logger.Logger
31- inet4Prefixes []netip.Prefix
32- inet6Prefixes []netip.Prefix
33- inet4ServerAddress netip.Addr
34- inet4Address netip.Addr
35- inet6ServerAddress netip.Addr
36- inet6Address netip.Addr
37- broadcastAddr netip.Addr
38- udpTimeout time.Duration
39- tcpListener net.Listener
40- tcpListener6 net.Listener
41- tcpPort uint16
42- tcpPort6 uint16
43- tcpNat * TCPNat
44- udpNat * udpnat.Service
45- bindInterface bool
46- interfaceFinder control.InterfaceFinder
47- frontHeadroom int
48- txChecksumOffload bool
25+ ctx context.Context
26+ tun Tun
27+ tunName string
28+ mtu int
29+ handler Handler
30+ logger logger.Logger
31+ inet4Prefixes []netip.Prefix
32+ inet6Prefixes []netip.Prefix
33+ inet4ServerAddress netip.Addr
34+ inet4Address netip.Addr
35+ inet6ServerAddress netip.Addr
36+ inet6Address netip.Addr
37+ broadcastAddr netip.Addr
38+ udpTimeout time.Duration
39+ inet4LocalRedirectAddress []netip.Addr
40+ inet6LocalRedirectAddress []netip.Addr
41+ tcpListener net.Listener
42+ tcpListener6 net.Listener
43+ tcpPort uint16
44+ tcpPort6 uint16
45+ tcpNat * TCPNat
46+ udpNat * udpnat.Service
47+ bindInterface bool
48+ interfaceFinder control.InterfaceFinder
49+ frontHeadroom int
50+ txChecksumOffload bool
4951}
5052
5153type Session struct {
@@ -57,18 +59,20 @@ type Session struct {
5759
5860func NewSystem (options StackOptions ) (Stack , error ) {
5961 stack := & System {
60- ctx : options .Context ,
61- tun : options .Tun ,
62- tunName : options .TunOptions .Name ,
63- mtu : int (options .TunOptions .MTU ),
64- udpTimeout : options .UDPTimeout ,
65- handler : options .Handler ,
66- logger : options .Logger ,
67- inet4Prefixes : options .TunOptions .Inet4Address ,
68- inet6Prefixes : options .TunOptions .Inet6Address ,
69- broadcastAddr : BroadcastAddr (options .TunOptions .Inet4Address ),
70- bindInterface : options .ForwarderBindInterface ,
71- interfaceFinder : options .InterfaceFinder ,
62+ ctx : options .Context ,
63+ tun : options .Tun ,
64+ tunName : options .TunOptions .Name ,
65+ mtu : int (options .TunOptions .MTU ),
66+ udpTimeout : options .UDPTimeout ,
67+ inet4LocalRedirectAddress : options .Inet4LocalRedirectAddress ,
68+ inet6LocalRedirectAddress : options .Inet6LocalRedirectAddress ,
69+ handler : options .Handler ,
70+ logger : options .Logger ,
71+ inet4Prefixes : options .TunOptions .Inet4Address ,
72+ inet6Prefixes : options .TunOptions .Inet6Address ,
73+ broadcastAddr : BroadcastAddr (options .TunOptions .Inet4Address ),
74+ bindInterface : options .ForwarderBindInterface ,
75+ interfaceFinder : options .InterfaceFinder ,
7276 }
7377 if len (options .TunOptions .Inet4Address ) > 0 {
7478 if ! HasNextAddress (options .TunOptions .Inet4Address [0 ], 1 ) {
@@ -352,18 +356,29 @@ func (s *System) processIPv4TCP(ipHdr header.IPv4, tcpHdr header.TCP) (bool, err
352356 ipHdr .SetDestinationAddr (session .Source .Addr ())
353357 tcpHdr .SetDestinationPort (session .Source .Port ())
354358 } else {
355- natPort , err := s .tcpNat .Lookup (source , destination , s .handler )
356- if err != nil {
357- if err == ErrDrop {
358- return false , nil
359- } else {
360- return false , s .resetIPv4TCP (ipHdr , tcpHdr )
359+ var localRedirect bool
360+ for _ , inet4LocalRedirectAddress := range s .inet4LocalRedirectAddress {
361+ if destination .Addr () == inet4LocalRedirectAddress {
362+ ipHdr .SetDestinationAddr (ipHdr .SourceAddr ())
363+ ipHdr .SetSourceAddr (inet4LocalRedirectAddress )
364+ localRedirect = true
365+ break
366+ }
367+ }
368+ if ! localRedirect {
369+ natPort , err := s .tcpNat .Lookup (source , destination , s .handler )
370+ if err != nil {
371+ if err == ErrDrop {
372+ return false , nil
373+ } else {
374+ return false , s .resetIPv4TCP (ipHdr , tcpHdr )
375+ }
361376 }
377+ ipHdr .SetSourceAddr (s .inet4Address )
378+ tcpHdr .SetSourcePort (natPort )
379+ ipHdr .SetDestinationAddr (s .inet4ServerAddress )
380+ tcpHdr .SetDestinationPort (s .tcpPort )
362381 }
363- ipHdr .SetSourceAddr (s .inet4Address )
364- tcpHdr .SetSourcePort (natPort )
365- ipHdr .SetDestinationAddr (s .inet4ServerAddress )
366- tcpHdr .SetDestinationPort (s .tcpPort )
367382 }
368383 if ! s .txChecksumOffload {
369384 tcpHdr .SetChecksum (0 )
@@ -439,18 +454,29 @@ func (s *System) processIPv6TCP(ipHdr header.IPv6, tcpHdr header.TCP) (bool, err
439454 ipHdr .SetDestinationAddr (session .Source .Addr ())
440455 tcpHdr .SetDestinationPort (session .Source .Port ())
441456 } else {
442- natPort , err := s .tcpNat .Lookup (source , destination , s .handler )
443- if err != nil {
444- if err == ErrDrop {
445- return false , nil
446- } else {
447- return false , s .resetIPv6TCP (ipHdr , tcpHdr )
457+ var localRedirect bool
458+ for _ , inet6LocalRedirectAddress := range s .inet6LocalRedirectAddress {
459+ if destination .Addr () == inet6LocalRedirectAddress {
460+ ipHdr .SetDestinationAddr (ipHdr .SourceAddr ())
461+ ipHdr .SetSourceAddr (inet6LocalRedirectAddress )
462+ localRedirect = true
463+ break
464+ }
465+ }
466+ if ! localRedirect {
467+ natPort , err := s .tcpNat .Lookup (source , destination , s .handler )
468+ if err != nil {
469+ if err == ErrDrop {
470+ return false , nil
471+ } else {
472+ return false , s .resetIPv6TCP (ipHdr , tcpHdr )
473+ }
448474 }
475+ ipHdr .SetSourceAddr (s .inet6Address )
476+ tcpHdr .SetSourcePort (natPort )
477+ ipHdr .SetDestinationAddr (s .inet6ServerAddress )
478+ tcpHdr .SetDestinationPort (s .tcpPort6 )
449479 }
450- ipHdr .SetSourceAddr (s .inet6Address )
451- tcpHdr .SetSourcePort (natPort )
452- ipHdr .SetDestinationAddr (s .inet6ServerAddress )
453- tcpHdr .SetDestinationPort (s .tcpPort6 )
454480 }
455481 if ! s .txChecksumOffload {
456482 tcpHdr .SetChecksum (0 )
0 commit comments