wgengine/router: take a link monitor

Prep for #1591 which will need to make Linux's router react to changes
that the link monitor observes.

The router package already depended on the monitor package
transitively. Now it's explicit.

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
pull/2467/head
Brad Fitzpatrick 3 years ago committed by Brad Fitzpatrick
parent 24db1a3c9b
commit ed8587f90d

@ -349,7 +349,7 @@ func tryEngine(logf logger.Logf, linkMon *monitor.Mon, name string) (e wgengine.
return nil, false, err return nil, false, err
} }
conf.Tun = dev conf.Tun = dev
r, err := router.New(logf, dev) r, err := router.New(logf, dev, linkMon)
if err != nil { if err != nil {
dev.Close() dev.Close()
return nil, false, err return nil, false, err

@ -168,7 +168,7 @@ func startIPNServer(ctx context.Context, logid string) error {
if err != nil { if err != nil {
return nil, fmt.Errorf("TUN: %w", err) return nil, fmt.Errorf("TUN: %w", err)
} }
r, err := router.New(logf, dev) r, err := router.New(logf, dev, nil)
if err != nil { if err != nil {
dev.Close() dev.Close()
return nil, fmt.Errorf("router: %w", err) return nil, fmt.Errorf("router: %w", err)

@ -11,6 +11,7 @@ import (
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
"tailscale.com/wgengine/monitor"
) )
// Router is responsible for managing the system network stack. // 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 // New returns a new Router for the current platform, using the
// provided tun device. // 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: ") logf = logger.WithPrefix(logf, "router: ")
return newUserspaceRouter(logf, tundev) return newUserspaceRouter(logf, tundev, linkMon)
} }
// Cleanup restores the system network configuration to its original state // Cleanup restores the system network configuration to its original state

@ -7,10 +7,11 @@ package router
import ( import (
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/wgengine/monitor"
) )
func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) {
return newUserspaceBSDRouter(logf, tundev) return newUserspaceBSDRouter(logf, tundev, linkMon)
} }
func cleanup(logger.Logf, string) { func cleanup(logger.Logf, string) {

@ -7,12 +7,16 @@
package router package router
import ( import (
"fmt"
"runtime"
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/wgengine/monitor"
) )
func newUserspaceRouter(logf logger.Logf, tunname string, tunDev tun.Device, netChanged func()) Router { func newUserspaceRouter(logf logger.Logf, tunname string, tunDev tun.Device, linkMon *monitor.Mon) Router {
return NewFakeRouter(logf, tunname, tunDev, netChanged) panic(fmt.Sprintf("unsupported OS %q", runtime.GOOS))
} }
func cleanup(logf logger.Logf, interfaceName string) { func cleanup(logf logger.Logf, interfaceName string) {

@ -7,6 +7,7 @@ package router
import ( import (
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/wgengine/monitor"
) )
// For now this router only supports the userspace WireGuard implementations. // 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 // Work is currently underway for an in-kernel FreeBSD implementation of wireguard
// https://svnweb.freebsd.org/base?view=revision&revision=357986 // https://svnweb.freebsd.org/base?view=revision&revision=357986
func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) { func newUserspaceRouter(logf logger.Logf, tundev tun.Device, linkMon *monitor.Mon) (Router, error) {
return newUserspaceBSDRouter(logf, tundev) return newUserspaceBSDRouter(logf, tundev, linkMon)
} }
func cleanup(logf logger.Logf, interfaceName string) { func cleanup(logf logger.Logf, interfaceName string) {

@ -22,6 +22,7 @@ import (
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/types/preftype" "tailscale.com/types/preftype"
"tailscale.com/version/distro" "tailscale.com/version/distro"
"tailscale.com/wgengine/monitor"
) )
const ( const (
@ -96,6 +97,7 @@ type netfilterRunner interface {
type linuxRouter struct { type linuxRouter struct {
logf func(fmt string, args ...interface{}) logf func(fmt string, args ...interface{})
tunname string tunname string
linkMon *monitor.Mon
addrs map[netaddr.IPPrefix]bool addrs map[netaddr.IPPrefix]bool
routes map[netaddr.IPPrefix]bool routes map[netaddr.IPPrefix]bool
localRoutes map[netaddr.IPPrefix]bool localRoutes map[netaddr.IPPrefix]bool
@ -112,7 +114,7 @@ type linuxRouter struct {
cmd commandRunner 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() tunname, err := tunDev.Name()
if err != nil { if err != nil {
return nil, err 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) ipRuleAvailable := (cmd.run("ip", "rule") == nil)
return &linuxRouter{ return &linuxRouter{
logf: logf, logf: logf,
tunname: tunname, tunname: tunname,
netfilterMode: netfilterOff, netfilterMode: netfilterOff,
linkMon: linkMon,
ipRuleAvailable: ipRuleAvailable, ipRuleAvailable: ipRuleAvailable,
v6Available: supportsV6, v6Available: supportsV6,

@ -18,6 +18,8 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/types/logger"
"tailscale.com/wgengine/monitor"
) )
func TestRouterStates(t *testing.T) { 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) 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 { if err != nil {
t.Fatalf("failed to create router: %v", err) 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 { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

@ -13,6 +13,7 @@ import (
"golang.zx2c4.com/wireguard/tun" "golang.zx2c4.com/wireguard/tun"
"inet.af/netaddr" "inet.af/netaddr"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/wgengine/monitor"
) )
// For now this router only supports the WireGuard userspace implementation. // For now this router only supports the WireGuard userspace implementation.
@ -21,13 +22,14 @@ import (
type openbsdRouter struct { type openbsdRouter struct {
logf logger.Logf logf logger.Logf
linkMon *monitor.Mon
tunname string tunname string
local4 netaddr.IPPrefix local4 netaddr.IPPrefix
local6 netaddr.IPPrefix local6 netaddr.IPPrefix
routes map[netaddr.IPPrefix]struct{} 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() tunname, err := tundev.Name()
if err != nil { if err != nil {
return nil, err return nil, err
@ -35,6 +37,7 @@ func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) {
return &openbsdRouter{ return &openbsdRouter{
logf: logf, logf: logf,
linkMon: linkMon,
tunname: tunname, tunname: tunname,
}, nil }, nil
} }

@ -17,16 +17,18 @@ import (
"tailscale.com/net/tsaddr" "tailscale.com/net/tsaddr"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/version" "tailscale.com/version"
"tailscale.com/wgengine/monitor"
) )
type userspaceBSDRouter struct { type userspaceBSDRouter struct {
logf logger.Logf logf logger.Logf
linkMon *monitor.Mon
tunname string tunname string
local []netaddr.IPPrefix local []netaddr.IPPrefix
routes map[netaddr.IPPrefix]struct{} 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() tunname, err := tundev.Name()
if err != nil { if err != nil {
return nil, err return nil, err
@ -34,6 +36,7 @@ func newUserspaceBSDRouter(logf logger.Logf, tundev tun.Device) (Router, error)
return &userspaceBSDRouter{ return &userspaceBSDRouter{
logf: logf, logf: logf,
linkMon: linkMon,
tunname: tunname, tunname: tunname,
}, nil }, nil
} }

@ -24,16 +24,18 @@ import (
"tailscale.com/logtail/backoff" "tailscale.com/logtail/backoff"
"tailscale.com/net/dns" "tailscale.com/net/dns"
"tailscale.com/types/logger" "tailscale.com/types/logger"
"tailscale.com/wgengine/monitor"
) )
type winRouter struct { type winRouter struct {
logf func(fmt string, args ...interface{}) logf func(fmt string, args ...interface{})
linkMon *monitor.Mon // may be nil
nativeTun *tun.NativeTun nativeTun *tun.NativeTun
routeChangeCallback *winipcfg.RouteChangeCallback routeChangeCallback *winipcfg.RouteChangeCallback
firewall *firewallTweaker 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) nativeTun := tundev.(*tun.NativeTun)
luid := winipcfg.LUID(nativeTun.LUID()) luid := winipcfg.LUID(nativeTun.LUID())
guid, err := luid.GUID() guid, err := luid.GUID()
@ -43,6 +45,7 @@ func newUserspaceRouter(logf logger.Logf, tundev tun.Device) (Router, error) {
return &winRouter{ return &winRouter{
logf: logf, logf: logf,
linkMon: linkMon,
nativeTun: nativeTun, nativeTun: nativeTun,
firewall: &firewallTweaker{ firewall: &firewallTweaker{
logf: logger.WithPrefix(logf, "firewall: "), logf: logger.WithPrefix(logf, "firewall: "),

Loading…
Cancel
Save