From 1138f4eb5f326d913b127c34cddf636b8e4047c8 Mon Sep 17 00:00:00 2001 From: Val Date: Tue, 18 Jul 2023 23:51:32 +0200 Subject: [PATCH] wgengine/router,ipn/ipnlocal: add MTU field to router config The MacOS client can't set the MTU when creating the tun due to lack of permissions, so add it to the router config and have MacOS set it in the callback using a method that it does have permissions for. Updates #8219 Signed-off-by: Val --- wgengine/router/callback.go | 17 ++++++++++++++--- wgengine/router/router.go | 5 +++++ wgengine/router/router_test.go | 14 ++++++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/wgengine/router/callback.go b/wgengine/router/callback.go index 1d7f32846..c1838539b 100644 --- a/wgengine/router/callback.go +++ b/wgengine/router/callback.go @@ -24,9 +24,16 @@ type CallbackRouter struct { // will return ErrGetBaseConfigNotSupported. GetBaseConfigFunc func() (dns.OSConfig, error) - mu sync.Mutex // protects all the following - rcfg *Config // last applied router config - dcfg *dns.OSConfig // last applied DNS config + // InitialMTU is the MTU the tun should be initialized with. + // Zero means don't change the MTU from the default. This MTU + // is applied only once, shortly after the TUN is created, and + // ignored thereafter. + InitialMTU uint32 + + mu sync.Mutex // protects all the following + didSetMTU bool // if we set the MTU already + rcfg *Config // last applied router config + dcfg *dns.OSConfig // last applied DNS config } // Up implements Router. @@ -41,6 +48,10 @@ func (r *CallbackRouter) Set(rcfg *Config) error { if r.rcfg.Equal(rcfg) { return nil } + if r.didSetMTU == false { + r.didSetMTU = true + rcfg.NewMTU = int(r.InitialMTU) + } r.rcfg = rcfg return r.SetBoth(r.rcfg, r.dcfg) } diff --git a/wgengine/router/router.go b/wgengine/router/router.go index 11668a70e..ecea521ad 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -67,6 +67,11 @@ type Config struct { // routing rules apply. LocalRoutes []netip.Prefix + // NewMTU is currently only used by the MacOS network extension + // app to set the MTU of the tun in the router configuration + // callback. If zero, the MTU is unchanged. + NewMTU int + // Linux-only things below, ignored on other platforms. SubnetRoutes []netip.Prefix // subnets being advertised to other Tailscale nodes SNATSubnetRoutes bool // SNAT traffic to local subnets diff --git a/wgengine/router/router_test.go b/wgengine/router/router_test.go index 413de5742..d06033ba8 100644 --- a/wgengine/router/router_test.go +++ b/wgengine/router/router_test.go @@ -21,8 +21,8 @@ func mustCIDRs(ss ...string) []netip.Prefix { func TestConfigEqual(t *testing.T) { testedFields := []string{ - "LocalAddrs", "Routes", "LocalRoutes", "SubnetRoutes", - "SNATSubnetRoutes", "NetfilterMode", + "LocalAddrs", "Routes", "LocalRoutes", "NewMTU", + "SubnetRoutes", "SNATSubnetRoutes", "NetfilterMode", } configType := reflect.TypeOf(Config{}) configFields := []string{} @@ -134,6 +134,16 @@ func TestConfigEqual(t *testing.T) { &Config{NetfilterMode: preftype.NetfilterNoDivert}, true, }, + { + &Config{NewMTU: 0}, + &Config{NewMTU: 0}, + true, + }, + { + &Config{NewMTU: 1280}, + &Config{NewMTU: 0}, + false, + }, } for i, tt := range tests { got := tt.a.Equal(tt.b)