Add loopback address support
This commit is contained in:
parent
f57754918d
commit
5e343c4b66
7 changed files with 524 additions and 183 deletions
138
stack_system.go
138
stack_system.go
|
|
@ -23,30 +23,32 @@ import (
|
|||
var ErrIncludeAllNetworks = E.New("`system` and `mixed` stack are not available when `includeAllNetworks` is enabled. See https://github.com/SagerNet/sing-tun/issues/25")
|
||||
|
||||
type System struct {
|
||||
ctx context.Context
|
||||
tun Tun
|
||||
tunName string
|
||||
mtu int
|
||||
handler Handler
|
||||
logger logger.Logger
|
||||
inet4Prefixes []netip.Prefix
|
||||
inet6Prefixes []netip.Prefix
|
||||
inet4ServerAddress netip.Addr
|
||||
inet4Address netip.Addr
|
||||
inet6ServerAddress netip.Addr
|
||||
inet6Address netip.Addr
|
||||
broadcastAddr netip.Addr
|
||||
udpTimeout time.Duration
|
||||
tcpListener net.Listener
|
||||
tcpListener6 net.Listener
|
||||
tcpPort uint16
|
||||
tcpPort6 uint16
|
||||
tcpNat *TCPNat
|
||||
udpNat *udpnat.Service
|
||||
bindInterface bool
|
||||
interfaceFinder control.InterfaceFinder
|
||||
frontHeadroom int
|
||||
txChecksumOffload bool
|
||||
ctx context.Context
|
||||
tun Tun
|
||||
tunName string
|
||||
mtu int
|
||||
handler Handler
|
||||
logger logger.Logger
|
||||
inet4Prefixes []netip.Prefix
|
||||
inet6Prefixes []netip.Prefix
|
||||
inet4ServerAddress netip.Addr
|
||||
inet4Address netip.Addr
|
||||
inet6ServerAddress netip.Addr
|
||||
inet6Address netip.Addr
|
||||
broadcastAddr netip.Addr
|
||||
inet4LoopbackAddress []netip.Addr
|
||||
inet6LoopbackAddress []netip.Addr
|
||||
udpTimeout time.Duration
|
||||
tcpListener net.Listener
|
||||
tcpListener6 net.Listener
|
||||
tcpPort uint16
|
||||
tcpPort6 uint16
|
||||
tcpNat *TCPNat
|
||||
udpNat *udpnat.Service
|
||||
bindInterface bool
|
||||
interfaceFinder control.InterfaceFinder
|
||||
frontHeadroom int
|
||||
txChecksumOffload bool
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
|
|
@ -58,18 +60,20 @@ type Session struct {
|
|||
|
||||
func NewSystem(options StackOptions) (Stack, error) {
|
||||
stack := &System{
|
||||
ctx: options.Context,
|
||||
tun: options.Tun,
|
||||
tunName: options.TunOptions.Name,
|
||||
mtu: int(options.TunOptions.MTU),
|
||||
udpTimeout: options.UDPTimeout,
|
||||
handler: options.Handler,
|
||||
logger: options.Logger,
|
||||
inet4Prefixes: options.TunOptions.Inet4Address,
|
||||
inet6Prefixes: options.TunOptions.Inet6Address,
|
||||
broadcastAddr: BroadcastAddr(options.TunOptions.Inet4Address),
|
||||
bindInterface: options.ForwarderBindInterface,
|
||||
interfaceFinder: options.InterfaceFinder,
|
||||
ctx: options.Context,
|
||||
tun: options.Tun,
|
||||
tunName: options.TunOptions.Name,
|
||||
mtu: int(options.TunOptions.MTU),
|
||||
inet4LoopbackAddress: options.TunOptions.Inet4LoopbackAddress,
|
||||
inet6LoopbackAddress: options.TunOptions.Inet6LoopbackAddress,
|
||||
udpTimeout: options.UDPTimeout,
|
||||
handler: options.Handler,
|
||||
logger: options.Logger,
|
||||
inet4Prefixes: options.TunOptions.Inet4Address,
|
||||
inet6Prefixes: options.TunOptions.Inet6Address,
|
||||
broadcastAddr: BroadcastAddr(options.TunOptions.Inet4Address),
|
||||
bindInterface: options.ForwarderBindInterface,
|
||||
interfaceFinder: options.InterfaceFinder,
|
||||
}
|
||||
if len(options.TunOptions.Inet4Address) > 0 {
|
||||
if !HasNextAddress(options.TunOptions.Inet4Address[0], 1) {
|
||||
|
|
@ -353,18 +357,29 @@ func (s *System) processIPv4TCP(ipHdr header.IPv4, tcpHdr header.TCP) (bool, err
|
|||
ipHdr.SetDestinationAddr(session.Source.Addr())
|
||||
tcpHdr.SetDestinationPort(session.Source.Port())
|
||||
} else {
|
||||
natPort, err := s.tcpNat.Lookup(source, destination, s.handler)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrDrop) {
|
||||
return false, nil
|
||||
} else {
|
||||
return false, s.resetIPv4TCP(ipHdr, tcpHdr)
|
||||
var loopback bool
|
||||
for _, inet4LoopbackAddress := range s.inet4LoopbackAddress {
|
||||
if destination.Addr() == inet4LoopbackAddress {
|
||||
ipHdr.SetDestinationAddr(ipHdr.SourceAddr())
|
||||
ipHdr.SetSourceAddr(inet4LoopbackAddress)
|
||||
loopback = true
|
||||
break
|
||||
}
|
||||
}
|
||||
ipHdr.SetSourceAddr(s.inet4Address)
|
||||
tcpHdr.SetSourcePort(natPort)
|
||||
ipHdr.SetDestinationAddr(s.inet4ServerAddress)
|
||||
tcpHdr.SetDestinationPort(s.tcpPort)
|
||||
if !loopback {
|
||||
natPort, err := s.tcpNat.Lookup(source, destination, s.handler)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrDrop) {
|
||||
return false, nil
|
||||
} else {
|
||||
return false, s.resetIPv4TCP(ipHdr, tcpHdr)
|
||||
}
|
||||
}
|
||||
ipHdr.SetSourceAddr(s.inet4Address)
|
||||
tcpHdr.SetSourcePort(natPort)
|
||||
ipHdr.SetDestinationAddr(s.inet4ServerAddress)
|
||||
tcpHdr.SetDestinationPort(s.tcpPort)
|
||||
}
|
||||
}
|
||||
if !s.txChecksumOffload {
|
||||
tcpHdr.SetChecksum(0)
|
||||
|
|
@ -440,18 +455,29 @@ func (s *System) processIPv6TCP(ipHdr header.IPv6, tcpHdr header.TCP) (bool, err
|
|||
ipHdr.SetDestinationAddr(session.Source.Addr())
|
||||
tcpHdr.SetDestinationPort(session.Source.Port())
|
||||
} else {
|
||||
natPort, err := s.tcpNat.Lookup(source, destination, s.handler)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrDrop) {
|
||||
return false, nil
|
||||
} else {
|
||||
return false, s.resetIPv6TCP(ipHdr, tcpHdr)
|
||||
var loopback bool
|
||||
for _, inet6LoopbackAddress := range s.inet6LoopbackAddress {
|
||||
if destination.Addr() == inet6LoopbackAddress {
|
||||
ipHdr.SetDestinationAddr(ipHdr.SourceAddr())
|
||||
ipHdr.SetSourceAddr(inet6LoopbackAddress)
|
||||
loopback = true
|
||||
break
|
||||
}
|
||||
}
|
||||
ipHdr.SetSourceAddr(s.inet6Address)
|
||||
tcpHdr.SetSourcePort(natPort)
|
||||
ipHdr.SetDestinationAddr(s.inet6ServerAddress)
|
||||
tcpHdr.SetDestinationPort(s.tcpPort6)
|
||||
if !loopback {
|
||||
natPort, err := s.tcpNat.Lookup(source, destination, s.handler)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrDrop) {
|
||||
return false, nil
|
||||
} else {
|
||||
return false, s.resetIPv6TCP(ipHdr, tcpHdr)
|
||||
}
|
||||
}
|
||||
ipHdr.SetSourceAddr(s.inet6Address)
|
||||
tcpHdr.SetSourcePort(natPort)
|
||||
ipHdr.SetDestinationAddr(s.inet6ServerAddress)
|
||||
tcpHdr.SetDestinationPort(s.tcpPort6)
|
||||
}
|
||||
}
|
||||
if !s.txChecksumOffload {
|
||||
tcpHdr.SetChecksum(0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue