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  }