[fix] auto-route for android

This commit is contained in:
adlyq 2022-04-20 22:00:05 +08:00
parent f40c2eb71d
commit 4b79f8de93
6 changed files with 34 additions and 16 deletions

View file

@ -875,7 +875,7 @@ func parseAuthentication(rawRecords []string) []auth.AuthUser {
func parseTun(rawTun RawTun, general *General) (*Tun, error) { func parseTun(rawTun RawTun, general *General) (*Tun, error) {
if rawTun.Enable && rawTun.AutoDetectInterface { if rawTun.Enable && rawTun.AutoDetectInterface {
autoDetectInterfaceName, err := commons.GetAutoDetectInterface() autoDetectInterfaceName, err := commons.GetAutoDetectInterface()
if err != nil || autoDetectInterfaceName == "" { if err != nil {
log.Warnln("Can not find auto detect interface.[%s]", err) log.Warnln("Can not find auto detect interface.[%s]", err)
} else { } else {
log.Warnln("Auto detect interface: %s", autoDetectInterfaceName) log.Warnln("Auto detect interface: %s", autoDetectInterfaceName)

View file

@ -2,9 +2,11 @@ package proxy
import ( import (
"fmt" "fmt"
"github.com/Dreamacro/clash/common/cmd"
"github.com/Dreamacro/clash/listener/inner" "github.com/Dreamacro/clash/listener/inner"
"net" "net"
"os" "os"
"runtime"
"strconv" "strconv"
"sync" "sync"
@ -395,5 +397,8 @@ func genAddr(host string, port int, allowLan bool) string {
func Cleanup() { func Cleanup() {
if tunStackListener != nil { if tunStackListener != nil {
_ = tunStackListener.Close() _ = tunStackListener.Close()
if runtime.GOOS == "android" {
_, _ = cmd.ExecCmd("ip rule del pref 5000")
}
} }
} }

View file

@ -3,7 +3,6 @@ package commons
import ( import (
"fmt" "fmt"
"net" "net"
"sync"
"time" "time"
"github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/dialer"
@ -12,7 +11,6 @@ import (
var ( 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"} 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 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]) 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) t := time.NewTicker(defaultInterfaceMonitorDuration)
defer t.Stop() defer t.Stop()
@ -44,9 +42,7 @@ func DefaultInterfaceChangeMonitor(cb func(ifName string)) {
} }
dialer.DefaultInterface.Store(interfaceName) dialer.DefaultInterface.Store(interfaceName)
if cb != nil {
cb(interfaceName)
}
log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, interfaceName) log.Warnln("[TUN] default interface changed by monitor, %s => %s", old, interfaceName)
} }
} }

View file

@ -54,7 +54,7 @@ func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
} }
} }
go DefaultInterfaceChangeMonitor(nil) go DefaultInterfaceChangeMonitor()
return execRouterCmd("add", "-inet6", "2000::/3", interfaceName) return execRouterCmd("add", "-inet6", "2000::/3", interfaceName)
} }

View file

@ -2,13 +2,17 @@ package commons
import ( import (
"fmt" "fmt"
"net/netip"
"github.com/Dreamacro/clash/common/cmd" "github.com/Dreamacro/clash/common/cmd"
"github.com/Dreamacro/clash/listener/tun/device" "github.com/Dreamacro/clash/listener/tun/device"
"github.com/Dreamacro/clash/log"
"net/netip"
"runtime"
) )
func GetAutoDetectInterface() (string, error) { 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") 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 { func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
linkIP := addr.Masked().Addr().Next() if runtime.GOOS == "android" {
for _, route := range defaultRoutes { tableId := 1981801
if err := execRouterCmd("add", route, interfaceName, linkIP.String()); err != nil { for _, route := range defaultRoutes {
return err 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 return nil
} }

View file

@ -205,7 +205,7 @@ startOver:
wintunInterfaceName = dev.Name() wintunInterfaceName = dev.Name()
go DefaultInterfaceChangeMonitor(nil) go DefaultInterfaceChangeMonitor()
return nil return nil
} }