From 99492e0d70a1cf1d65553b3f2e5c6d4fc8cfec50 Mon Sep 17 00:00:00 2001 From: XYenon Date: Mon, 10 Oct 2022 13:26:16 +0800 Subject: [PATCH] Add custom route support (#2) --- go.mod | 4 ++-- go.sum | 8 ++++---- tun.go | 2 ++ tun_darwin.go | 45 ++++++++++++++++++++++++++++++--------------- tun_linux.go | 50 ++++++++++++++++++++++++++++++++++++++------------ tun_windows.go | 30 ++++++++++++++++++++++++------ 6 files changed, 100 insertions(+), 39 deletions(-) diff --git a/go.mod b/go.mod index eca1774..e2f8638 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,8 @@ require ( github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 github.com/sagernet/sing v0.0.0-20220929000216-9a83e35b7186 - golang.org/x/net v0.0.0-20220927171203-f486391704dc - golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec + golang.org/x/net v0.0.0-20221004154528-8021a29435af + golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c ) diff --git a/go.sum b/go.sum index 1f51580..05c14a8 100644 --- a/go.sum +++ b/go.sum @@ -13,13 +13,13 @@ github.com/sagernet/sing v0.0.0-20220929000216-9a83e35b7186 h1:ZDlgH6dTozS3ODaYq github.com/sagernet/sing v0.0.0-20220929000216-9a83e35b7186/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4= 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= -golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ= -golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= +golang.org/x/net v0.0.0-20221004154528-8021a29435af h1:wv66FM3rLZGPdxpYL+ApnDe2HzHcTFta3z5nsc13wI4= +golang.org/x/net v0.0.0-20221004154528-8021a29435af/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI= -golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 h1:AzgQNqF+FKwyQ5LbVrVqOcuuFB67N47F9+htZYH0wFM= +golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4= diff --git a/tun.go b/tun.go index f070795..067607a 100644 --- a/tun.go +++ b/tun.go @@ -37,6 +37,8 @@ type Options struct { MTU uint32 AutoRoute bool StrictRoute bool + Inet4RouteAddress []netip.Prefix + Inet6RouteAddress []netip.Prefix IncludeUID []ranges.Range[uint32] ExcludeUID []ranges.Range[uint32] IncludeAndroidUser []int diff --git a/tun_darwin.go b/tun_darwin.go index b7d9048..e849bec 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -241,27 +241,42 @@ func configure(tunFd int, ifIndex int, name string, options Options) error { } if options.AutoRoute { if len(options.Inet4Address) > 0 { - for _, subnet := range []netip.Prefix{ - netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 0, 0, 0}), 8), - netip.PrefixFrom(netip.AddrFrom4([4]byte{2, 0, 0, 0}), 7), - netip.PrefixFrom(netip.AddrFrom4([4]byte{4, 0, 0, 0}), 6), - netip.PrefixFrom(netip.AddrFrom4([4]byte{8, 0, 0, 0}), 5), - netip.PrefixFrom(netip.AddrFrom4([4]byte{16, 0, 0, 0}), 4), - netip.PrefixFrom(netip.AddrFrom4([4]byte{32, 0, 0, 0}), 3), - netip.PrefixFrom(netip.AddrFrom4([4]byte{64, 0, 0, 0}), 2), - netip.PrefixFrom(netip.AddrFrom4([4]byte{128, 0, 0, 0}), 1), - } { + var routes []netip.Prefix + if len(options.Inet4RouteAddress) > 0 { + routes = append(options.Inet4RouteAddress, netip.PrefixFrom(options.Inet4Address[0].Addr().Next(), 32)) + } else { + routes = []netip.Prefix{ + netip.PrefixFrom(netip.AddrFrom4([4]byte{1, 0, 0, 0}), 8), + netip.PrefixFrom(netip.AddrFrom4([4]byte{2, 0, 0, 0}), 7), + netip.PrefixFrom(netip.AddrFrom4([4]byte{4, 0, 0, 0}), 6), + netip.PrefixFrom(netip.AddrFrom4([4]byte{8, 0, 0, 0}), 5), + netip.PrefixFrom(netip.AddrFrom4([4]byte{16, 0, 0, 0}), 4), + netip.PrefixFrom(netip.AddrFrom4([4]byte{32, 0, 0, 0}), 3), + netip.PrefixFrom(netip.AddrFrom4([4]byte{64, 0, 0, 0}), 2), + netip.PrefixFrom(netip.AddrFrom4([4]byte{128, 0, 0, 0}), 1), + } + } + for _, subnet := range routes { err = addRoute(subnet, options.Inet4Address[0].Addr()) if err != nil { - return E.Cause(err, "add ipv4 route "+subnet.String()) + return E.Cause(err, "add ipv4 route ", subnet) } } } if len(options.Inet6Address) > 0 { - subnet := netip.PrefixFrom(netip.AddrFrom16([16]byte{32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}), 3) - err = addRoute(subnet, options.Inet6Address[0].Addr()) - if err != nil { - return E.Cause(err, "add ipv6 route "+subnet.String()) + var routes []netip.Prefix + if len(options.Inet6RouteAddress) > 0 { + routes = append(options.Inet6RouteAddress, netip.PrefixFrom(options.Inet6Address[0].Addr().Next(), 128)) + } else { + routes = []netip.Prefix{ + netip.PrefixFrom(netip.AddrFrom16([16]byte{32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}), 3), + } + } + for _, subnet := range routes { + err = addRoute(subnet, options.Inet6Address[0].Addr()) + if err != nil { + return E.Cause(err, "add ipv6 route ", subnet) + } } } } diff --git a/tun_linux.go b/tun_linux.go index ac19064..be78840 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -171,26 +171,52 @@ func (t *NativeTun) routes(tunLink netlink.Link) []netlink.Route { var routes []netlink.Route if len(t.options.Inet4Address) > 0 { if t.options.AutoRoute { + if len(t.options.Inet4RouteAddress) > 0 { + for _, addr := range t.options.Inet4RouteAddress { + routes = append(routes, netlink.Route{ + Dst: &net.IPNet{ + IP: addr.Addr().AsSlice(), + Mask: net.CIDRMask(addr.Bits(), 32), + }, + LinkIndex: tunLink.Attrs().Index, + Table: t.options.TableIndex, + }) + } + } else { + routes = append(routes, netlink.Route{ + Dst: &net.IPNet{ + IP: net.IPv4zero, + Mask: net.CIDRMask(0, 32), + }, + LinkIndex: tunLink.Attrs().Index, + Table: t.options.TableIndex, + }) + } + } + } + if len(t.options.Inet6Address) > 0 { + if len(t.options.Inet6RouteAddress) > 0 { + for _, addr := range t.options.Inet6RouteAddress { + routes = append(routes, netlink.Route{ + Dst: &net.IPNet{ + IP: addr.Addr().AsSlice(), + Mask: net.CIDRMask(addr.Bits(), 128), + }, + LinkIndex: tunLink.Attrs().Index, + Table: t.options.TableIndex, + }) + } + } else { routes = append(routes, netlink.Route{ Dst: &net.IPNet{ - IP: net.IPv4zero, - Mask: net.CIDRMask(0, 32), + IP: net.IPv6zero, + Mask: net.CIDRMask(0, 128), }, LinkIndex: tunLink.Attrs().Index, Table: t.options.TableIndex, }) } } - if len(t.options.Inet6Address) > 0 { - routes = append(routes, netlink.Route{ - Dst: &net.IPNet{ - IP: net.IPv6zero, - Mask: net.CIDRMask(0, 128), - }, - LinkIndex: tunLink.Attrs().Index, - Table: t.options.TableIndex, - }) - } return routes } diff --git a/tun_windows.go b/tun_windows.go index 631de64..12cfb40 100644 --- a/tun_windows.go +++ b/tun_windows.go @@ -108,15 +108,33 @@ func (t *NativeTun) configure() error { } } else { if len(t.options.Inet4Address) > 0 { - err := luid.AddRoute(netip.PrefixFrom(netip.IPv4Unspecified(), 0), netip.IPv4Unspecified(), 0) - if err != nil { - return E.Cause(err, "set ipv4 route") + if len(t.options.Inet4RouteAddress) > 0 { + for _, addr := range t.options.Inet4RouteAddress { + err := luid.AddRoute(addr, netip.IPv4Unspecified(), 0) + if err != nil { + return E.Cause(err, "add ipv4 route: ", addr) + } + } + } else { + err := luid.AddRoute(netip.PrefixFrom(netip.IPv4Unspecified(), 0), netip.IPv4Unspecified(), 0) + if err != nil { + return E.Cause(err, "set ipv4 route") + } } } if len(t.options.Inet6Address) > 0 { - err := luid.AddRoute(netip.PrefixFrom(netip.IPv6Unspecified(), 0), netip.IPv6Unspecified(), 0) - if err != nil { - return E.Cause(err, "set ipv6 route") + if len(t.options.Inet6RouteAddress) > 0 { + for _, addr := range t.options.Inet6RouteAddress { + err := luid.AddRoute(addr, netip.IPv6Unspecified(), 0) + if err != nil { + return E.Cause(err, "add ipv6 route: ", addr) + } + } + } else { + err := luid.AddRoute(netip.PrefixFrom(netip.IPv6Unspecified(), 0), netip.IPv6Unspecified(), 0) + if err != nil { + return E.Cause(err, "set ipv6 route") + } } } }