diff --git a/cmd/tailscaled/tailscaled.go b/cmd/tailscaled/tailscaled.go index ddae1a411..4d3651a22 100644 --- a/cmd/tailscaled/tailscaled.go +++ b/cmd/tailscaled/tailscaled.go @@ -349,7 +349,7 @@ func tryEngine(logf logger.Logf, linkMon *monitor.Mon, name string) (e wgengine. return nil, false, err } conf.Tun = dev - r, err := router.New(logf, dev) + r, err := router.New(logf, dev, linkMon) if err != nil { dev.Close() return nil, false, err diff --git a/cmd/tailscaled/tailscaled_windows.go b/cmd/tailscaled/tailscaled_windows.go index 9d5937cdb..447ee67f3 100644 --- a/cmd/tailscaled/tailscaled_windows.go +++ b/cmd/tailscaled/tailscaled_windows.go @@ -168,7 +168,7 @@ func startIPNServer(ctx context.Context, logid string) error { if err != nil { return nil, fmt.Errorf("TUN: %w", err) } - r, err := router.New(logf, dev) + r, err := router.New(logf, dev, nil) if err != nil { dev.Close() return nil, fmt.Errorf("router: %w", err) diff --git a/wgengine/router/router.go b/wgengine/router/router.go index 67bb312b5..0a162dc28 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -11,6 +11,7 @@ import ( "inet.af/netaddr" "tailscale.com/types/logger" "tailscale.com/types/preftype" + "tailscale.com/wgengine/monitor" ) // Router is responsible for managing the system network stack. @@ -31,9 +32,12 @@ type Router interface { // New returns a new Router for the current platform, using the // provided tun device. -func New(logf logger.Logf, tundev tun.Device) (Router, error) { +// +// If linkMon is nil, it's not used. It's currently (2021-07-20) only +// used on Linux in some situations. +func New(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { logf = logger.WithPrefix(logf, "router: ") - return newUserspaceRouter(logf, tundev) + return newUserspaceRouter(logf, tundev, linkMon) } // Cleanup restores the system network configuration to its original state diff --git a/wgengine/router/router_darwin.go b/wgengine/router/router_darwin.go index f5408e387..931c4d7bd 100644 --- a/wgengine/router/router_darwin.go +++ b/wgengine/router/router_darwin.go @@ -7,10 +7,11 @@ package router import ( "golang.zx2c4.com/wireguard/tun" "tailscale.com/types/logger" + "tailscale.com/wgengine/monitor" ) -func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { - return newUserspaceBSDRouter(logf, tundev) +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { + return newUserspaceBSDRouter(logf, tundev, linkMon) } func cleanup(logger.Logf, string) { diff --git a/wgengine/router/router_default.go b/wgengine/router/router_default.go index 756e88d07..99899c6e3 100644 --- a/wgengine/router/router_default.go +++ b/wgengine/router/router_default.go @@ -7,12 +7,16 @@ package router import ( + "fmt" + "runtime" + "golang.zx2c4.com/wireguard/tun" "tailscale.com/types/logger" + "tailscale.com/wgengine/monitor" ) -func newUserspaceRouter(logf logger.Logf, tunname string, tunDev tun.Device, netChanged func()) Router { - return NewFakeRouter(logf, tunname, tunDev, netChanged) +func newUserspaceRouter(logf logger.Logf, tunname string, tunDev tun.Device, linkMon *monitor.Mon) Router { + panic(fmt.Sprintf("unsupported OS %q", runtime.GOOS)) } func cleanup(logf logger.Logf, interfaceName string) { diff --git a/wgengine/router/router_freebsd.go b/wgengine/router/router_freebsd.go index 0e88b709c..70174c94d 100644 --- a/wgengine/router/router_freebsd.go +++ b/wgengine/router/router_freebsd.go @@ -7,6 +7,7 @@ package router import ( "golang.zx2c4.com/wireguard/tun" "tailscale.com/types/logger" + "tailscale.com/wgengine/monitor" ) // For now this router only supports the userspace WireGuard implementations. @@ -14,8 +15,8 @@ import ( // Work is currently underway for an in-kernel FreeBSD implementation of wireguard // https://svnweb.freebsd.org/base?view=revision&revision=357986 -func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { - return newUserspaceBSDRouter(logf, tundev) +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { + return newUserspaceBSDRouter(logf, tundev, linkMon) } func cleanup(logf logger.Logf, interfaceName string) { diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index 907632d5c..ee9e4a565 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -22,6 +22,7 @@ import ( "tailscale.com/types/logger" "tailscale.com/types/preftype" "tailscale.com/version/distro" + "tailscale.com/wgengine/monitor" ) const ( @@ -96,6 +97,7 @@ type netfilterRunner interface { type linuxRouter struct { logf func(fmt string, args ...interface{}) tunname string + linkMon *monitor.Mon addrs map[netaddr.IPPrefix]bool routes map[netaddr.IPPrefix]bool localRoutes map[netaddr.IPPrefix]bool @@ -112,7 +114,7 @@ type linuxRouter struct { cmd commandRunner } -func newUserspaceRouter(logf logger.Logf, tunDev tun.Device) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tunDev tun.Device, linkMon *monitor.Mon) (Router, error) { tunname, err := tunDev.Name() if err != nil { return nil, err @@ -143,16 +145,17 @@ func newUserspaceRouter(logf logger.Logf, tunDev tun.Device) (Router, error) { } } - return newUserspaceRouterAdvanced(logf, tunname, ipt4, ipt6, osCommandRunner{}, supportsV6, supportsV6NAT) + return newUserspaceRouterAdvanced(logf, tunname, linkMon, ipt4, ipt6, osCommandRunner{}, supportsV6, supportsV6NAT) } -func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, netfilter4, netfilter6 netfilterRunner, cmd commandRunner, supportsV6, supportsV6NAT bool) (Router, error) { +func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, linkMon *monitor.Mon, netfilter4, netfilter6 netfilterRunner, cmd commandRunner, supportsV6, supportsV6NAT bool) (Router, error) { ipRuleAvailable := (cmd.run("ip", "rule") == nil) return &linuxRouter{ logf: logf, tunname: tunname, netfilterMode: netfilterOff, + linkMon: linkMon, ipRuleAvailable: ipRuleAvailable, v6Available: supportsV6, diff --git a/wgengine/router/router_linux_test.go b/wgengine/router/router_linux_test.go index 6887dd1e1..8b9b228bb 100644 --- a/wgengine/router/router_linux_test.go +++ b/wgengine/router/router_linux_test.go @@ -18,6 +18,8 @@ import ( "github.com/google/go-cmp/cmp" "golang.zx2c4.com/wireguard/tun" "inet.af/netaddr" + "tailscale.com/types/logger" + "tailscale.com/wgengine/monitor" ) func TestRouterStates(t *testing.T) { @@ -314,8 +316,15 @@ ip route add throw 192.168.0.0/24 table 52` + basic, }, } + mon, err := monitor.New(logger.Discard) + if err != nil { + t.Fatal(err) + } + mon.Start() + defer mon.Close() + fake := NewFakeOS(t) - router, err := newUserspaceRouterAdvanced(t.Logf, "tailscale0", fake.netfilter4, fake.netfilter6, fake, true, true) + router, err := newUserspaceRouterAdvanced(t.Logf, "tailscale0", mon, fake.netfilter4, fake.netfilter6, fake, true, true) if err != nil { t.Fatalf("failed to create router: %v", err) } @@ -659,7 +668,14 @@ func TestDelRouteIdempotent(t *testing.T) { } } - r, err := newUserspaceRouter(logf, tun) + mon, err := monitor.New(logger.Discard) + if err != nil { + t.Fatal(err) + } + mon.Start() + defer mon.Close() + + r, err := newUserspaceRouter(logf, tun, mon) if err != nil { t.Fatal(err) } diff --git a/wgengine/router/router_openbsd.go b/wgengine/router/router_openbsd.go index 5f8c26a03..995125564 100644 --- a/wgengine/router/router_openbsd.go +++ b/wgengine/router/router_openbsd.go @@ -13,6 +13,7 @@ import ( "golang.zx2c4.com/wireguard/tun" "inet.af/netaddr" "tailscale.com/types/logger" + "tailscale.com/wgengine/monitor" ) // For now this router only supports the WireGuard userspace implementation. @@ -21,13 +22,14 @@ import ( type openbsdRouter struct { logf logger.Logf + linkMon *monitor.Mon tunname string local4 netaddr.IPPrefix local6 netaddr.IPPrefix routes map[netaddr.IPPrefix]struct{} } -func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { tunname, err := tundev.Name() if err != nil { return nil, err @@ -35,6 +37,7 @@ func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { return &openbsdRouter{ logf: logf, + linkMon: linkMon, tunname: tunname, }, nil } diff --git a/wgengine/router/router_userspace_bsd.go b/wgengine/router/router_userspace_bsd.go index 7a9482324..faca19a81 100644 --- a/wgengine/router/router_userspace_bsd.go +++ b/wgengine/router/router_userspace_bsd.go @@ -17,16 +17,18 @@ import ( "tailscale.com/net/tsaddr" "tailscale.com/types/logger" "tailscale.com/version" + "tailscale.com/wgengine/monitor" ) type userspaceBSDRouter struct { logf logger.Logf + linkMon *monitor.Mon tunname string local []netaddr.IPPrefix routes map[netaddr.IPPrefix]struct{} } -func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device) (Router, error) { +func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { tunname, err := tundev.Name() if err != nil { return nil, err @@ -34,6 +36,7 @@ func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device) (Router, error) return &userspaceBSDRouter{ logf: logf, + linkMon: linkMon, tunname: tunname, }, nil } diff --git a/wgengine/router/router_windows.go b/wgengine/router/router_windows.go index b107c6a3a..6dcb6a7ff 100644 --- a/wgengine/router/router_windows.go +++ b/wgengine/router/router_windows.go @@ -24,16 +24,18 @@ import ( "tailscale.com/logtail/backoff" "tailscale.com/net/dns" "tailscale.com/types/logger" + "tailscale.com/wgengine/monitor" ) type winRouter struct { logf func(fmt string, args ...interface{}) + linkMon *monitor.Mon // may be nil nativeTun *tun.NativeTun routeChangeCallback *winipcfg.RouteChangeCallback firewall *firewallTweaker } -func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { +func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) { nativeTun := tundev.(*tun.NativeTun) luid := winipcfg.LUID(nativeTun.LUID()) guid, err := luid.GUID() @@ -43,6 +45,7 @@ func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { return &winRouter{ logf: logf, + linkMon: linkMon, nativeTun: nativeTun, firewall: &firewallTweaker{ logf: logger.WithPrefix(logf, "firewall: "),