diff --git a/config/config.go b/config/config.go index 38abf07a..a30c8c25 100644 --- a/config/config.go +++ b/config/config.go @@ -875,7 +875,7 @@ func parseAuthentication(rawRecords []string) []auth.AuthUser { func parseTun(rawTun RawTun, general *General) (*Tun, error) { if rawTun.Enable && rawTun.AutoDetectInterface { autoDetectInterfaceName, err := commons.GetAutoDetectInterface() - if err != nil || autoDetectInterfaceName == "" { + if err != nil { log.Warnln("Can not find auto detect interface.[%s]", err) } else { log.Warnln("Auto detect interface: %s", autoDetectInterfaceName) diff --git a/listener/listener.go b/listener/listener.go index f4efd356..79732b66 100644 --- a/listener/listener.go +++ b/listener/listener.go @@ -2,9 +2,11 @@ package proxy import ( "fmt" + "github.com/Dreamacro/clash/common/cmd" "github.com/Dreamacro/clash/listener/inner" "net" "os" + "runtime" "strconv" "sync" @@ -395,5 +397,8 @@ func genAddr(host string, port int, allowLan bool) string { func Cleanup() { if tunStackListener != nil { _ = tunStackListener.Close() + if runtime.GOOS == "android" { + _, _ = cmd.ExecCmd("ip rule del pref 5000") + } } } diff --git a/listener/tun/ipstack/commons/router.go b/listener/tun/ipstack/commons/router.go index c1eea999..c6c697e5 100644 --- a/listener/tun/ipstack/commons/router.go +++ b/listener/tun/ipstack/commons/router.go @@ -3,7 +3,6 @@ package commons import ( "fmt" "net" - "sync" "time" "github.com/Dreamacro/clash/component/dialer" @@ -12,7 +11,6 @@ import ( 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"} - mux sync.Mutex defaultInterfaceMonitorDuration = 3 * time.Second ) @@ -25,7 +23,7 @@ func ipv4MaskString(bits int) string { return fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3]) } -func DefaultInterfaceChangeMonitor(cb func(ifName string)) { +func DefaultInterfaceChangeMonitor() { t := time.NewTicker(defaultInterfaceMonitorDuration) defer t.Stop() @@ -44,9 +42,7 @@ func DefaultInterfaceChangeMonitor(cb func(ifName string)) { } dialer.DefaultInterface.Store(interfaceName) - if cb != nil { - cb(interfaceName) - } + log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, interfaceName) } } diff --git a/listener/tun/ipstack/commons/router_darwin.go b/listener/tun/ipstack/commons/router_darwin.go index 77f0abaf..9a5a18df 100644 --- a/listener/tun/ipstack/commons/router_darwin.go +++ b/listener/tun/ipstack/commons/router_darwin.go @@ -54,7 +54,7 @@ func configInterfaceRouting(interfaceName string, addr netip.Prefix) error { } } - go DefaultInterfaceChangeMonitor(nil) + go DefaultInterfaceChangeMonitor() return execRouterCmd("add", "-inet6", "2000::/3", interfaceName) } diff --git a/listener/tun/ipstack/commons/router_linux.go b/listener/tun/ipstack/commons/router_linux.go index be239989..34281d86 100644 --- a/listener/tun/ipstack/commons/router_linux.go +++ b/listener/tun/ipstack/commons/router_linux.go @@ -2,13 +2,17 @@ package commons import ( "fmt" - "net/netip" - "github.com/Dreamacro/clash/common/cmd" "github.com/Dreamacro/clash/listener/tun/device" + "github.com/Dreamacro/clash/log" + "net/netip" + "runtime" ) func GetAutoDetectInterface() (string, error) { + if runtime.GOOS == "android" { + return cmd.ExecCmd("sh -c ip route | awk 'NR==1{print $3}' | xargs echo -n") + } return cmd.ExecCmd("bash -c ip route show | grep 'default via' | awk -F ' ' 'NR==1{print $5}' | xargs echo -n") } @@ -35,14 +39,27 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, } func configInterfaceRouting(interfaceName string, addr netip.Prefix) error { - linkIP := addr.Masked().Addr().Next() - for _, route := range defaultRoutes { - if err := execRouterCmd("add", route, interfaceName, linkIP.String()); err != nil { - return err + if runtime.GOOS == "android" { + tableId := 1981801 + for _, route := range defaultRoutes { + if _, err := cmd.ExecCmd(fmt.Sprintf("ip route add %s dev %s scope link table %d", route, interfaceName, tableId)); err != nil { + return err + } + } + _, err := cmd.ExecCmd(fmt.Sprintf("ip rule add lookup %d suppress_prefixlength 0 pref 5000", tableId)) + if err != nil { + log.Warnln("%s", err) + } + } else { + linkIP := addr.Masked().Addr().Next() + for _, route := range defaultRoutes { + if err := execRouterCmd("add", route, interfaceName, linkIP.String()); err != nil { + return err + } } } - go DefaultInterfaceChangeMonitor(nil) + go DefaultInterfaceChangeMonitor() return nil } diff --git a/listener/tun/ipstack/commons/router_windows.go b/listener/tun/ipstack/commons/router_windows.go index e6fe8d5a..50a1cbba 100644 --- a/listener/tun/ipstack/commons/router_windows.go +++ b/listener/tun/ipstack/commons/router_windows.go @@ -205,7 +205,7 @@ startOver: wintunInterfaceName = dev.Name() - go DefaultInterfaceChangeMonitor(nil) + go DefaultInterfaceChangeMonitor() return nil }