version/distro,wgengine/router: raise WSL eth0 MTU when too low

WSL has started to set the eth0 default route interface default to 1280
MTU, which is too low to carry 1280 byte packets from tailscale0 once
wrapped in WireGuard. The change down to 1280 is very likely smaller
than necessary for almost all users. We can not easily determine the
ideal MTU, but if all the preconditions match, we raise the MTU to 1360,
which is just enough for Tailscale traffic to work.

Updates #4833
Updates #7346

Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
James Tucker 2023-03-02 21:04:01 -08:00 committed by James Tucker
parent d92ef4c215
commit 7b73c9628d
2 changed files with 52 additions and 0 deletions

View File

@ -32,6 +32,7 @@ const (
)
var distro lazy.SyncValue[Distro]
var isWSL lazy.SyncValue[bool]
// Get returns the current distro, or the empty string if unknown.
func Get() Distro {
@ -47,6 +48,15 @@ func Get() Distro {
})
}
// IsWSL reports whether we're running in the Windows Subsystem for Linux.
func IsWSL() bool {
return runtime.GOOS == "linux" && isWSL.Get(func() bool {
// We could look for $WSL_INTEROP instead, however that may be missing if
// the user has started to use systemd in WSL2.
return have("/proc/sys/fs/binfmt_misc/WSLInterop") || have("/mnt/wsl")
})
}
func have(file string) bool {
_, err := os.Stat(file)
return err == nil

View File

@ -7,6 +7,7 @@ import (
"bytes"
"errors"
"fmt"
"net"
"net/netip"
"os"
"os/exec"
@ -224,6 +225,8 @@ func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, linkMon *monit
r.logf("mwan3 on openWRT detected, switching policy base priority to 1300")
}
r.fixupWSLMTU()
return r, nil
}
@ -891,6 +894,45 @@ func (r *linuxRouter) downInterface() error {
return netlink.LinkSetDown(link)
}
// fixupWSLMTU sets the MTU on the eth0 interface to 1360 bytes if running under
// WSL, eth0 is the default route, and has the MTU 1280 bytes.
func (r *linuxRouter) fixupWSLMTU() {
if !distro.IsWSL() {
return
}
if r.useIPCommand() {
r.logf("fixupWSLMTU: not implemented by ip command")
return
}
link, err := netlink.LinkByName("eth0")
if err != nil {
r.logf("warning: fixupWSLMTU: could not open eth0: %v", err)
return
}
routes, err := netlink.RouteGet(net.IPv4(8, 8, 8, 8))
if err != nil || len(routes) == 0 {
if err == nil {
err = fmt.Errorf("none found")
}
r.logf("fixupWSLMTU: could not get default route: %v", err)
return
}
if routes[0].LinkIndex != link.Attrs().Index {
r.logf("fixupWSLMTU: default route is not via eth0")
return
}
if link.Attrs().MTU == 1280 {
if err := netlink.LinkSetMTU(link, 1360); err != nil {
r.logf("warning: fixupWSLMTU: could not raise eth0 MTU: %v", err)
}
}
}
// addrFamily is an address family: IPv4 or IPv6.
type addrFamily byte