mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
wgengine/router: split out from wgengine.
The router implementations are logically separate, with their own API. Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
ee3395e63a
commit
1ac570def7
@ -14,6 +14,7 @@
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"runtime"
|
||||
|
||||
"github.com/apenwarr/fixconsole"
|
||||
"github.com/pborman/getopt/v2"
|
||||
@ -33,10 +34,18 @@
|
||||
// later, the global state key doesn't look like a username.
|
||||
const globalStateKey = "_daemon"
|
||||
|
||||
var defaultTunName = "tailscale0"
|
||||
|
||||
func init() {
|
||||
if runtime.GOOS == "openbsd" {
|
||||
defaultTunName = "tun"
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
fake := getopt.BoolLong("fake", 0, "fake tunnel+routing instead of tuntap")
|
||||
debug := getopt.StringLong("debug", 0, "", "Address of debug server")
|
||||
tunname := getopt.StringLong("tun", 0, wgengine.DefaultTunName, "tunnel interface name")
|
||||
tunname := getopt.StringLong("tun", 0, defaultTunName, "tunnel interface name")
|
||||
listenport := getopt.Uint16Long("port", 'p', magicsock.DefaultPort, "WireGuard port (0=autoselect)")
|
||||
statepath := getopt.StringLong("state", 0, paths.DefaultTailscaledStateFile(), "Path of state file")
|
||||
socketpath := getopt.StringLong("socket", 's', paths.DefaultTailscaledSocket(), "Path of the service unix socket")
|
||||
|
@ -24,6 +24,7 @@
|
||||
"tailscale.com/tstest"
|
||||
"tailscale.com/wgengine"
|
||||
"tailscale.com/wgengine/magicsock"
|
||||
"tailscale.com/wgengine/router"
|
||||
"tailscale.io/control" // not yet released
|
||||
)
|
||||
|
||||
@ -196,7 +197,7 @@ func newNode(t *testing.T, prefix string, https *httptest.Server) testNode {
|
||||
}
|
||||
|
||||
tun := tuntest.NewChannelTUN()
|
||||
e1, err := wgengine.NewUserspaceEngineAdvanced(logfe, tun.TUN(), wgengine.NewFakeRouter, 0)
|
||||
e1, err := wgengine.NewUserspaceEngineAdvanced(logfe, tun.TUN(), router.NewFake, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("NewFakeEngine: %v\n", err)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ for file in $(find $1 -name '*.go'); do
|
||||
$1/tempfork/*)
|
||||
# Skip, tempfork of third-party code
|
||||
;;
|
||||
$1/wgengine/ifconfig_windows.go)
|
||||
$1/wgengine/router/ifconfig_windows.go)
|
||||
# WireGuard copyright.
|
||||
;;
|
||||
*)
|
||||
|
@ -3,7 +3,7 @@
|
||||
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
57
wgengine/router/router.go
Normal file
57
wgengine/router/router.go
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package router presents an interface to manipulate the host network
|
||||
// stack's state.
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/tailscale/wireguard-go/device"
|
||||
"github.com/tailscale/wireguard-go/tun"
|
||||
"github.com/tailscale/wireguard-go/wgcfg"
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
// Router is responsible for managing the system network stack.
|
||||
//
|
||||
// There is typically only one instance of this interface per process.
|
||||
type Router interface {
|
||||
// Up brings the router up.
|
||||
Up() error
|
||||
|
||||
// SetRoutes is called regularly on network map updates.
|
||||
// It's how you kernel route table entries are populated for
|
||||
// each peer.
|
||||
SetRoutes(RouteSettings) error
|
||||
|
||||
// Close closes the router.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// NewUserspaceRouter returns a new Router for the current platform, using the provided tun device.
|
||||
func New(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (Router, error) {
|
||||
return newUserspaceRouter(logf, wgdev, tundev)
|
||||
}
|
||||
|
||||
// RouteSettings is the full WireGuard config data (set of peers keys,
|
||||
// IP, etc in wgcfg.Config) plus the things that WireGuard doesn't do
|
||||
// itself, like DNS stuff.
|
||||
type RouteSettings struct {
|
||||
LocalAddr wgcfg.CIDR // TODO: why is this here? how does it differ from wgcfg.Config's info?
|
||||
DNS []wgcfg.IP
|
||||
DNSDomains []string
|
||||
Cfg *wgcfg.Config
|
||||
}
|
||||
|
||||
// OnlyRelevantParts returns a string minimally describing the route settings.
|
||||
func (rs *RouteSettings) OnlyRelevantParts() string {
|
||||
var peers [][]wgcfg.CIDR
|
||||
for _, p := range rs.Cfg.Peers {
|
||||
peers = append(peers, p.AllowedIPs)
|
||||
}
|
||||
return fmt.Sprintf("%v %v %v %v",
|
||||
rs.LocalAddr, rs.DNS, rs.DNSDomains, peers)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/tailscale/wireguard-go/device"
|
||||
@ -10,8 +10,6 @@
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
const DefaultTunName = "tailscale0"
|
||||
|
||||
type darwinRouter struct {
|
||||
tunname string
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
|
||||
// +build linux darwin
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
// SetRoutesFunc applies the given route settings to the OS network
|
||||
// stack.
|
@ -4,7 +4,7 @@
|
||||
|
||||
// +build !windows,!linux,!darwin,!openbsd,!freebsd
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/tailscale/wireguard-go/device"
|
||||
@ -12,8 +12,6 @@
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
const DefaultTunName = "tailscale0"
|
||||
|
||||
func newUserspaceRouter(logf logger.Logf, tunname string, dev *device.Device, tuntap tun.Device, netChanged func()) Router {
|
||||
return NewFakeRouter(logf, tunname, dev, tuntap, netChanged)
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/tailscale/wireguard-go/device"
|
||||
@ -10,9 +10,9 @@
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
// NewFakeRouter returns a new fake Router implementation whose
|
||||
// implementation does nothing and always returns nil errors.
|
||||
func NewFakeRouter(logf logger.Logf, _ *device.Device, _ tun.Device) (Router, error) {
|
||||
// NewFakeRouter returns a Router that does nothing when called and
|
||||
// always returns nil errors.
|
||||
func NewFake(logf logger.Logf, _ *device.Device, _ tun.Device) (Router, error) {
|
||||
return fakeRouter{logf: logf}, nil
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -20,8 +20,6 @@
|
||||
// Work is currently underway for an in-kernel FreeBSD implementation of wireguard
|
||||
// https://svnweb.freebsd.org/base?view=revision&revision=357986
|
||||
|
||||
const DefaultTunName = "tailscale0"
|
||||
|
||||
type freebsdRouter struct {
|
||||
logf logger.Logf
|
||||
tunname string
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -22,8 +22,6 @@
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
const DefaultTunName = "tailscale0"
|
||||
|
||||
type linuxRouter struct {
|
||||
logf func(fmt string, args ...interface{})
|
||||
tunname string
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -25,8 +25,6 @@
|
||||
// There is an experimental kernel version in the works for OpenBSD:
|
||||
// https://git.zx2c4.com/wireguard-openbsd.
|
||||
|
||||
const DefaultTunName = "tun"
|
||||
|
||||
type openbsdRouter struct {
|
||||
logf logger.Logf
|
||||
tunname string
|
@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package wgengine
|
||||
package router
|
||||
|
||||
import (
|
||||
"log"
|
||||
@ -13,8 +13,6 @@
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
const DefaultTunName = "tailscale0"
|
||||
|
||||
type winRouter struct {
|
||||
logf func(fmt string, args ...interface{})
|
||||
tunname string
|
@ -32,6 +32,7 @@
|
||||
"tailscale.com/wgengine/magicsock"
|
||||
"tailscale.com/wgengine/monitor"
|
||||
"tailscale.com/wgengine/packet"
|
||||
"tailscale.com/wgengine/router"
|
||||
)
|
||||
|
||||
// minimalMTU is the MTU we set on tailscale's tuntap
|
||||
@ -50,7 +51,7 @@ type userspaceEngine struct {
|
||||
waitCh chan struct{}
|
||||
tundev tun.Device
|
||||
wgdev *device.Device
|
||||
router Router
|
||||
router router.Router
|
||||
magicConn *magicsock.Conn
|
||||
linkMon *monitor.Mon
|
||||
|
||||
@ -82,11 +83,11 @@ func (l *Loggify) Write(b []byte) (int, error) {
|
||||
func NewFakeUserspaceEngine(logf logger.Logf, listenPort uint16) (Engine, error) {
|
||||
logf("Starting userspace wireguard engine (FAKE tuntap device).")
|
||||
tun := NewFakeTun()
|
||||
return NewUserspaceEngineAdvanced(logf, tun, NewFakeRouter, listenPort)
|
||||
return NewUserspaceEngineAdvanced(logf, tun, router.NewFake, listenPort)
|
||||
}
|
||||
|
||||
// NewUserspaceEngine creates the named tun device and returns a Tailscale Engine
|
||||
// running on it.
|
||||
// NewUserspaceEngine creates the named tun device and returns a
|
||||
// Tailscale Engine running on it.
|
||||
func NewUserspaceEngine(logf logger.Logf, tunname string, listenPort uint16) (Engine, error) {
|
||||
if tunname == "" {
|
||||
return nil, fmt.Errorf("--tun name must not be blank")
|
||||
@ -102,7 +103,7 @@ func NewUserspaceEngine(logf logger.Logf, tunname string, listenPort uint16) (En
|
||||
}
|
||||
logf("CreateTUN ok.")
|
||||
|
||||
e, err := NewUserspaceEngineAdvanced(logf, tundev, newUserspaceRouter, listenPort)
|
||||
e, err := NewUserspaceEngineAdvanced(logf, tundev, router.New, listenPort)
|
||||
if err != nil {
|
||||
logf("NewUserspaceEngineAdv: %v", err)
|
||||
tundev.Close()
|
||||
@ -111,6 +112,10 @@ func NewUserspaceEngine(logf logger.Logf, tunname string, listenPort uint16) (En
|
||||
return e, err
|
||||
}
|
||||
|
||||
// RouterGen is the signature for a function that creates a
|
||||
// router.Router.
|
||||
type RouterGen func(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (router.Router, error)
|
||||
|
||||
// NewUserspaceEngineAdvanced is like NewUserspaceEngine but takes a pre-created TUN device and allows specifing
|
||||
// a custom router constructor and listening port.
|
||||
func NewUserspaceEngineAdvanced(logf logger.Logf, tundev tun.Device, routerGen RouterGen, listenPort uint16) (Engine, error) {
|
||||
@ -236,7 +241,7 @@ func newUserspaceEngineAdvanced(logf logger.Logf, tundev tun.Device, routerGen R
|
||||
e.wgdev.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err := e.router.SetRoutes(RouteSettings{Cfg: new(wgcfg.Config)}); err != nil {
|
||||
if err := e.router.SetRoutes(router.RouteSettings{Cfg: new(wgcfg.Config)}); err != nil {
|
||||
e.wgdev.Close()
|
||||
return nil, err
|
||||
}
|
||||
@ -375,7 +380,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, dnsDomains []string) error
|
||||
cidr.Mask = 10 // route the whole cgnat range
|
||||
}
|
||||
|
||||
rs := RouteSettings{
|
||||
rs := router.RouteSettings{
|
||||
LocalAddr: cidr,
|
||||
Cfg: cfg,
|
||||
DNS: cfg.DNS,
|
||||
|
@ -10,6 +10,8 @@
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"tailscale.com/wgengine/router"
|
||||
)
|
||||
|
||||
func TestWatchdog(t *testing.T) {
|
||||
@ -18,7 +20,7 @@ func TestWatchdog(t *testing.T) {
|
||||
t.Run("default watchdog does not fire", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tun := NewFakeTun()
|
||||
e, err := NewUserspaceEngineAdvanced(t.Logf, tun, NewFakeRouter, 0)
|
||||
e, err := NewUserspaceEngineAdvanced(t.Logf, tun, router.NewFake, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -35,7 +37,7 @@ func TestWatchdog(t *testing.T) {
|
||||
t.Run("watchdog fires on blocked getStatus", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
tun := NewFakeTun()
|
||||
e, err := NewUserspaceEngineAdvanced(t.Logf, tun, NewFakeRouter, 0)
|
||||
e, err := NewUserspaceEngineAdvanced(t.Logf, tun, router.NewFake, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -6,15 +6,11 @@
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tailscale/wireguard-go/device"
|
||||
"github.com/tailscale/wireguard-go/tun"
|
||||
"github.com/tailscale/wireguard-go/wgcfg"
|
||||
"tailscale.com/ipn/ipnstate"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/wgengine/filter"
|
||||
)
|
||||
|
||||
@ -48,51 +44,6 @@ type Status struct {
|
||||
// NetInfoCallback is the type used by Engine.SetNetInfoCallback.
|
||||
type NetInfoCallback func(*tailcfg.NetInfo)
|
||||
|
||||
// RouteSettings is the full WireGuard config data (set of peers keys,
|
||||
// IP, etc in wgcfg.Config) plus the things that WireGuard doesn't do
|
||||
// itself, like DNS stuff.
|
||||
type RouteSettings struct {
|
||||
LocalAddr wgcfg.CIDR // TODO: why is this here? how does it differ from wgcfg.Config's info?
|
||||
DNS []wgcfg.IP
|
||||
DNSDomains []string
|
||||
Cfg *wgcfg.Config
|
||||
}
|
||||
|
||||
// OnlyRelevantParts returns a string minimally describing the route settings.
|
||||
func (rs *RouteSettings) OnlyRelevantParts() string {
|
||||
var peers [][]wgcfg.CIDR
|
||||
for _, p := range rs.Cfg.Peers {
|
||||
peers = append(peers, p.AllowedIPs)
|
||||
}
|
||||
return fmt.Sprintf("%v %v %v %v",
|
||||
rs.LocalAddr, rs.DNS, rs.DNSDomains, peers)
|
||||
}
|
||||
|
||||
// NewUserspaceRouter returns a new Router for the current platform, using the provided tun device.
|
||||
func NewUserspaceRouter(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (Router, error) {
|
||||
return newUserspaceRouter(logf, wgdev, tundev)
|
||||
}
|
||||
|
||||
// RouterGen is the signature for the two funcs that create Router implementations:
|
||||
// NewUserspaceRouter (which varies by operating system) and NewFakeRouter.
|
||||
type RouterGen func(logf logger.Logf, wgdev *device.Device, tundev tun.Device) (Router, error)
|
||||
|
||||
// Router is responsible for managing the system route table.
|
||||
//
|
||||
// There's only one instance, and one per-OS implementation.
|
||||
type Router interface {
|
||||
// Up brings the router up.
|
||||
Up() error
|
||||
|
||||
// SetRoutes is called regularly on network map updates.
|
||||
// It's how you kernel route table entries are populated for
|
||||
// each peer.
|
||||
SetRoutes(RouteSettings) error
|
||||
|
||||
// Close closes the router.
|
||||
Close() error
|
||||
}
|
||||
|
||||
// ErrNoChanges is returned by Engine.Reconfig if no changes were made.
|
||||
var ErrNoChanges = errors.New("no changes made to Engine config")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user