refactor: 使用 netlink 配置 ip rule

This commit is contained in:
adlyq 2022-05-29 15:03:27 +08:00
parent 39e7832676
commit 13e907bbd0
4 changed files with 61 additions and 26 deletions

4
go.mod
View file

@ -16,7 +16,7 @@ require (
github.com/oschwald/geoip2-golang v1.7.0
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.1
github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86
github.com/vishvananda/netlink v1.2.0-beta.0.20220404152918-5e915e014938
github.com/xtls/go v0.0.0-20210920065950-d4af136d3672
go.etcd.io/bbolt v1.3.6
go.uber.org/atomic v1.9.0
@ -60,3 +60,5 @@ require (
)
replace golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 => github.com/MetaCubeX/wintun-go v0.0.0-20220319102620-bbc5e6b2015e
replace github.com/vishvananda/netlink v1.2.0-beta.0.20220404152918-5e915e014938 => github.com/MetaCubeX/netlink v1.2.0-beta.0.20220428021510-cbf1fc89c622

6
go.sum
View file

@ -10,6 +10,8 @@ git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGy
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Dreamacro/go-shadowsocks2 v0.1.8 h1:Ixejp5JscEc866gAvm/l6TFd7BOBvDviKgwb1quWw3g=
github.com/Dreamacro/go-shadowsocks2 v0.1.8/go.mod h1:51y4Q6tJoCE7e8TmYXcQRqfoxPfE9Cvn79V6pB6Df7Y=
github.com/MetaCubeX/netlink v1.2.0-beta.0.20220428021510-cbf1fc89c622 h1:Rs71V26e5N/5EEK2p2o2iG763sAjD4lit4ob061Tf9E=
github.com/MetaCubeX/netlink v1.2.0-beta.0.20220428021510-cbf1fc89c622/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
github.com/MetaCubeX/wintun-go v0.0.0-20220319102620-bbc5e6b2015e h1:GRfT5Lf8HP7RNczKIwTYLoCh1PPuIs/sY9hj+W+3deg=
github.com/MetaCubeX/wintun-go v0.0.0-20220319102620-bbc5e6b2015e/go.mod h1:ARUuShAtcziEJ/vnZ2hgoP+zc0J7Ukcca2S/NPDoQCc=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
@ -202,8 +204,7 @@ github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIz
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86 h1:7SWt9pGCMaw+N1ZhRsaLKaYNviFhxambdoaoYlDqz1w=
github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
github.com/xtls/go v0.0.0-20210920065950-d4af136d3672 h1:4mkzGhKqt3JO1BWYjtD3iRFyAx4ow67hmSqOcGjuxqQ=
@ -297,6 +298,7 @@ golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View file

@ -2,9 +2,9 @@ package proxy
import (
"fmt"
"github.com/Dreamacro/clash/common/cmd"
"github.com/Dreamacro/clash/listener/inner"
"github.com/Dreamacro/clash/listener/tun/ipstack/commons"
"github.com/vishvananda/netlink"
"net"
"runtime"
"sort"
@ -457,9 +457,13 @@ func Cleanup(wait bool) {
}
if runtime.GOOS == "android" {
prefs := []int{9000, 9001, 9002, 9003, 9004}
for _, pref := range prefs {
_, _ = cmd.ExecCmd(fmt.Sprintf("ip rule del pref %d", pref))
r := netlink.NewRule()
for i := 0; i < 5; i++ {
r.Priority = 9000 + i*10
err := netlink.RuleDel(r)
if err != nil {
log.Warnln("[TOUTE] cleanup route rule: %s", err)
}
}
}
}

View file

@ -57,6 +57,7 @@ func ConfigInterfaceAddress(dev device.Device, addr netip.Prefix, forceMTU int,
func configInterfaceRouting(index int, interfaceName string, ip netip.Addr) error {
const tableId = 1981801
var pref = 9000
for _, route := range defaultRoutes {
_, ipn, err := net.ParseCIDR(route)
@ -75,25 +76,51 @@ func configInterfaceRouting(index int, interfaceName string, ip netip.Addr) erro
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", 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))
logIfErr := func(e error) {
if e != nil {
log.Warnln("[TOUTE] config route rule: %s", e)
}
}
var r *netlink.Rule
r = netlink.NewRule()
r.Table = 254
r.Priority = pref
logIfErr(netlink.RuleAdd(r))
pref += 10
r = netlink.NewRule()
_, nl, _ := net.ParseCIDR("0.0.0.0/32")
r.Table = tableId
r.Priority = pref
r.Src = nl
r.IifName = "lo"
r.UID = netlink.NewRuleUIDRange(0, 4294967294)
logIfErr(netlink.RuleAdd(r))
pref += 10
_, nl, _ = net.ParseCIDR(ip.String())
r.Priority = pref
r.Src = nl
logIfErr(netlink.RuleAdd(r))
pref += 10
r = netlink.NewRule()
r.Table = 254
r.Priority = pref
r.IifName = interfaceName
r.SuppressPrefixlen = 0
logIfErr(netlink.RuleAdd(r))
pref += 10
r = netlink.NewRule()
r.Table = tableId
r.Priority = pref
r.IifName = "lo"
r.SuppressPrefixlen = 0
r.Invert = true
logIfErr(netlink.RuleAdd(r))
return nil
}
func execAddRuleCmd(rule string) {
_, err := cmd.ExecCmd("ip rule add " + rule)
if err != nil {
log.Warnln("%s", err)
}
}
func execRouterCmd(action, route, interfaceName, linkIP, table string) error {
cmdStr := fmt.Sprintf("ip route %s %s dev %s proto kernel scope link src %s table %s", action, route, interfaceName, linkIP, table)
_, err := cmd.ExecCmd(cmdStr)
return err
}