fix: 热重载Tun配置
This commit is contained in:
@ -2,16 +2,21 @@ package commons
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/Dreamacro/clash/component/dialer"
|
||||
"github.com/Dreamacro/clash/component/iface"
|
||||
"github.com/Dreamacro/clash/log"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultRoutes = []string{"1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/6", "8.0.0.0/5", "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/1"}
|
||||
defaultInterfaceMonitorDuration = 3 * time.Second
|
||||
defaultRoutes = []string{"1.0.0.0/8", "2.0.0.0/7", "4.0.0.0/6", "8.0.0.0/5", "16.0.0.0/4", "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/1"}
|
||||
|
||||
monitorDuration = 3 * time.Second
|
||||
monitorStarted = false
|
||||
monitorStop = make(chan struct{}, 2)
|
||||
monitorMux sync.Mutex
|
||||
)
|
||||
|
||||
func ipv4MaskString(bits int) string {
|
||||
@ -23,26 +28,80 @@ func ipv4MaskString(bits int) string {
|
||||
return fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
|
||||
}
|
||||
|
||||
func DefaultInterfaceChangeMonitor() {
|
||||
t := time.NewTicker(defaultInterfaceMonitorDuration)
|
||||
defer t.Stop()
|
||||
func StartDefaultInterfaceChangeMonitor() {
|
||||
go func() {
|
||||
monitorMux.Lock()
|
||||
if monitorStarted {
|
||||
monitorMux.Unlock()
|
||||
return
|
||||
}
|
||||
monitorStarted = true
|
||||
monitorMux.Unlock()
|
||||
|
||||
for {
|
||||
<-t.C
|
||||
|
||||
interfaceName, err := GetAutoDetectInterface()
|
||||
if err != nil {
|
||||
log.Warnln("[TUN] default interface monitor exited, cause: %v", err)
|
||||
continue
|
||||
select {
|
||||
case <-monitorStop:
|
||||
default:
|
||||
}
|
||||
|
||||
old := dialer.DefaultInterface.Load()
|
||||
if interfaceName == old {
|
||||
continue
|
||||
t := time.NewTicker(monitorDuration)
|
||||
defer t.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-t.C:
|
||||
interfaceName, err := GetAutoDetectInterface()
|
||||
if err != nil {
|
||||
log.Warnln("[TUN] default interface monitor err: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
old := dialer.DefaultInterface.Load()
|
||||
if interfaceName == old {
|
||||
continue
|
||||
}
|
||||
|
||||
dialer.DefaultInterface.Store(interfaceName)
|
||||
iface.FlushCache()
|
||||
|
||||
log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, interfaceName)
|
||||
case <-monitorStop:
|
||||
break
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
dialer.DefaultInterface.Store(interfaceName)
|
||||
func StopDefaultInterfaceChangeMonitor() {
|
||||
monitorMux.Lock()
|
||||
defer monitorMux.Unlock()
|
||||
|
||||
log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, interfaceName)
|
||||
if monitorStarted {
|
||||
monitorStop <- struct{}{}
|
||||
monitorStarted = false
|
||||
}
|
||||
}
|
||||
|
||||
func WaitForTunClose(deviceName string) {
|
||||
t := time.NewTicker(600 * time.Millisecond)
|
||||
defer t.Stop()
|
||||
log.Debugln("[TUN] waiting for device close")
|
||||
for {
|
||||
<-t.C
|
||||
interfaces, err := net.Interfaces()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
found := false
|
||||
for i := len(interfaces) - 1; i > -1; i-- {
|
||||
if interfaces[i].Name == deviceName {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func GetAutoDetectInterface() (ifn string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute, autoDetectInterface bool) error {
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute bool) error {
|
||||
var (
|
||||
interfaceName = dev.Name()
|
||||
ip = addr.Masked().Addr().Next()
|
||||
@ -45,12 +45,12 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||
}
|
||||
|
||||
if autoRoute {
|
||||
err = configInterfaceRouting(interfaceName, addr, autoDetectInterface)
|
||||
err = configInterfaceRouting(interfaceName, addr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix, autoDetectInterface bool) error {
|
||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
|
||||
linkIP := addr.Masked().Addr().Next()
|
||||
const tableId = 1981801
|
||||
|
||||
@ -65,10 +65,6 @@ func configInterfaceRouting(interfaceName string, addr netip.Prefix, autoDetectI
|
||||
execAddRuleCmd(fmt.Sprintf("from all iif %s lookup main suppress_prefixlength 0 pref 9003", interfaceName))
|
||||
execAddRuleCmd(fmt.Sprintf("not from all iif lo lookup %d pref 9004", tableId))
|
||||
|
||||
if autoDetectInterface {
|
||||
go DefaultInterfaceChangeMonitor()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ func GetAutoDetectInterface() (string, error) {
|
||||
return cmd.ExecCmd("bash -c route -n get default | grep 'interface:' | awk -F ' ' 'NR==1{print $2}' | xargs echo -n")
|
||||
}
|
||||
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute, autoDetectInterface bool) error {
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute bool) error {
|
||||
if !addr.Addr().Is4() {
|
||||
return fmt.Errorf("supported ipv4 only")
|
||||
}
|
||||
@ -37,12 +37,12 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||
}
|
||||
|
||||
if autoRoute {
|
||||
err = configInterfaceRouting(interfaceName, addr, autoDetectInterface)
|
||||
err = configInterfaceRouting(interfaceName, addr)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix, autoDetectInterface bool) error {
|
||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
|
||||
var (
|
||||
routes = append(defaultRoutes, addr.String())
|
||||
gateway = addr.Masked().Addr().Next()
|
||||
@ -54,10 +54,6 @@ func configInterfaceRouting(interfaceName string, addr netip.Prefix, autoDetectI
|
||||
}
|
||||
}
|
||||
|
||||
if autoDetectInterface {
|
||||
go DefaultInterfaceChangeMonitor()
|
||||
}
|
||||
|
||||
return execRouterCmd("add", "-inet6", "2000::/3", interfaceName)
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ func GetAutoDetectInterface() (string, error) {
|
||||
return cmd.ExecCmd("bash -c ip route show | grep 'default via' | awk -F ' ' 'NR==1{print $5}' | xargs echo -n")
|
||||
}
|
||||
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute, autoDetectInterface bool) error {
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute bool) error {
|
||||
var (
|
||||
interfaceName = dev.Name()
|
||||
ip = addr.Masked().Addr().Next()
|
||||
@ -32,12 +32,12 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
|
||||
}
|
||||
|
||||
if autoRoute {
|
||||
_ = configInterfaceRouting(interfaceName, addr, autoDetectInterface)
|
||||
_ = configInterfaceRouting(interfaceName, addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix, autoDetectInterface bool) error {
|
||||
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
|
||||
linkIP := addr.Masked().Addr().Next()
|
||||
|
||||
for _, route := range defaultRoutes {
|
||||
@ -46,10 +46,6 @@ func configInterfaceRouting(interfaceName string, addr netip.Prefix, autoDetectI
|
||||
}
|
||||
}
|
||||
|
||||
if autoDetectInterface {
|
||||
go DefaultInterfaceChangeMonitor()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,6 @@ func GetAutoDetectInterface() (string, error) {
|
||||
return "", fmt.Errorf("can not auto detect interface-name on this OS: %s, you must be detecting interface-name by manual", runtime.GOOS)
|
||||
}
|
||||
|
||||
func ConfigInterfaceAddress(device.Device, netip.Prefix, int, bool, bool) error {
|
||||
func ConfigInterfaceAddress(device.Device, netip.Prefix, int, bool) error {
|
||||
return fmt.Errorf("unsupported on this OS: %s", runtime.GOOS)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func GetAutoDetectInterface() (string, error) {
|
||||
return getAutoDetectInterfaceByFamily(winipcfg.AddressFamily(windows.AF_INET6))
|
||||
}
|
||||
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute, autoDetectInterface bool) error {
|
||||
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute bool) error {
|
||||
retryOnFailure := services.StartedAtBoot()
|
||||
tryTimes := 0
|
||||
var err error
|
||||
@ -205,10 +205,6 @@ startOver:
|
||||
|
||||
wintunInterfaceName = dev.Name()
|
||||
|
||||
if autoDetectInterface {
|
||||
go DefaultInterfaceChangeMonitor()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
// New TunAdapter
|
||||
func New(tunConf *config.Tun, tunAddressPrefix *netip.Prefix, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) {
|
||||
func New(tunConf *config.Tun, tcpIn chan<- C.ConnContext, udpIn chan<- *inbound.PacketAdapter) (ipstack.Stack, error) {
|
||||
|
||||
var (
|
||||
tunAddress = netip.Prefix{}
|
||||
@ -38,8 +38,8 @@ func New(tunConf *config.Tun, tunAddressPrefix *netip.Prefix, tcpIn chan<- C.Con
|
||||
err error
|
||||
)
|
||||
|
||||
if tunAddressPrefix != nil {
|
||||
tunAddress = *tunAddressPrefix
|
||||
if tunConf.TunAddressPrefix != nil {
|
||||
tunAddress = *tunConf.TunAddressPrefix
|
||||
}
|
||||
|
||||
if devName == "" {
|
||||
@ -90,12 +90,16 @@ func New(tunConf *config.Tun, tunAddressPrefix *netip.Prefix, tcpIn chan<- C.Con
|
||||
}
|
||||
|
||||
// setting address and routing
|
||||
err = commons.ConfigInterfaceAddress(tunDevice, tunAddress, mtu, autoRoute, tunConf.AutoDetectInterface)
|
||||
err = commons.ConfigInterfaceAddress(tunDevice, tunAddress, mtu, autoRoute)
|
||||
if err != nil {
|
||||
_ = tunDevice.Close()
|
||||
return nil, fmt.Errorf("setting interface address and routing failed: %w", err)
|
||||
}
|
||||
|
||||
if tunConf.AutoDetectInterface {
|
||||
commons.StartDefaultInterfaceChangeMonitor()
|
||||
}
|
||||
|
||||
setAtLatest(stackType, devName)
|
||||
|
||||
log.Infoln("TUN stack listening at: %s(%s), mtu: %d, auto route: %v, ip stack: %s", tunDevice.Name(), tunAddress.Masked().Addr().Next().String(), mtu, autoRoute, stackType)
|
||||
|
Reference in New Issue
Block a user