chore: dialer will consider the routing of the local interface when auto-detect-interface in tun is enabled

for #1881 #1819
This commit is contained in:
wwqgtxx
2025-03-10 10:45:07 +08:00
parent 00e6466153
commit 4bd3ae52bd
5 changed files with 65 additions and 31 deletions

View File

@@ -512,9 +512,6 @@ func ReCreateTun(tunConf LC.Tun, tunnel C.Tunnel) {
}()
if tunConf.Equal(LastTunConf) {
if tunLister != nil {
tunLister.FlushDefaultInterface()
}
return
}

View File

@@ -52,6 +52,8 @@ type Listener struct {
autoRedirect tun.AutoRedirect
autoRedirectOutputMark int32
cDialerInterfaceFinder dialer.InterfaceFinder
ruleUpdateCallbackCloser io.Closer
ruleUpdateMutex sync.Mutex
routeAddressMap map[string]*netipx.IPSet
@@ -290,13 +292,25 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
}
l.defaultInterfaceMonitor = defaultInterfaceMonitor
defaultInterfaceMonitor.RegisterCallback(func(event int) {
l.FlushDefaultInterface()
iface.FlushCache()
resolver.ResetConnection() // reset resolver's connection after default interface changed
})
err = defaultInterfaceMonitor.Start()
if err != nil {
err = E.Cause(err, "start DefaultInterfaceMonitor")
return
}
if options.AutoDetectInterface {
l.cDialerInterfaceFinder = &cDialerInterfaceFinder{
tunName: tunName,
defaultInterfaceMonitor: defaultInterfaceMonitor,
}
if !dialer.DefaultInterfaceFinder.CompareAndSwap(nil, l.cDialerInterfaceFinder) {
err = E.New("don't allowed two tun listener using auto-detect-interface")
return
}
}
}
tunOptions := tun.Options{
@@ -503,27 +517,25 @@ func (l *Listener) updateRule(ruleProvider provider.RuleProvider, exclude bool,
}
}
func (l *Listener) FlushDefaultInterface() {
if l.options.AutoDetectInterface && l.defaultInterfaceMonitor != nil {
for _, destination := range []netip.Addr{netip.IPv4Unspecified(), netip.IPv6Unspecified(), netip.MustParseAddr("1.1.1.1")} {
autoDetectInterfaceName := l.defaultInterfaceMonitor.DefaultInterfaceName(destination)
if autoDetectInterfaceName == l.tunName {
log.Warnln("[TUN] Auto detect interface by %s get same name with tun", destination.String())
} else if autoDetectInterfaceName == "" || autoDetectInterfaceName == "<nil>" {
log.Warnln("[TUN] Auto detect interface by %s get empty name.", destination.String())
} else {
if old := dialer.DefaultInterface.Swap(autoDetectInterfaceName); old != autoDetectInterfaceName {
log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, autoDetectInterfaceName)
iface.FlushCache()
resolver.ResetConnection() // reset resolver's connection after default interface changed
}
return
}
}
if dialer.DefaultInterface.CompareAndSwap("", "<invalid>") {
log.Warnln("[TUN] Auto detect interface failed, set '<invalid>' to DefaultInterface to avoid lookback")
type cDialerInterfaceFinder struct {
tunName string
defaultInterfaceMonitor tun.DefaultInterfaceMonitor
}
func (d *cDialerInterfaceFinder) FindInterfaceName(destination netip.Addr) string {
for _, dest := range []netip.Addr{destination, netip.IPv4Unspecified(), netip.IPv6Unspecified()} {
autoDetectInterfaceName := d.defaultInterfaceMonitor.DefaultInterfaceName(dest)
if autoDetectInterfaceName == d.tunName {
log.Warnln("[TUN] Auto detect interface for %s get same name with tun", destination.String())
} else if autoDetectInterfaceName == "" || autoDetectInterfaceName == "<nil>" {
log.Warnln("[TUN] Auto detect interface for %s get empty name.", destination.String())
} else {
log.Debugln("[TUN] Auto detect interface for %s --> %s", destination, autoDetectInterfaceName)
return autoDetectInterfaceName
}
}
log.Warnln("[TUN] Auto detect interface for %s failed, return '<invalid>' to avoid lookback", destination)
return "<invalid>"
}
func uidToRange(uidList []uint32) []ranges.Range[uint32] {
@@ -564,6 +576,9 @@ func (l *Listener) Close() error {
if l.autoRedirectOutputMark != 0 {
dialer.DefaultRoutingMark.CompareAndSwap(l.autoRedirectOutputMark, 0)
}
if l.cDialerInterfaceFinder != nil {
dialer.DefaultInterfaceFinder.CompareAndSwap(l.cDialerInterfaceFinder, nil)
}
return common.Close(
l.ruleUpdateCallbackCloser,
l.tunStack,