From 2e93c12cdc384d9195a1dd5050e676f912b40555 Mon Sep 17 00:00:00 2001 From: Haruue Date: Wed, 20 Mar 2024 13:45:12 +0800 Subject: [PATCH] feat(tun): export sing-tun auto route config --- app/cmd/client.go | 63 ++++++++++++++++++++++++++++++++------ app/go.mod | 2 +- app/go.sum | 2 ++ app/internal/tun/server.go | 24 ++++++++++++--- 4 files changed, 75 insertions(+), 16 deletions(-) diff --git a/app/cmd/client.go b/app/cmd/client.go index 755032e..42c5a3a 100644 --- a/app/cmd/client.go +++ b/app/cmd/client.go @@ -5,6 +5,7 @@ import ( "crypto/x509" "encoding/hex" "errors" + "fmt" "net" "net/netip" "os" @@ -153,8 +154,17 @@ type tunConfig struct { Name string `mapstructure:"name"` MTU uint32 `mapstructure:"mtu"` Timeout time.Duration `mapstructure:"timeout"` - Prefix4 string `mapstructure:"prefix4"` - Prefix6 string `mapstructure:"prefix6"` + Address struct { + IPv4 string `mapstructure:"ipv4"` + IPv6 string `mapstructure:"ipv6"` + } `mapstructure:"address"` + Route *struct { + Strict bool `mapstructure:"strict"` + IPv4 []string `mapstructure:"ipv4"` + IPv6 []string `mapstructure:"ipv6"` + IPv4Exclude []string `mapstructure:"ipv4Exclude"` + IPv6Exclude []string `mapstructure:"ipv6Exclude"` + } `mapstructure:"route"` } func (c *clientConfig) fillServerAddr(hyConfig *client.Config) error { @@ -684,19 +694,19 @@ func clientTUN(config tunConfig, c client.Client) error { if timeout == 0 { timeout = 300 } - if config.Prefix4 == "" { - config.Prefix4 = "100.100.100.101/30" + if config.Address.IPv4 == "" { + config.Address.IPv4 = "100.100.100.101/30" } - prefix4, err := netip.ParsePrefix(config.Prefix4) + prefix4, err := netip.ParsePrefix(config.Address.IPv4) if err != nil { - return configError{Field: "prefix4", Err: err} + return configError{Field: "address.ipv4", Err: err} } - if config.Prefix6 == "" { - config.Prefix6 = "2001::ffff:ffff:ffff:fff1/126" + if config.Address.IPv6 == "" { + config.Address.IPv6 = "2001::ffff:ffff:ffff:fff1/126" } - prefix6, err := netip.ParsePrefix(config.Prefix6) + prefix6, err := netip.ParsePrefix(config.Address.IPv6) if err != nil { - return configError{Field: "prefix6", Err: err} + return configError{Field: "address.ipv6", Err: err} } server := &tun.Server{ HyClient: c, @@ -708,6 +718,39 @@ func clientTUN(config tunConfig, c client.Client) error { Inet4Address: []netip.Prefix{prefix4}, Inet6Address: []netip.Prefix{prefix6}, } + if config.Route != nil { + server.AutoRoute = true + server.StructRoute = config.Route.Strict + + parsePrefixes := func(field string, s []string) ([]netip.Prefix, error) { + var prefixes []netip.Prefix + for i, s := range s { + p, err := netip.ParsePrefix(s) + if err != nil { + return nil, configError{Field: fmt.Sprintf("%s[%d]", field, i), Err: err} + } + prefixes = append(prefixes, p) + } + return prefixes, nil + } + + server.Inet4RouteAddress, err = parsePrefixes("route.ipv4", config.Route.IPv4) + if err != nil { + return err + } + server.Inet6RouteAddress, err = parsePrefixes("route.ipv6", config.Route.IPv6) + if err != nil { + return err + } + server.Inet4RouteExcludeAddress, err = parsePrefixes("route.ipv4Exclude", config.Route.IPv4Exclude) + if err != nil { + return err + } + server.Inet6RouteExcludeAddress, err = parsePrefixes("route.ipv6Exclude", config.Route.IPv6Exclude) + if err != nil { + return err + } + } logger.Info("TUN listening", zap.String("interface", config.Name)) return server.Serve() } diff --git a/app/go.mod b/app/go.mod index d9f598e..8beb77b 100644 --- a/app/go.mod +++ b/app/go.mod @@ -6,7 +6,7 @@ require ( github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f github.com/apernet/hysteria/core v0.0.0-00010101000000-000000000000 github.com/apernet/hysteria/extras v0.0.0-00010101000000-000000000000 - github.com/apernet/sing-tun v0.2.5-0.20240319071017-94362fc6c4cd + github.com/apernet/sing-tun v0.2.5-0.20240320024814-b1e6f9d4930f github.com/caddyserver/certmagic v0.17.2 github.com/mdp/qrterminal/v3 v3.1.1 github.com/mholt/acmez v1.0.4 diff --git a/app/go.sum b/app/go.sum index fe0b734..9f92233 100644 --- a/app/go.sum +++ b/app/go.sum @@ -46,6 +46,8 @@ github.com/apernet/sing-tun v0.2.5-0.20240319051541-59e6f4bd5d1e h1:yFDb2wKpWQmz github.com/apernet/sing-tun v0.2.5-0.20240319051541-59e6f4bd5d1e/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk= github.com/apernet/sing-tun v0.2.5-0.20240319071017-94362fc6c4cd h1:2EOhAnrNARO2xt7doxlV8+6c6W0hi48hFHiqhlYqtDM= github.com/apernet/sing-tun v0.2.5-0.20240319071017-94362fc6c4cd/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk= +github.com/apernet/sing-tun v0.2.5-0.20240320024814-b1e6f9d4930f h1:IK/7rFSnRRLXCjcuWreyPzfPEfZd2Xz9v2+RsFoodbs= +github.com/apernet/sing-tun v0.2.5-0.20240320024814-b1e6f9d4930f/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= diff --git a/app/internal/tun/server.go b/app/internal/tun/server.go index 5953647..03ddc56 100644 --- a/app/internal/tun/server.go +++ b/app/internal/tun/server.go @@ -31,6 +31,14 @@ type Server struct { // required by system stack Inet4Address []netip.Prefix Inet6Address []netip.Prefix + + // auto route + AutoRoute bool + StructRoute bool + Inet4RouteAddress []netip.Prefix + Inet6RouteAddress []netip.Prefix + Inet4RouteExcludeAddress []netip.Prefix + Inet6RouteExcludeAddress []netip.Prefix } type EventLogger interface { @@ -42,11 +50,17 @@ type EventLogger interface { func (s *Server) Serve() error { tunOpts := tun.Options{ - Name: s.IfName, - Inet4Address: s.Inet4Address, - Inet6Address: s.Inet6Address, - MTU: s.MTU, - GSO: true, + Name: s.IfName, + Inet4Address: s.Inet4Address, + Inet6Address: s.Inet6Address, + MTU: s.MTU, + GSO: true, + AutoRoute: s.AutoRoute, + StrictRoute: s.StructRoute, + Inet4RouteAddress: s.Inet4RouteAddress, + Inet6RouteAddress: s.Inet6RouteAddress, + Inet4RouteExcludeAddress: s.Inet4RouteExcludeAddress, + Inet6RouteExcludeAddress: s.Inet6RouteExcludeAddress, Logger: &singLogger{ tag: "tun", zapLogger: s.Logger,