refactor: 合并部分android代码入linux && ip 使用netlink配置路由

This commit is contained in:
adlyq
2022-05-28 19:26:42 +08:00
parent fb4872ff7f
commit 9272d02149
4 changed files with 119 additions and 253 deletions

View File

@ -5,8 +5,9 @@ import (
"github.com/Dreamacro/clash/common/cmd"
"github.com/Dreamacro/clash/listener/tun/device"
"github.com/Dreamacro/clash/log"
"github.com/vishvananda/netlink"
"net"
"net/netip"
"strconv"
"strings"
)
@ -30,38 +31,63 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
ip = addr.Masked().Addr().Next()
)
_, err := cmd.ExecCmd(fmt.Sprintf("ip addr add %s dev %s", ip.String(), interfaceName))
metaLink, err := netlink.LinkByName(interfaceName)
if err != nil {
return err
}
_, err = cmd.ExecCmd(fmt.Sprintf("ip link set %s up", interfaceName))
naddr, err := netlink.ParseAddr(addr.String())
if err != nil {
return err
}
if err = execRouterCmd("add", addr.Masked().String(), interfaceName, ip.String(), "main"); err != nil {
if err = netlink.AddrAdd(metaLink, naddr); err != nil {
return err
}
if err = netlink.LinkSetUp(metaLink); err != nil {
return err
}
if err = netlink.RouteAdd(&netlink.Route{
LinkIndex: metaLink.Attrs().Index,
Scope: netlink.SCOPE_LINK,
Protocol: 2,
Src: ip.AsSlice(),
Table: 254,
}); err != nil {
return err
}
if autoRoute {
err = configInterfaceRouting(interfaceName, addr)
err = configInterfaceRouting(metaLink.Attrs().Index, interfaceName, ip)
}
return err
}
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
linkIP := addr.Masked().Addr().Next()
func configInterfaceRouting(index int, interfaceName string, ip netip.Addr) error {
const tableId = 1981801
for _, route := range defaultRoutes {
if err := execRouterCmd("add", route, interfaceName, linkIP.String(), strconv.Itoa(tableId)); err != nil {
_, ipn, err := net.ParseCIDR(route)
if err != nil {
return err
}
if err := netlink.RouteAdd(&netlink.Route{
LinkIndex: index,
Scope: netlink.SCOPE_LINK,
Protocol: 2,
Src: ip.AsSlice(),
Dst: ipn,
Table: 254,
}); err != nil {
return err
}
}
execAddRuleCmd(fmt.Sprintf("lookup main pref 9000"))
execAddRuleCmd(fmt.Sprintf("from 0.0.0.0 iif lo uidrange 0-4294967294 lookup %d pref 9001", tableId))
execAddRuleCmd(fmt.Sprintf("from %s iif lo uidrange 0-4294967294 lookup %d pref 9002", linkIP, tableId))
execAddRuleCmd(fmt.Sprintf("from %s iif lo uidrange 0-4294967294 lookup %d pref 9002", ip, tableId))
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))

View File

@ -6,15 +6,33 @@ import (
"fmt"
"github.com/Dreamacro/clash/common/cmd"
"github.com/Dreamacro/clash/listener/tun/device"
"github.com/vishvananda/netlink"
"net"
"net/netip"
)
func GetAutoDetectInterface() (string, error) {
execCmd, err := cmd.ExecCmd("bash -c ip route show | grep 'default via' | awk -F ' ' 'NR==1{print $5}' | xargs echo -n")
if execCmd == "" {
return "", fmt.Errorf("interface not found")
routes, err := netlink.RouteList(nil, netlink.FAMILY_V4)
if err != nil {
return "", err
}
return execCmd, err
for _, route := range routes {
if route.Dst == nil {
lk, err := netlink.LinkByIndex(route.LinkIndex)
if err != nil {
return "", err
}
if lk.Type() == "tuntap" {
continue
}
return lk.Attrs().Name, nil
}
}
return "", fmt.Errorf("interface not found")
}
func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int, autoRoute bool) error {
@ -23,29 +41,55 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
ip = addr.Masked().Addr().Next()
)
if _, err := cmd.ExecCmd(fmt.Sprintf("ip addr add %s dev %s", ip.String(), interfaceName)); err != nil {
metaLink, err := netlink.LinkByName(interfaceName)
if err != nil {
return err
}
if _, err := cmd.ExecCmd(fmt.Sprintf("ip link set %s up", interfaceName)); err != nil {
naddr, err := netlink.ParseAddr(addr.String())
if err != nil {
return err
}
if err := execRouterCmd("add", addr.Masked().String(), interfaceName, ip.String(), "main"); err != nil {
if err = netlink.AddrAdd(metaLink, naddr); err != nil {
return err
}
if err = netlink.LinkSetUp(metaLink); err != nil {
return err
}
if err = netlink.RouteAdd(&netlink.Route{
LinkIndex: metaLink.Attrs().Index,
Scope: netlink.SCOPE_LINK,
Protocol: 2,
Src: ip.AsSlice(),
Table: 254,
}); err != nil {
return err
}
if autoRoute {
_ = configInterfaceRouting(interfaceName, addr)
_ = configInterfaceRouting(metaLink.Attrs().Index, interfaceName, ip)
}
return nil
}
func configInterfaceRouting(interfaceName string, addr netip.Prefix) error {
linkIP := addr.Masked().Addr().Next()
func configInterfaceRouting(index int, interfaceName string, ip netip.Addr) error {
for _, route := range defaultRoutes {
if err := execRouterCmd("add", route, interfaceName, linkIP.String(), "main"); err != nil {
_, ipn, err := net.ParseCIDR(route)
if err != nil {
return err
}
if err := netlink.RouteAdd(&netlink.Route{
LinkIndex: index,
Scope: netlink.SCOPE_LINK,
Protocol: 2,
Src: ip.AsSlice(),
Dst: ipn,
Table: 254,
}); err != nil {
return err
}
}