github.com/yaling888/clash@v1.53.0/listener/tun/ipstack/commons/router.go (about) 1 package commons 2 3 import ( 4 "errors" 5 "net/netip" 6 "sync" 7 "time" 8 9 "github.com/phuslu/log" 10 11 A "github.com/yaling888/clash/adapter" 12 "github.com/yaling888/clash/adapter/outbound" 13 "github.com/yaling888/clash/component/dialer" 14 "github.com/yaling888/clash/component/iface" 15 C "github.com/yaling888/clash/constant" 16 "github.com/yaling888/clash/constant/provider" 17 "github.com/yaling888/clash/tunnel" 18 ) 19 20 //nolint:unused 21 var ( 22 defaultRoutes = []string{ 23 "1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/6", "8.0.0.0/5", 24 "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/1", 25 } 26 27 monitorMux sync.Mutex 28 29 tunStatus = C.TunDisabled 30 tunChangeCallback C.TUNChangeCallback 31 errInterfaceNotFound = errors.New("default interface not found") 32 ) 33 34 type DefaultInterface struct { 35 Name string 36 Index int 37 IP netip.Addr 38 Gateway netip.Addr 39 } 40 41 func GetAutoDetectInterface() (string, error) { 42 var ( 43 retryOnFailure = true 44 tryTimes = 0 45 ) 46 startOver: 47 if tryTimes > 0 { 48 log.Info(). 49 Int("times", tryTimes). 50 Msg("[TUN] retrying lookup default interface after failure, maybe system just booted") 51 time.Sleep(time.Second) 52 retryOnFailure = retryOnFailure && tryTimes < 25 53 } 54 tryTimes++ 55 56 ifaceM, err := defaultRouteInterface() 57 if err != nil { 58 if err == errInterfaceNotFound && retryOnFailure { 59 goto startOver 60 } else { 61 return "", err 62 } 63 } 64 65 return ifaceM.Name, nil 66 } 67 68 func UpdateWireGuardBind() { 69 ps := tunnel.Proxies() 70 for _, p := range ps { 71 if p.Type() == C.WireGuard { 72 p.(*A.Proxy).ProxyAdapter.(*outbound.WireGuard).UpdateBind() 73 } 74 } 75 pds := tunnel.Providers() 76 for _, pd := range pds { 77 if pd.VehicleType() == provider.Compatible { 78 continue 79 } 80 for _, p := range pd.Proxies() { 81 if p.Type() == C.WireGuard { 82 p.(*A.Proxy).ProxyAdapter.(*outbound.WireGuard).UpdateBind() 83 } 84 } 85 } 86 } 87 88 func SetTunChangeCallback(callback C.TUNChangeCallback) { 89 tunChangeCallback = callback 90 } 91 92 func SetTunStatus(status C.TUNState) { 93 tunStatus = status 94 } 95 96 //nolint:unused 97 func onChangeDefaultRoute() { 98 routeInterface, err := defaultRouteInterface() 99 if err != nil { 100 if err == errInterfaceNotFound && tunStatus == C.TunEnabled { 101 log.Info().Msg("[Route] lost default interface, pause tun adapter") 102 103 tunStatus = C.TunPaused 104 tunChangeCallback.Pause() 105 } 106 return 107 } 108 109 interfaceName := routeInterface.Name 110 oldInterfaceName := dialer.DefaultInterface.Load() 111 if interfaceName == oldInterfaceName && tunStatus == C.TunEnabled { 112 return 113 } 114 115 dialer.DefaultInterface.Store(interfaceName) 116 117 iface.FlushCache() 118 UpdateWireGuardBind() 119 120 if tunStatus == C.TunPaused { 121 log.Info(). 122 Str("iface", interfaceName). 123 NetIPAddr("ip", routeInterface.IP). 124 NetIPAddr("gw", routeInterface.Gateway). 125 Msg("[Route] found default interface, resume tun adapter") 126 127 tunStatus = C.TunEnabled 128 tunChangeCallback.Resume() 129 return 130 } 131 132 log.Info(). 133 Str("oldIface", oldInterfaceName). 134 Str("newIface", interfaceName). 135 NetIPAddr("ip", routeInterface.IP). 136 NetIPAddr("gw", routeInterface.Gateway). 137 Msg("[Route] default interface changed") 138 }