mirror of
https://github.com/MetaCubeX/mihomo.git
synced 2026-02-26 08:47:09 +00:00
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:
@@ -512,9 +512,6 @@ func ReCreateTun(tunConf LC.Tun, tunnel C.Tunnel) {
|
||||
}()
|
||||
|
||||
if tunConf.Equal(LastTunConf) {
|
||||
if tunLister != nil {
|
||||
tunLister.FlushDefaultInterface()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user