@@ -52,6 +52,8 @@ type Listener struct {
5252 autoRedirect tun.AutoRedirect
5353 autoRedirectOutputMark int32
5454
55+ cDialerInterfaceFinder dialer.InterfaceFinder
56+
5557 ruleUpdateCallbackCloser io.Closer
5658 ruleUpdateMutex sync.Mutex
5759 routeAddressMap map [string ]* netipx.IPSet
@@ -290,13 +292,25 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis
290292 }
291293 l .defaultInterfaceMonitor = defaultInterfaceMonitor
292294 defaultInterfaceMonitor .RegisterCallback (func (event int ) {
293- l .FlushDefaultInterface ()
295+ iface .FlushCache ()
296+ resolver .ResetConnection () // reset resolver's connection after default interface changed
294297 })
295298 err = defaultInterfaceMonitor .Start ()
296299 if err != nil {
297300 err = E .Cause (err , "start DefaultInterfaceMonitor" )
298301 return
299302 }
303+
304+ if options .AutoDetectInterface {
305+ l .cDialerInterfaceFinder = & cDialerInterfaceFinder {
306+ tunName : tunName ,
307+ defaultInterfaceMonitor : defaultInterfaceMonitor ,
308+ }
309+ if ! dialer .DefaultInterfaceFinder .CompareAndSwap (nil , l .cDialerInterfaceFinder ) {
310+ err = E .New ("don't allowed two tun listener using auto-detect-interface" )
311+ return
312+ }
313+ }
300314 }
301315
302316 tunOptions := tun.Options {
@@ -503,27 +517,25 @@ func (l *Listener) updateRule(ruleProvider provider.RuleProvider, exclude bool,
503517 }
504518}
505519
506- func (l * Listener ) FlushDefaultInterface () {
507- if l .options .AutoDetectInterface && l .defaultInterfaceMonitor != nil {
508- for _ , destination := range []netip.Addr {netip .IPv4Unspecified (), netip .IPv6Unspecified (), netip .MustParseAddr ("1.1.1.1" )} {
509- autoDetectInterfaceName := l .defaultInterfaceMonitor .DefaultInterfaceName (destination )
510- if autoDetectInterfaceName == l .tunName {
511- log .Warnln ("[TUN] Auto detect interface by %s get same name with tun" , destination .String ())
512- } else if autoDetectInterfaceName == "" || autoDetectInterfaceName == "<nil>" {
513- log .Warnln ("[TUN] Auto detect interface by %s get empty name." , destination .String ())
514- } else {
515- if old := dialer .DefaultInterface .Swap (autoDetectInterfaceName ); old != autoDetectInterfaceName {
516- log .Warnln ("[TUN] default interface changed by monitor, %s => %s" , old , autoDetectInterfaceName )
517- iface .FlushCache ()
518- resolver .ResetConnection () // reset resolver's connection after default interface changed
519- }
520- return
521- }
522- }
523- if dialer .DefaultInterface .CompareAndSwap ("" , "<invalid>" ) {
524- log .Warnln ("[TUN] Auto detect interface failed, set '<invalid>' to DefaultInterface to avoid lookback" )
520+ type cDialerInterfaceFinder struct {
521+ tunName string
522+ defaultInterfaceMonitor tun.DefaultInterfaceMonitor
523+ }
524+
525+ func (d * cDialerInterfaceFinder ) FindInterfaceName (destination netip.Addr ) string {
526+ for _ , dest := range []netip.Addr {destination , netip .IPv4Unspecified (), netip .IPv6Unspecified ()} {
527+ autoDetectInterfaceName := d .defaultInterfaceMonitor .DefaultInterfaceName (dest )
528+ if autoDetectInterfaceName == d .tunName {
529+ log .Warnln ("[TUN] Auto detect interface for %s get same name with tun" , destination .String ())
530+ } else if autoDetectInterfaceName == "" || autoDetectInterfaceName == "<nil>" {
531+ log .Warnln ("[TUN] Auto detect interface for %s get empty name." , destination .String ())
532+ } else {
533+ log .Debugln ("[TUN] Auto detect interface for %s --> %s" , destination , autoDetectInterfaceName )
534+ return autoDetectInterfaceName
525535 }
526536 }
537+ log .Warnln ("[TUN] Auto detect interface for %s failed, return '<invalid>' to avoid lookback" , destination )
538+ return "<invalid>"
527539}
528540
529541func uidToRange (uidList []uint32 ) []ranges.Range [uint32 ] {
@@ -564,6 +576,9 @@ func (l *Listener) Close() error {
564576 if l .autoRedirectOutputMark != 0 {
565577 dialer .DefaultRoutingMark .CompareAndSwap (l .autoRedirectOutputMark , 0 )
566578 }
579+ if l .cDialerInterfaceFinder != nil {
580+ dialer .DefaultInterfaceFinder .CompareAndSwap (l .cDialerInterfaceFinder , nil )
581+ }
567582 return common .Close (
568583 l .ruleUpdateCallbackCloser ,
569584 l .tunStack ,
0 commit comments