From d76334d2f0dfbac790dc70ded1cd20a0ce8d2739 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 4 Feb 2021 13:12:42 -0800 Subject: [PATCH] ipn: split LocalBackend off into new ipn/ipnlocal package And move a couple other types down into leafier packages. Now cmd/tailscale doesn't bring in netlink, magicsock, wgengine, etc. Fixes #1181 Signed-off-by: Brad Fitzpatrick --- cmd/tailscale/cli/up.go | 8 +- cmd/tailscale/depaware.txt | 86 ++++++---------- cmd/tailscaled/depaware.txt | 18 ++-- ipn/backend.go | 5 +- ipn/{ => ipnlocal}/local.go | 145 ++++++++++++++------------- ipn/{ => ipnlocal}/local_test.go | 5 +- ipn/{ => ipnlocal}/loglines_test.go | 14 +-- ipn/ipnserver/server.go | 9 +- ipn/ipnstate/ipnstate.go | 6 ++ ipn/prefs.go | 6 +- ipn/prefs_clone.go | 4 +- ipn/prefs_test.go | 10 +- types/preftype/netfiltermode.go | 30 ++++++ wgengine/pendopen.go | 3 +- wgengine/router/router.go | 30 +----- wgengine/router/router_linux.go | 45 +++++---- wgengine/router/router_linux_test.go | 18 ++-- wgengine/userspace.go | 12 +-- wgengine/wgengine.go | 15 +-- 19 files changed, 229 insertions(+), 240 deletions(-) rename ipn/{ => ipnlocal}/local.go (92%) rename ipn/{ => ipnlocal}/local_test.go (99%) rename ipn/{ => ipnlocal}/loglines_test.go (92%) create mode 100644 types/preftype/netfiltermode.go diff --git a/cmd/tailscale/cli/up.go b/cmd/tailscale/cli/up.go index e60801f9b..e4690f021 100644 --- a/cmd/tailscale/cli/up.go +++ b/cmd/tailscale/cli/up.go @@ -22,9 +22,9 @@ import ( "inet.af/netaddr" "tailscale.com/ipn" "tailscale.com/tailcfg" + "tailscale.com/types/preftype" "tailscale.com/version" "tailscale.com/version/distro" - "tailscale.com/wgengine/router" ) var upCmd = &ffcli.Command{ @@ -202,12 +202,12 @@ func runUp(ctx context.Context, args []string) error { if runtime.GOOS == "linux" { switch upArgs.netfilterMode { case "on": - prefs.NetfilterMode = router.NetfilterOn + prefs.NetfilterMode = preftype.NetfilterOn case "nodivert": - prefs.NetfilterMode = router.NetfilterNoDivert + prefs.NetfilterMode = preftype.NetfilterNoDivert warnf("netfilter=nodivert; add iptables calls to ts-* chains manually.") case "off": - prefs.NetfilterMode = router.NetfilterOff + prefs.NetfilterMode = preftype.NetfilterOff warnf("netfilter=off; configure iptables yourself.") default: fatalf("invalid value --netfilter-mode: %q", upArgs.netfilterMode) diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 659a3c4f3..0fab8b1fb 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -4,29 +4,20 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep W 💣 github.com/alexbrainman/sspi/negotiate from tailscale.com/net/tshttpproxy github.com/apenwarr/fixconsole from tailscale.com/cmd/tailscale W 💣 github.com/apenwarr/w32 from github.com/apenwarr/fixconsole - L github.com/coreos/go-iptables/iptables from tailscale.com/wgengine/router - LW github.com/go-multierror/multierror from tailscale.com/wgengine/router - W 💣 github.com/go-ole/go-ole from github.com/go-ole/go-ole/oleutil+ - W 💣 github.com/go-ole/go-ole/oleutil from tailscale.com/wgengine/winnet - L 💣 github.com/godbus/dbus/v5 from tailscale.com/wgengine/router/dns - L 💣 github.com/jsimonetti/rtnetlink from tailscale.com/wgengine/monitor - L github.com/jsimonetti/rtnetlink/internal/unix from github.com/jsimonetti/rtnetlink - L 💣 github.com/mdlayher/netlink from github.com/jsimonetti/rtnetlink+ - L 💣 github.com/mdlayher/netlink/nlenc from github.com/jsimonetti/rtnetlink+ L github.com/mdlayher/sdnotify from tailscale.com/util/systemd github.com/peterbourgon/ff/v2 from github.com/peterbourgon/ff/v2/ffcli github.com/peterbourgon/ff/v2/ffcli from tailscale.com/cmd/tailscale/cli - 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+ - 💣 github.com/tailscale/wireguard-go/device from tailscale.com/wgengine+ + 💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device + 💣 github.com/tailscale/wireguard-go/device from tailscale.com/wgengine/wgcfg github.com/tailscale/wireguard-go/device/tokenbucket from github.com/tailscale/wireguard-go/device 💣 github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device W 💣 github.com/tailscale/wireguard-go/ipc/winpipe from github.com/tailscale/wireguard-go/ipc github.com/tailscale/wireguard-go/ratelimiter from github.com/tailscale/wireguard-go/device github.com/tailscale/wireguard-go/replay from github.com/tailscale/wireguard-go/device github.com/tailscale/wireguard-go/rwcancel from github.com/tailscale/wireguard-go/device+ - github.com/tailscale/wireguard-go/tai64n from github.com/tailscale/wireguard-go/device+ - 💣 github.com/tailscale/wireguard-go/tun from github.com/tailscale/wireguard-go/device+ - W 💣 github.com/tailscale/wireguard-go/tun/wintun from github.com/tailscale/wireguard-go/tun+ + github.com/tailscale/wireguard-go/tai64n from github.com/tailscale/wireguard-go/device + 💣 github.com/tailscale/wireguard-go/tun from github.com/tailscale/wireguard-go/device + W 💣 github.com/tailscale/wireguard-go/tun/wintun from github.com/tailscale/wireguard-go/tun github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck github.com/toqueteos/webbrowser from tailscale.com/cmd/tailscale/cli 💣 go4.org/intern from inet.af/netaddr @@ -35,64 +26,51 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep W 💣 golang.zx2c4.com/wireguard/windows/tunnel/winipcfg from tailscale.com/net/interfaces+ inet.af/netaddr from tailscale.com/cmd/tailscale/cli+ rsc.io/goversion/version from tailscale.com/version - tailscale.com/atomicfile from tailscale.com/ipn+ + tailscale.com/atomicfile from tailscale.com/ipn tailscale.com/cmd/tailscale/cli from tailscale.com/cmd/tailscale - tailscale.com/control/controlclient from tailscale.com/ipn+ - tailscale.com/derp from tailscale.com/derp/derphttp+ - tailscale.com/derp/derphttp from tailscale.com/net/netcheck+ + tailscale.com/control/controlclient from tailscale.com/ipn + tailscale.com/derp from tailscale.com/derp/derphttp + tailscale.com/derp/derphttp from tailscale.com/net/netcheck tailscale.com/derp/derpmap from tailscale.com/cmd/tailscale/cli - tailscale.com/disco from tailscale.com/derp+ - tailscale.com/internal/deepprint from tailscale.com/ipn+ + tailscale.com/disco from tailscale.com/derp tailscale.com/ipn from tailscale.com/cmd/tailscale/cli tailscale.com/ipn/ipnstate from tailscale.com/cmd/tailscale/cli+ - tailscale.com/ipn/policy from tailscale.com/ipn tailscale.com/log/logheap from tailscale.com/control/controlclient - tailscale.com/logtail/backoff from tailscale.com/control/controlclient+ + tailscale.com/logtail/backoff from tailscale.com/control/controlclient tailscale.com/metrics from tailscale.com/derp tailscale.com/net/dnscache from tailscale.com/control/controlclient+ tailscale.com/net/flowtrack from tailscale.com/wgengine/filter+ 💣 tailscale.com/net/interfaces from tailscale.com/cmd/tailscale/cli+ - tailscale.com/net/netcheck from tailscale.com/cmd/tailscale/cli+ + tailscale.com/net/netcheck from tailscale.com/cmd/tailscale/cli tailscale.com/net/netns from tailscale.com/control/controlclient+ - tailscale.com/net/packet from tailscale.com/wgengine+ - tailscale.com/net/stun from tailscale.com/net/netcheck+ + tailscale.com/net/packet from tailscale.com/wgengine/filter + tailscale.com/net/stun from tailscale.com/net/netcheck tailscale.com/net/tlsdial from tailscale.com/control/controlclient+ - tailscale.com/net/tsaddr from tailscale.com/ipn+ + tailscale.com/net/tsaddr from tailscale.com/net/interfaces 💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+ tailscale.com/paths from tailscale.com/cmd/tailscale/cli - tailscale.com/portlist from tailscale.com/ipn tailscale.com/safesocket from tailscale.com/cmd/tailscale/cli 💣 tailscale.com/syncs from tailscale.com/net/interfaces+ tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+ W tailscale.com/tsconst from tailscale.com/net/interfaces - tailscale.com/tstime from tailscale.com/wgengine/magicsock tailscale.com/types/empty from tailscale.com/control/controlclient+ tailscale.com/types/key from tailscale.com/derp+ tailscale.com/types/logger from tailscale.com/cmd/tailscale/cli+ - tailscale.com/types/nettype from tailscale.com/wgengine/magicsock tailscale.com/types/opt from tailscale.com/control/controlclient+ + tailscale.com/types/preftype from tailscale.com/cmd/tailscale/cli+ tailscale.com/types/strbuilder from tailscale.com/net/packet tailscale.com/types/structs from tailscale.com/control/controlclient+ - tailscale.com/types/wgkey from tailscale.com/control/controlclient+ + tailscale.com/types/wgkey from tailscale.com/control/controlclient tailscale.com/util/dnsname from tailscale.com/cmd/tailscale/cli+ - LW tailscale.com/util/endian from tailscale.com/net/netns+ + W tailscale.com/util/endian from tailscale.com/net/netns tailscale.com/util/lineread from tailscale.com/control/controlclient+ - tailscale.com/util/systemd from tailscale.com/control/controlclient+ + tailscale.com/util/systemd from tailscale.com/control/controlclient tailscale.com/version from tailscale.com/cmd/tailscale/cli+ tailscale.com/version/distro from tailscale.com/cmd/tailscale/cli+ - tailscale.com/wgengine from tailscale.com/ipn - tailscale.com/wgengine/filter from tailscale.com/control/controlclient+ - tailscale.com/wgengine/magicsock from tailscale.com/wgengine - 💣 tailscale.com/wgengine/monitor from tailscale.com/wgengine - tailscale.com/wgengine/router from tailscale.com/cmd/tailscale/cli+ - tailscale.com/wgengine/router/dns from tailscale.com/ipn+ - tailscale.com/wgengine/tsdns from tailscale.com/ipn+ - tailscale.com/wgengine/tstun from tailscale.com/wgengine - tailscale.com/wgengine/wgcfg from tailscale.com/control/controlclient+ - tailscale.com/wgengine/wglog from tailscale.com/wgengine - W 💣 tailscale.com/wgengine/winnet from tailscale.com/wgengine/router + tailscale.com/wgengine/filter from tailscale.com/control/controlclient + tailscale.com/wgengine/wgcfg from tailscale.com/control/controlclient golang.org/x/crypto/blake2b from golang.org/x/crypto/nacl/box - golang.org/x/crypto/blake2s from github.com/tailscale/wireguard-go/device+ + golang.org/x/crypto/blake2s from github.com/tailscale/wireguard-go/device golang.org/x/crypto/chacha20 from golang.org/x/crypto/chacha20poly1305 golang.org/x/crypto/chacha20poly1305 from crypto/tls+ golang.org/x/crypto/cryptobyte from crypto/ecdsa+ @@ -103,9 +81,9 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep golang.org/x/crypto/nacl/secretbox from golang.org/x/crypto/nacl/box golang.org/x/crypto/poly1305 from github.com/tailscale/wireguard-go/device+ golang.org/x/crypto/salsa20/salsa from golang.org/x/crypto/nacl/box+ - golang.org/x/net/bpf from github.com/mdlayher/netlink+ + golang.org/x/net/bpf from golang.org/x/net/ipv4+ golang.org/x/net/context/ctxhttp from golang.org/x/oauth2/internal - golang.org/x/net/dns/dnsmessage from net+ + golang.org/x/net/dns/dnsmessage from net golang.org/x/net/http/httpguts from net/http golang.org/x/net/http/httpproxy from net/http golang.org/x/net/http2/hpack from net/http @@ -119,9 +97,9 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep golang.org/x/sync/errgroup from tailscale.com/derp golang.org/x/sync/singleflight from tailscale.com/net/dnscache golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+ - LD golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ + LD golang.org/x/sys/unix from github.com/tailscale/wireguard-go/conn+ W golang.org/x/sys/windows from github.com/apenwarr/fixconsole+ - W golang.org/x/sys/windows/registry from golang.zx2c4.com/wireguard/windows/tunnel/winipcfg+ + W golang.org/x/sys/windows/registry from golang.zx2c4.com/wireguard/windows/tunnel/winipcfg golang.org/x/text/secure/bidirule from golang.org/x/net/idna golang.org/x/text/transform from golang.org/x/text/secure/bidirule+ golang.org/x/text/unicode/bidi from golang.org/x/net/idna+ @@ -158,7 +136,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep debug/elf from rsc.io/goversion/version debug/macho from rsc.io/goversion/version debug/pe from rsc.io/goversion/version - encoding from encoding/json+ + encoding from encoding/json encoding/asn1 from crypto/x509+ encoding/base64 from encoding/json+ encoding/binary from compress/gzip+ @@ -172,7 +150,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep hash from compress/zlib+ hash/adler32 from compress/zlib hash/crc32 from compress/gzip+ - hash/fnv from tailscale.com/wgengine/magicsock hash/maphash from go4.org/mem html from tailscale.com/ipn/ipnstate io from bufio+ @@ -181,7 +158,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep math from compress/flate+ math/big from crypto/dsa+ math/bits from compress/flate+ - math/rand from github.com/mdlayher/netlink+ + math/rand from github.com/tailscale/wireguard-go/device+ mime from golang.org/x/oauth2/internal+ mime/multipart from net/http mime/quotedprintable from mime/multipart @@ -192,16 +169,15 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep net/textproto from golang.org/x/net/http/httpguts+ net/url from crypto/x509+ os from crypto/rand+ - os/exec from github.com/coreos/go-iptables/iptables+ + os/exec from github.com/toqueteos/webbrowser+ os/signal from tailscale.com/cmd/tailscale/cli - L os/user from github.com/godbus/dbus/v5 path from debug/dwarf+ path/filepath from crypto/x509+ reflect from crypto/x509+ - regexp from github.com/coreos/go-iptables/iptables+ + regexp from rsc.io/goversion/version regexp/syntax from regexp runtime/debug from golang.org/x/sync/singleflight - runtime/pprof from tailscale.com/log/logheap+ + runtime/pprof from tailscale.com/log/logheap sort from compress/flate+ strconv from compress/flate+ strings from bufio+ diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 45f4f3a08..ac3eef2a2 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -73,11 +73,12 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/derp/derphttp from tailscale.com/net/netcheck+ tailscale.com/derp/derpmap from tailscale.com/cmd/tailscaled tailscale.com/disco from tailscale.com/derp+ - tailscale.com/internal/deepprint from tailscale.com/ipn+ - tailscale.com/ipn from tailscale.com/ipn/ipnserver + tailscale.com/internal/deepprint from tailscale.com/ipn/ipnlocal+ + tailscale.com/ipn from tailscale.com/ipn/ipnserver+ + tailscale.com/ipn/ipnlocal from tailscale.com/ipn/ipnserver tailscale.com/ipn/ipnserver from tailscale.com/cmd/tailscaled tailscale.com/ipn/ipnstate from tailscale.com/ipn+ - tailscale.com/ipn/policy from tailscale.com/ipn + tailscale.com/ipn/policy from tailscale.com/ipn/ipnlocal tailscale.com/log/filelogger from tailscale.com/ipn/ipnserver tailscale.com/log/logheap from tailscale.com/control/controlclient tailscale.com/logpolicy from tailscale.com/cmd/tailscaled @@ -87,17 +88,17 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/metrics from tailscale.com/derp tailscale.com/net/dnscache from tailscale.com/control/controlclient+ tailscale.com/net/flowtrack from tailscale.com/wgengine/filter+ - 💣 tailscale.com/net/interfaces from tailscale.com/ipn+ + 💣 tailscale.com/net/interfaces from tailscale.com/cmd/tailscaled+ tailscale.com/net/netcheck from tailscale.com/wgengine/magicsock tailscale.com/net/netns from tailscale.com/control/controlclient+ 💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnserver tailscale.com/net/packet from tailscale.com/wgengine+ tailscale.com/net/stun from tailscale.com/net/netcheck+ tailscale.com/net/tlsdial from tailscale.com/control/controlclient+ - tailscale.com/net/tsaddr from tailscale.com/ipn+ + tailscale.com/net/tsaddr from tailscale.com/ipn/ipnlocal+ 💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+ tailscale.com/paths from tailscale.com/cmd/tailscaled+ - tailscale.com/portlist from tailscale.com/ipn + tailscale.com/portlist from tailscale.com/ipn/ipnlocal tailscale.com/safesocket from tailscale.com/ipn/ipnserver tailscale.com/smallzstd from tailscale.com/ipn/ipnserver+ 💣 tailscale.com/syncs from tailscale.com/net/interfaces+ @@ -110,6 +111,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/types/logger from tailscale.com/cmd/tailscaled+ tailscale.com/types/nettype from tailscale.com/wgengine/magicsock tailscale.com/types/opt from tailscale.com/control/controlclient+ + tailscale.com/types/preftype from tailscale.com/ipn+ tailscale.com/types/strbuilder from tailscale.com/net/packet tailscale.com/types/structs from tailscale.com/control/controlclient+ tailscale.com/types/wgkey from tailscale.com/control/controlclient+ @@ -127,8 +129,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de 💣 tailscale.com/wgengine/monitor from tailscale.com/wgengine+ tailscale.com/wgengine/netstack from tailscale.com/cmd/tailscaled tailscale.com/wgengine/router from tailscale.com/cmd/tailscaled+ - tailscale.com/wgengine/router/dns from tailscale.com/ipn+ - tailscale.com/wgengine/tsdns from tailscale.com/ipn+ + tailscale.com/wgengine/router/dns from tailscale.com/ipn/ipnlocal+ + tailscale.com/wgengine/tsdns from tailscale.com/ipn/ipnlocal+ tailscale.com/wgengine/tstun from tailscale.com/wgengine+ tailscale.com/wgengine/wgcfg from tailscale.com/control/controlclient+ tailscale.com/wgengine/wglog from tailscale.com/wgengine diff --git a/ipn/backend.go b/ipn/backend.go index 8042b6625..85bb0581f 100644 --- a/ipn/backend.go +++ b/ipn/backend.go @@ -14,7 +14,6 @@ import ( "tailscale.com/tailcfg" "tailscale.com/types/empty" "tailscale.com/types/structs" - "tailscale.com/wgengine" ) type State int @@ -46,10 +45,10 @@ func (s State) String() string { // EngineStatus contains WireGuard engine stats. type EngineStatus struct { - RBytes, WBytes wgengine.ByteCount + RBytes, WBytes int64 NumLive int LiveDERPs int // number of active DERP connections - LivePeers map[tailcfg.NodeKey]wgengine.PeerStatus + LivePeers map[tailcfg.NodeKey]ipnstate.PeerStatusLite } // Notify is a communication from a backend (e.g. tailscaled) to a frontend diff --git a/ipn/local.go b/ipn/ipnlocal/local.go similarity index 92% rename from ipn/local.go rename to ipn/ipnlocal/local.go index 0877ad9f7..cb42ce347 100644 --- a/ipn/local.go +++ b/ipn/ipnlocal/local.go @@ -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 ipn +package ipnlocal import ( "bytes" @@ -19,6 +19,7 @@ import ( "inet.af/netaddr" "tailscale.com/control/controlclient" "tailscale.com/internal/deepprint" + "tailscale.com/ipn" "tailscale.com/ipn/ipnstate" "tailscale.com/ipn/policy" "tailscale.com/net/interfaces" @@ -66,7 +67,7 @@ type LocalBackend struct { keyLogf logger.Logf // for printing list of peers on change statsLogf logger.Logf // for printing peers stats on change e wgengine.Engine - store StateStore + store ipn.StateStore backendLogID string portpoll *portlist.Poller // may be nil portpollOnce sync.Once // guards starting readPoller @@ -78,21 +79,21 @@ type LocalBackend struct { // The mutex protects the following elements. mu sync.Mutex - notify func(Notify) + notify func(ipn.Notify) c *controlclient.Client - stateKey StateKey // computed in part from user-provided value - userID string // current controlling user ID (for Windows, primarily) - prefs *Prefs + stateKey ipn.StateKey // computed in part from user-provided value + userID string // current controlling user ID (for Windows, primarily) + prefs *ipn.Prefs inServerMode bool machinePrivKey wgkey.Private - state State + state ipn.State // hostinfo is mutated in-place while mu is held. hostinfo *tailcfg.Hostinfo // netMap is not mutated in-place once set. netMap *controlclient.NetworkMap nodeByAddr map[netaddr.IP]*tailcfg.Node activeLogin string // last logged LoginName from netMap - engineStatus EngineStatus + engineStatus ipn.EngineStatus endpoints []string blocked bool authURL string @@ -107,7 +108,7 @@ type LocalBackend struct { // NewLocalBackend returns a new LocalBackend that is ready to run, // but is not actually running. -func NewLocalBackend(logf logger.Logf, logid string, store StateStore, e wgengine.Engine) (*LocalBackend, error) { +func NewLocalBackend(logf logger.Logf, logid string, store ipn.StateStore, e wgengine.Engine) (*LocalBackend, error) { if e == nil { panic("ipn.NewLocalBackend: wgengine must not be nil") } @@ -130,7 +131,7 @@ func NewLocalBackend(logf logger.Logf, logid string, store StateStore, e wgengin e: e, store: store, backendLogID: logid, - state: NoState, + state: ipn.NoState, portpoll: portpoll, gotPortPollRes: make(chan struct{}), } @@ -151,7 +152,7 @@ func (b *LocalBackend) linkChange(major bool, ifst *interfaces.State) { networkUp := ifst.AnyInterfaceUp() if b.c != nil { - go b.c.SetPaused(b.state == Stopped || !networkUp) + go b.c.SetPaused(b.state == ipn.Stopped || !networkUp) } // If the PAC-ness of the network changed, reconfig wireguard+route to @@ -159,7 +160,7 @@ func (b *LocalBackend) linkChange(major bool, ifst *interfaces.State) { if hadPAC != ifst.HasPAC() { b.logf("linkChange: in state %v; PAC changed from %v->%v", b.state, hadPAC, ifst.HasPAC()) switch b.state { - case NoState, Stopped: + case ipn.NoState, ipn.Stopped: // Do nothing. default: go b.authReconfig() @@ -280,7 +281,7 @@ func (b *LocalBackend) setClientStatus(st controlclient.Status) { // Auth completed, unblock the engine b.blockEngineUpdates(false) b.authReconfig() - b.send(Notify{LoginFinished: &empty.Message{}}) + b.send(ipn.Notify{LoginFinished: &empty.Message{}}) } prefsChanged := false @@ -311,7 +312,7 @@ func (b *LocalBackend) setClientStatus(st controlclient.Status) { if st.URL != "" { b.authURL = st.URL } - if b.state == NeedsLogin { + if b.state == ipn.NeedsLogin { if !b.prefs.WantRunning { prefsChanged = true } @@ -331,7 +332,7 @@ func (b *LocalBackend) setClientStatus(st controlclient.Status) { b.logf("Failed to save new controlclient state: %v", err) } } - b.send(Notify{Prefs: prefs}) + b.send(ipn.Notify{Prefs: prefs}) } if st.NetMap != nil { if netMap != nil { @@ -350,7 +351,7 @@ func (b *LocalBackend) setClientStatus(st controlclient.Status) { } b.e.SetDERPMap(st.NetMap.DERPMap) - b.send(Notify{NetMap: st.NetMap}) + b.send(ipn.Notify{NetMap: st.NetMap}) } if st.URL != "" { b.logf("Received auth URL: %.20v...", st.URL) @@ -392,7 +393,7 @@ func (b *LocalBackend) setWgengineStatus(s *wgengine.Status, err error) { b.statusChanged.Broadcast() b.statusLock.Unlock() - b.send(Notify{Engine: &es}) + b.send(ipn.Notify{Engine: &es}) } // Start applies the configuration specified in opts, and starts the @@ -405,7 +406,7 @@ func (b *LocalBackend) setWgengineStatus(s *wgengine.Status, err error) { // guarantee that switching from one user's state to another is // actually a supported operation (it should be, but it's very unclear // from the following whether or not that is a safe transition). -func (b *LocalBackend) Start(opts Options) error { +func (b *LocalBackend) Start(opts ipn.Options) error { if opts.Prefs == nil && opts.StateKey == "" { return errors.New("no state key or prefs provided") } @@ -438,7 +439,7 @@ func (b *LocalBackend) Start(opts Options) error { hostinfo.NetInfo = b.hostinfo.NetInfo } b.hostinfo = hostinfo - b.state = NoState + b.state = ipn.NoState if err := b.loadStateLocked(opts.StateKey, opts.Prefs, opts.LegacyConfigPath); err != nil { b.mu.Unlock() @@ -535,8 +536,8 @@ func (b *LocalBackend) Start(opts Options) error { blid := b.backendLogID b.logf("Backend: logs: be:%v fe:%v", blid, opts.FrontendLogID) - b.send(Notify{BackendLogID: &blid}) - b.send(Notify{Prefs: prefs}) + b.send(ipn.Notify{BackendLogID: &blid}) + b.send(ipn.Notify{Prefs: prefs}) cli.Login(nil, controlclient.LoginDefault) return nil @@ -544,7 +545,7 @@ func (b *LocalBackend) Start(opts Options) error { // updateFilter updates the packet filter in wgengine based on the // given netMap and user preferences. -func (b *LocalBackend) updateFilter(netMap *controlclient.NetworkMap, prefs *Prefs) { +func (b *LocalBackend) updateFilter(netMap *controlclient.NetworkMap, prefs *ipn.Prefs) { // NOTE(danderson): keep change detection as the first thing in // this function. Don't try to optimize by returning early, more // likely than not you'll just end up breaking the change @@ -701,7 +702,7 @@ func (b *LocalBackend) readPoller() { // send delivers n to the connected frontend. If no frontend is // connected, the notification is dropped without being delivered. -func (b *LocalBackend) send(n Notify) { +func (b *LocalBackend) send(n ipn.Notify) { b.mu.Lock() notify := b.notify b.mu.Unlock() @@ -727,9 +728,9 @@ func (b *LocalBackend) popBrowserAuthNow() { b.blockEngineUpdates(true) b.stopEngineAndWait() - b.send(Notify{BrowseToURL: &url}) - if b.State() == Running { - b.enterState(Starting) + b.send(ipn.Notify{BrowseToURL: &url}) + if b.State() == ipn.Running { + b.enterState(ipn.Starting) } } @@ -760,21 +761,21 @@ func (b *LocalBackend) initMachineKeyLocked() (err error) { legacyMachineKey = b.prefs.Persist.LegacyFrontendPrivateMachineKey } - keyText, err := b.store.ReadState(MachineKeyStateKey) + keyText, err := b.store.ReadState(ipn.MachineKeyStateKey) if err == nil { if err := b.machinePrivKey.UnmarshalText(keyText); err != nil { - return fmt.Errorf("invalid key in %s key of %v: %w", MachineKeyStateKey, b.store, err) + return fmt.Errorf("invalid key in %s key of %v: %w", ipn.MachineKeyStateKey, b.store, err) } if b.machinePrivKey.IsZero() { - return fmt.Errorf("invalid zero key stored in %v key of %v", MachineKeyStateKey, b.store) + return fmt.Errorf("invalid zero key stored in %v key of %v", ipn.MachineKeyStateKey, b.store) } if !legacyMachineKey.IsZero() && !bytes.Equal(legacyMachineKey[:], b.machinePrivKey[:]) { b.logf("frontend-provided legacy machine key ignored; used value from server state") } return nil } - if err != ErrStateNotExist { - return fmt.Errorf("error reading %v key of %v: %w", MachineKeyStateKey, b.store, err) + if err != ipn.ErrStateNotExist { + return fmt.Errorf("error reading %v key of %v: %w", ipn.MachineKeyStateKey, b.store, err) } // If we didn't find one already on disk and the prefs already @@ -797,7 +798,7 @@ func (b *LocalBackend) initMachineKeyLocked() (err error) { } keyText, _ = b.machinePrivKey.MarshalText() - if err := b.store.WriteState(MachineKeyStateKey, keyText); err != nil { + if err := b.store.WriteState(ipn.MachineKeyStateKey, keyText); err != nil { b.logf("error writing machine key to store: %v", err) return err } @@ -810,14 +811,14 @@ func (b *LocalBackend) initMachineKeyLocked() (err error) { // user and prefs. If userID is blank or prefs is blank, no work is done. // // b.mu may either be held or not. -func (b *LocalBackend) writeServerModeStartState(userID string, prefs *Prefs) { +func (b *LocalBackend) writeServerModeStartState(userID string, prefs *ipn.Prefs) { if userID == "" || prefs == nil { return } if prefs.ForceDaemon { - stateKey := StateKey("user-" + userID) - if err := b.store.WriteState(ServerModeStartKey, []byte(stateKey)); err != nil { + stateKey := ipn.StateKey("user-" + userID) + if err := b.store.WriteState(ipn.ServerModeStartKey, []byte(stateKey)); err != nil { b.logf("WriteState error: %v", err) } // It's important we do this here too, even if it looks @@ -829,7 +830,7 @@ func (b *LocalBackend) writeServerModeStartState(userID string, prefs *Prefs) { b.logf("WriteState error: %v", err) } } else { - if err := b.store.WriteState(ServerModeStartKey, nil); err != nil { + if err := b.store.WriteState(ipn.ServerModeStartKey, nil); err != nil { b.logf("WriteState error: %v", err) } } @@ -838,7 +839,7 @@ func (b *LocalBackend) writeServerModeStartState(userID string, prefs *Prefs) { // loadStateLocked sets b.prefs and b.stateKey based on a complex // combination of key, prefs, and legacyPath. b.mu must be held when // calling. -func (b *LocalBackend) loadStateLocked(key StateKey, prefs *Prefs, legacyPath string) (err error) { +func (b *LocalBackend) loadStateLocked(key ipn.StateKey, prefs *ipn.Prefs, legacyPath string) (err error) { if prefs == nil && key == "" { panic("state key and prefs are both unset") } @@ -880,19 +881,19 @@ func (b *LocalBackend) loadStateLocked(key StateKey, prefs *Prefs, legacyPath st b.logf("using backend prefs") bs, err := b.store.ReadState(key) if err != nil { - if errors.Is(err, ErrStateNotExist) { + if errors.Is(err, ipn.ErrStateNotExist) { if legacyPath != "" { - b.prefs, err = LoadPrefs(legacyPath) + b.prefs, err = ipn.LoadPrefs(legacyPath) if err != nil { if !errors.Is(err, os.ErrNotExist) { b.logf("failed to load legacy prefs: %v", err) } - b.prefs = NewPrefs() + b.prefs = ipn.NewPrefs() } else { b.logf("imported prefs from relaynode for %q: %v", key, b.prefs.Pretty()) } } else { - b.prefs = NewPrefs() + b.prefs = ipn.NewPrefs() b.logf("created empty state for %q: %s", key, b.prefs.Pretty()) } if err := b.initMachineKeyLocked(); err != nil { @@ -902,7 +903,7 @@ func (b *LocalBackend) loadStateLocked(key StateKey, prefs *Prefs, legacyPath st } return fmt.Errorf("store.ReadState(%q): %v", key, err) } - b.prefs, err = PrefsFromBytes(bs, false) + b.prefs, err = ipn.PrefsFromBytes(bs, false) if err != nil { return fmt.Errorf("PrefsFromBytes: %v", err) } @@ -914,7 +915,7 @@ func (b *LocalBackend) loadStateLocked(key StateKey, prefs *Prefs, legacyPath st } // State returns the backend state machine's current state. -func (b *LocalBackend) State() State { +func (b *LocalBackend) State() ipn.State { b.mu.Lock() defer b.mu.Unlock() @@ -930,7 +931,7 @@ func (b *LocalBackend) InServerMode() bool { // getEngineStatus returns a copy of b.engineStatus. // // TODO(bradfitz): remove this and use Status() throughout. -func (b *LocalBackend) getEngineStatus() EngineStatus { +func (b *LocalBackend) getEngineStatus() ipn.EngineStatus { b.mu.Lock() defer b.mu.Unlock() @@ -986,7 +987,7 @@ func (b *LocalBackend) FakeExpireAfter(x time.Duration) { mapCopy.Expiry = time.Now().Add(x) } b.setNetMapLocked(&mapCopy) - b.send(Notify{NetMap: b.netMap}) + b.send(ipn.Notify{NetMap: b.netMap}) } func (b *LocalBackend) Ping(ipStr string) { @@ -996,7 +997,7 @@ func (b *LocalBackend) Ping(ipStr string) { return } b.e.Ping(ip, func(pr *ipnstate.PingResult) { - b.send(Notify{PingResult: pr}) + b.send(ipn.Notify{PingResult: pr}) }) } @@ -1005,11 +1006,11 @@ func (b *LocalBackend) Ping(ipStr string) { // b.mu must be held; mostly because the caller is about to anyway, and doing so // gives us slightly better guarantees about the two peers stats lines not // being intermixed if there are concurrent calls to our caller. -func (b *LocalBackend) parseWgStatusLocked(s *wgengine.Status) (ret EngineStatus) { +func (b *LocalBackend) parseWgStatusLocked(s *wgengine.Status) (ret ipn.EngineStatus) { var peerStats, peerKeys strings.Builder ret.LiveDERPs = s.DERPs - ret.LivePeers = map[tailcfg.NodeKey]wgengine.PeerStatus{} + ret.LivePeers = map[tailcfg.NodeKey]ipnstate.PeerStatusLite{} for _, p := range s.Peers { if !p.LastHandshake.IsZero() { fmt.Fprintf(&peerStats, "%d/%d ", p.RxBytes, p.TxBytes) @@ -1065,7 +1066,7 @@ func (b *LocalBackend) SetWantRunning(wantRunning bool) { // SetPrefs saves new user preferences and propagates them throughout // the system. Implements Backend. -func (b *LocalBackend) SetPrefs(newp *Prefs) { +func (b *LocalBackend) SetPrefs(newp *ipn.Prefs) { if newp == nil { panic("SetPrefs got nil prefs") } @@ -1132,7 +1133,7 @@ func (b *LocalBackend) SetPrefs(newp *Prefs) { b.authReconfig() } - b.send(Notify{Prefs: newp}) + b.send(ipn.Notify{Prefs: newp}) } // doSetHostinfoFilterServices calls SetHostinfo on the controlclient, @@ -1256,7 +1257,7 @@ func magicDNSRootDomains(nm *controlclient.NetworkMap) []string { } // routerConfig produces a router.Config from a wireguard config and IPN prefs. -func routerConfig(cfg *wgcfg.Config, prefs *Prefs) *router.Config { +func routerConfig(cfg *wgcfg.Config, prefs *ipn.Prefs) *router.Config { rs := &router.Config{ LocalAddrs: unmapIPPrefixes(cfg.Addresses), SubnetRoutes: unmapIPPrefixes(prefs.AdvertiseRoutes), @@ -1285,7 +1286,7 @@ func unmapIPPrefixes(ippsList ...[]netaddr.IPPrefix) (ret []netaddr.IPPrefix) { return ret } -func applyPrefsToHostinfo(hi *tailcfg.Hostinfo, prefs *Prefs) { +func applyPrefsToHostinfo(hi *tailcfg.Hostinfo, prefs *ipn.Prefs) { if h := prefs.Hostname; h != "" { hi.Hostname = h } @@ -1305,7 +1306,7 @@ func applyPrefsToHostinfo(hi *tailcfg.Hostinfo, prefs *Prefs) { // places twiddle IPN internal state without going through here, so // really this is more "one of several places in which random things // happen". -func (b *LocalBackend) enterState(newState State) { +func (b *LocalBackend) enterState(newState ipn.State) { b.mu.Lock() state := b.state b.state = newState @@ -1323,19 +1324,19 @@ func (b *LocalBackend) enterState(newState State) { b.logf("Switching ipn state %v -> %v (WantRunning=%v)", state, newState, prefs.WantRunning) if notify != nil { - b.send(Notify{State: &newState}) + b.send(ipn.Notify{State: &newState}) } if bc != nil { - bc.SetPaused(newState == Stopped || !networkUp) + bc.SetPaused(newState == ipn.Stopped || !networkUp) } switch newState { - case NeedsLogin: + case ipn.NeedsLogin: systemd.Status("Needs login: %s", authURL) b.blockEngineUpdates(true) fallthrough - case Stopped: + case ipn.Stopped: err := b.e.Reconfig(&wgcfg.Config{}, &router.Config{}) if err != nil { b.logf("Reconfig(down): %v", err) @@ -1344,11 +1345,11 @@ func (b *LocalBackend) enterState(newState State) { if authURL == "" { systemd.Status("Stopped; run 'tailscale up' to log in") } - case Starting, NeedsMachineAuth: + case ipn.Starting, ipn.NeedsMachineAuth: b.authReconfig() // Needed so that UpdateEndpoints can run b.e.RequestStatus() - case Running: + case ipn.Running: var addrs []string for _, addr := range b.netMap.Addresses { addrs = append(addrs, addr.IP.String()) @@ -1362,7 +1363,7 @@ func (b *LocalBackend) enterState(newState State) { // nextState returns the state the backend seems to be in, based on // its internal state. -func (b *LocalBackend) nextState() State { +func (b *LocalBackend) nextState() ipn.State { b.mu.Lock() b.assertClientLocked() var ( @@ -1378,31 +1379,31 @@ func (b *LocalBackend) nextState() State { if c.AuthCantContinue() { // Auth was interrupted or waiting for URL visit, // so it won't proceed without human help. - return NeedsLogin + return ipn.NeedsLogin } else { // Auth or map request needs to finish return state } case !wantRunning: - return Stopped + return ipn.Stopped case !netMap.Expiry.IsZero() && time.Until(netMap.Expiry) <= 0: - return NeedsLogin + return ipn.NeedsLogin case netMap.MachineStatus != tailcfg.MachineAuthorized: // TODO(crawshaw): handle tailcfg.MachineInvalid - return NeedsMachineAuth - case state == NeedsMachineAuth: + return ipn.NeedsMachineAuth + case state == ipn.NeedsMachineAuth: // (if we get here, we know MachineAuthorized == true) - return Starting - case state == Starting: + return ipn.Starting + case state == ipn.Starting: if st := b.getEngineStatus(); st.NumLive > 0 || st.LiveDERPs > 0 { - return Running + return ipn.Running } else { return state } - case state == Running: - return Running + case state == ipn.Running: + return ipn.Running default: - return Starting + return ipn.Starting } } @@ -1414,7 +1415,7 @@ func (b *LocalBackend) RequestEngineStatus() { // RequestStatus implements Backend. func (b *LocalBackend) RequestStatus() { st := b.Status() - b.send(Notify{Status: st}) + b.send(ipn.Notify{Status: st}) } // stateMachine updates the state machine state based on other things diff --git a/ipn/local_test.go b/ipn/ipnlocal/local_test.go similarity index 99% rename from ipn/local_test.go rename to ipn/ipnlocal/local_test.go index 547262f61..ec9400952 100644 --- a/ipn/local_test.go +++ b/ipn/ipnlocal/local_test.go @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package ipn +package ipnlocal import ( + "testing" + "inet.af/netaddr" "tailscale.com/control/controlclient" "tailscale.com/tailcfg" - "testing" ) func TestNetworkMapCompare(t *testing.T) { diff --git a/ipn/loglines_test.go b/ipn/ipnlocal/loglines_test.go similarity index 92% rename from ipn/loglines_test.go rename to ipn/ipnlocal/loglines_test.go index fb056e8be..656758afe 100644 --- a/ipn/loglines_test.go +++ b/ipn/ipnlocal/loglines_test.go @@ -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 ipn +package ipnlocal import ( "reflect" @@ -10,6 +10,8 @@ import ( "time" "tailscale.com/control/controlclient" + "tailscale.com/ipn" + "tailscale.com/ipn/ipnstate" "tailscale.com/logtail" "tailscale.com/tailcfg" "tailscale.com/tstest" @@ -38,9 +40,7 @@ func TestLocalLogLines(t *testing.T) { idA := logid(0xaa) // set up a LocalBackend, super bare bones. No functional data. - store := &MemoryStore{ - cache: make(map[StateKey][]byte), - } + store := &ipn.MemoryStore{} e, err := wgengine.NewFakeUserspaceEngine(logListen.Logf, 0, nil) if err != nil { t.Fatal(err) @@ -53,7 +53,7 @@ func TestLocalLogLines(t *testing.T) { defer lb.Shutdown() // custom adjustments for required non-nil fields - lb.prefs = NewPrefs() + lb.prefs = ipn.NewPrefs() lb.hostinfo = &tailcfg.Hostinfo{} // hacky manual override of the usual log-on-change behaviour of keylogf lb.keyLogf = logListen.Logf @@ -68,7 +68,7 @@ func TestLocalLogLines(t *testing.T) { // log prefs line persist := &controlclient.Persist{} - prefs := NewPrefs() + prefs := ipn.NewPrefs() prefs.Persist = persist lb.SetPrefs(prefs) @@ -76,7 +76,7 @@ func TestLocalLogLines(t *testing.T) { // log peers, peer keys status := &wgengine.Status{ - Peers: []wgengine.PeerStatus{wgengine.PeerStatus{ + Peers: []ipnstate.PeerStatusLite{{ TxBytes: 10, RxBytes: 10, LastHandshake: time.Now(), diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index dd8a39ab6..bc120ca60 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -28,6 +28,7 @@ import ( "inet.af/netaddr" "tailscale.com/control/controlclient" "tailscale.com/ipn" + "tailscale.com/ipn/ipnlocal" "tailscale.com/log/filelogger" "tailscale.com/logtail/backoff" "tailscale.com/net/netstat" @@ -93,7 +94,7 @@ type Options struct { // server is an IPN backend and its set of 0 or more active connections // talking to an IPN backend. type server struct { - b *ipn.LocalBackend + b *ipnlocal.LocalBackend logf logger.Logf // resetOnZero is whether to call bs.Reset on transition from // 1->0 connections. That is, this is whether the backend is @@ -612,7 +613,7 @@ func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() ( } } - b, err := ipn.NewLocalBackend(logf, logid, store, eng) + b, err := ipnlocal.NewLocalBackend(logf, logid, store, eng) if err != nil { return fmt.Errorf("NewLocalBackend: %v", err) } @@ -878,7 +879,7 @@ func (s *server) localhostHandler(ci connIdentity) http.Handler { }) } -func serveHTMLStatus(w http.ResponseWriter, b *ipn.LocalBackend) { +func serveHTMLStatus(w http.ResponseWriter, b *ipnlocal.LocalBackend) { w.Header().Set("Content-Type", "text/html; charset=utf-8") st := b.Status() // TODO(bradfitz): add LogID and opts to st? @@ -896,7 +897,7 @@ func peerPid(entries []netstat.Entry, la, ra netaddr.IPPort) int { // whoIsHandler is the debug server's /debug?ip=$IP HTTP handler. type whoIsHandler struct { - b *ipn.LocalBackend + b *ipnlocal.LocalBackend } func (h whoIsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { diff --git a/ipn/ipnstate/ipnstate.go b/ipn/ipnstate/ipnstate.go index fbddbc46b..3f2d359f7 100644 --- a/ipn/ipnstate/ipnstate.go +++ b/ipn/ipnstate/ipnstate.go @@ -50,6 +50,12 @@ func (s *Status) Peers() []key.Public { return kk } +type PeerStatusLite struct { + TxBytes, RxBytes int64 + LastHandshake time.Time + NodeKey tailcfg.NodeKey +} + type PeerStatus struct { PublicKey key.Public HostName string // HostInfo's Hostname (not a DNS name or necessarily unique) diff --git a/ipn/prefs.go b/ipn/prefs.go index f8256454b..cb6bf2869 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -18,7 +18,7 @@ import ( "inet.af/netaddr" "tailscale.com/atomicfile" "tailscale.com/control/controlclient" - "tailscale.com/wgengine/router" + "tailscale.com/types/preftype" ) //go:generate go run tailscale.com/cmd/cloner -type=Prefs -output=prefs_clone.go @@ -116,7 +116,7 @@ type Prefs struct { // NetfilterMode specifies how much to manage netfilter rules for // Tailscale, if at all. - NetfilterMode router.NetfilterMode + NetfilterMode preftype.NetfilterMode // The Persist field is named 'Config' in the file for backward // compatibility with earlier versions. @@ -240,7 +240,7 @@ func NewPrefs() *Prefs { AllowSingleHosts: true, CorpDNS: true, WantRunning: true, - NetfilterMode: router.NetfilterOn, + NetfilterMode: preftype.NetfilterOn, } } diff --git a/ipn/prefs_clone.go b/ipn/prefs_clone.go index c0e11f8f8..950e34145 100644 --- a/ipn/prefs_clone.go +++ b/ipn/prefs_clone.go @@ -9,7 +9,7 @@ package ipn import ( "inet.af/netaddr" "tailscale.com/control/controlclient" - "tailscale.com/wgengine/router" + "tailscale.com/types/preftype" ) // Clone makes a deep copy of Prefs. @@ -46,6 +46,6 @@ var _PrefsNeedsRegeneration = Prefs(struct { ForceDaemon bool AdvertiseRoutes []netaddr.IPPrefix NoSNAT bool - NetfilterMode router.NetfilterMode + NetfilterMode preftype.NetfilterMode Persist *controlclient.Persist }{}) diff --git a/ipn/prefs_test.go b/ipn/prefs_test.go index 9715d7c89..77278446c 100644 --- a/ipn/prefs_test.go +++ b/ipn/prefs_test.go @@ -16,8 +16,8 @@ import ( "inet.af/netaddr" "tailscale.com/control/controlclient" "tailscale.com/tstest" + "tailscale.com/types/preftype" "tailscale.com/types/wgkey" - "tailscale.com/wgengine/router" ) func fieldsOf(t reflect.Type) (fields []string) { @@ -192,13 +192,13 @@ func TestPrefsEqual(t *testing.T) { }, { - &Prefs{NetfilterMode: router.NetfilterOff}, - &Prefs{NetfilterMode: router.NetfilterOn}, + &Prefs{NetfilterMode: preftype.NetfilterOff}, + &Prefs{NetfilterMode: preftype.NetfilterOn}, false, }, { - &Prefs{NetfilterMode: router.NetfilterOn}, - &Prefs{NetfilterMode: router.NetfilterOn}, + &Prefs{NetfilterMode: preftype.NetfilterOn}, + &Prefs{NetfilterMode: preftype.NetfilterOn}, true, }, diff --git a/types/preftype/netfiltermode.go b/types/preftype/netfiltermode.go new file mode 100644 index 000000000..7e8dec9dd --- /dev/null +++ b/types/preftype/netfiltermode.go @@ -0,0 +1,30 @@ +// Copyright (c) 2021 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 preftype is a leaf package containing types for various +// preferences. +package preftype + +// NetfilterMode is the firewall management mode to use when +// programming the Linux network stack. +type NetfilterMode int + +const ( + NetfilterOff NetfilterMode = iota // remove all tailscale netfilter state + NetfilterNoDivert // manage tailscale chains, but don't call them + NetfilterOn // manage tailscale chains and call them from main chains +) + +func (m NetfilterMode) String() string { + switch m { + case NetfilterOff: + return "off" + case NetfilterNoDivert: + return "nodivert" + case NetfilterOn: + return "on" + default: + return "???" + } +} diff --git a/wgengine/pendopen.go b/wgengine/pendopen.go index f465f6542..2ede0429a 100644 --- a/wgengine/pendopen.go +++ b/wgengine/pendopen.go @@ -9,6 +9,7 @@ import ( "strconv" "time" + "tailscale.com/ipn/ipnstate" "tailscale.com/net/flowtrack" "tailscale.com/net/packet" "tailscale.com/wgengine/filter" @@ -158,7 +159,7 @@ func (e *userspaceEngine) onOpenTimeout(flow flowtrack.Tuple) { lastSeen = *n.LastSeen } - var ps *PeerStatus + var ps *ipnstate.PeerStatusLite if st, err := e.getStatus(); err == nil { for _, v := range st.Peers { if v.NodeKey == n.Key { diff --git a/wgengine/router/router.go b/wgengine/router/router.go index c65a0b806..9c3f1003f 100644 --- a/wgengine/router/router.go +++ b/wgengine/router/router.go @@ -11,6 +11,7 @@ import ( "github.com/tailscale/wireguard-go/tun" "inet.af/netaddr" "tailscale.com/types/logger" + "tailscale.com/types/preftype" "tailscale.com/wgengine/router/dns" ) @@ -53,29 +54,6 @@ func Cleanup(logf logger.Logf, interfaceName string) { cleanup(logf, interfaceName) } -// NetfilterMode is the firewall management mode to use when -// programming the Linux network stack. -type NetfilterMode int - -const ( - NetfilterOff NetfilterMode = iota // remove all tailscale netfilter state - NetfilterNoDivert // manage tailscale chains, but don't call them - NetfilterOn // manage tailscale chains and call them from main chains -) - -func (m NetfilterMode) String() string { - switch m { - case NetfilterOff: - return "off" - case NetfilterNoDivert: - return "nodivert" - case NetfilterOn: - return "on" - default: - return "???" - } -} - // Config is the subset of Tailscale configuration that is relevant to // the OS's network stack. type Config struct { @@ -86,9 +64,9 @@ type Config struct { // Linux-only things below, ignored on other platforms. - SubnetRoutes []netaddr.IPPrefix // subnets being advertised to other Tailscale nodes - SNATSubnetRoutes bool // SNAT traffic to local subnets - NetfilterMode NetfilterMode // how much to manage netfilter rules + SubnetRoutes []netaddr.IPPrefix // subnets being advertised to other Tailscale nodes + SNATSubnetRoutes bool // SNAT traffic to local subnets + NetfilterMode preftype.NetfilterMode // how much to manage netfilter rules } // shutdownConfig is a routing configuration that removes all router diff --git a/wgengine/router/router_linux.go b/wgengine/router/router_linux.go index d6e10dac1..c3724d77f 100644 --- a/wgengine/router/router_linux.go +++ b/wgengine/router/router_linux.go @@ -21,10 +21,17 @@ import ( "inet.af/netaddr" "tailscale.com/net/tsaddr" "tailscale.com/types/logger" + "tailscale.com/types/preftype" "tailscale.com/version/distro" "tailscale.com/wgengine/router/dns" ) +const ( + netfilterOff = preftype.NetfilterOff + netfilterNoDivert = preftype.NetfilterNoDivert + netfilterOn = preftype.NetfilterOn +) + // The following bits are added to packet marks for Tailscale use. // // We tried to pick bits sufficiently out of the way that it's @@ -89,7 +96,7 @@ type linuxRouter struct { addrs map[netaddr.IPPrefix]bool routes map[netaddr.IPPrefix]bool snatSubnetRoutes bool - netfilterMode NetfilterMode + netfilterMode preftype.NetfilterMode // Various feature checks for the network stack. ipRuleAvailable bool @@ -148,7 +155,7 @@ func newUserspaceRouterAdvanced(logf logger.Logf, tunname string, netfilter4, ne return &linuxRouter{ logf: logf, tunname: tunname, - netfilterMode: NetfilterOff, + netfilterMode: netfilterOff, ipRuleAvailable: ipRuleAvailable, v6Available: supportsV6, @@ -168,7 +175,7 @@ func (r *linuxRouter) Up() error { if err := r.addIPRules(); err != nil { return err } - if err := r.setNetfilterMode(NetfilterOff); err != nil { + if err := r.setNetfilterMode(netfilterOff); err != nil { return err } if err := r.upInterface(); err != nil { @@ -188,7 +195,7 @@ func (r *linuxRouter) Close() error { if err := r.delIPRules(); err != nil { return err } - if err := r.setNetfilterMode(NetfilterOff); err != nil { + if err := r.setNetfilterMode(netfilterOff); err != nil { return err } @@ -246,9 +253,9 @@ func (r *linuxRouter) Set(cfg *Config) error { // mode. Netfilter state is created or deleted appropriately to // reflect the new mode, and r.snatSubnetRoutes is updated to reflect // the current state of subnet SNATing. -func (r *linuxRouter) setNetfilterMode(mode NetfilterMode) error { +func (r *linuxRouter) setNetfilterMode(mode preftype.NetfilterMode) error { if distro.Get() == distro.Synology { - mode = NetfilterOff + mode = netfilterOff } if r.netfilterMode == mode { return nil @@ -264,9 +271,9 @@ func (r *linuxRouter) setNetfilterMode(mode NetfilterMode) error { reprocess := false switch mode { - case NetfilterOff: + case netfilterOff: switch r.netfilterMode { - case NetfilterNoDivert: + case netfilterNoDivert: if err := r.delNetfilterBase(); err != nil { return err } @@ -276,7 +283,7 @@ func (r *linuxRouter) setNetfilterMode(mode NetfilterMode) error { // This can happen if someone left a ref to // this table somewhere else. } - case NetfilterOn: + case netfilterOn: if err := r.delNetfilterHooks(); err != nil { return err } @@ -291,9 +298,9 @@ func (r *linuxRouter) setNetfilterMode(mode NetfilterMode) error { } } r.snatSubnetRoutes = false - case NetfilterNoDivert: + case netfilterNoDivert: switch r.netfilterMode { - case NetfilterOff: + case netfilterOff: reprocess = true if err := r.addNetfilterChains(); err != nil { return err @@ -302,12 +309,12 @@ func (r *linuxRouter) setNetfilterMode(mode NetfilterMode) error { return err } r.snatSubnetRoutes = false - case NetfilterOn: + case netfilterOn: if err := r.delNetfilterHooks(); err != nil { return err } } - case NetfilterOn: + case netfilterOn: // Because of bugs in old version of iptables-compat, // we can't add a "-j ts-forward" rule to FORWARD // while ts-forward contains an "-m mark" rule. But @@ -315,7 +322,7 @@ func (r *linuxRouter) setNetfilterMode(mode NetfilterMode) error { // So we have to delNetFilterBase, then add the hooks, // then re-addNetFilterBase, just in case. switch r.netfilterMode { - case NetfilterOff: + case netfilterOff: reprocess = true if err := r.addNetfilterChains(); err != nil { return err @@ -330,7 +337,7 @@ func (r *linuxRouter) setNetfilterMode(mode NetfilterMode) error { return err } r.snatSubnetRoutes = false - case NetfilterNoDivert: + case netfilterNoDivert: reprocess = true if err := r.delNetfilterBase(); err != nil { return err @@ -397,7 +404,7 @@ func (r *linuxRouter) delAddress(addr netaddr.IPPrefix) error { // addLoopbackRule adds a firewall rule to permit loopback traffic to // a local Tailscale IP. func (r *linuxRouter) addLoopbackRule(addr netaddr.IP) error { - if r.netfilterMode == NetfilterOff { + if r.netfilterMode == netfilterOff { return nil } @@ -419,7 +426,7 @@ func (r *linuxRouter) addLoopbackRule(addr netaddr.IP) error { // delLoopbackRule removes the firewall rule permitting loopback // traffic to a Tailscale IP. func (r *linuxRouter) delLoopbackRule(addr netaddr.IP) error { - if r.netfilterMode == NetfilterOff { + if r.netfilterMode == netfilterOff { return nil } @@ -903,7 +910,7 @@ func (r *linuxRouter) delNetfilterHooks() error { // addSNATRule adds a netfilter rule to SNAT traffic destined for // local subnets. func (r *linuxRouter) addSNATRule() error { - if r.netfilterMode == NetfilterOff { + if r.netfilterMode == netfilterOff { return nil } @@ -922,7 +929,7 @@ func (r *linuxRouter) addSNATRule() error { // delSNATRule removes the netfilter rule to SNAT traffic destined for // local subnets. Fails if the rule does not exist. func (r *linuxRouter) delSNATRule() error { - if r.netfilterMode == NetfilterOff { + if r.netfilterMode == netfilterOff { return nil } diff --git a/wgengine/router/router_linux_test.go b/wgengine/router/router_linux_test.go index bcc93af8f..8298c6d07 100644 --- a/wgengine/router/router_linux_test.go +++ b/wgengine/router/router_linux_test.go @@ -58,7 +58,7 @@ up` + basic, name: "local addr only", in: &Config{ LocalAddrs: mustCIDRs("100.101.102.103/10"), - NetfilterMode: NetfilterOff, + NetfilterMode: netfilterOff, }, want: ` up @@ -70,7 +70,7 @@ ip addr add 100.101.102.103/10 dev tailscale0` + basic, in: &Config{ LocalAddrs: mustCIDRs("100.101.102.103/10"), Routes: mustCIDRs("100.100.100.100/32", "192.168.16.0/24"), - NetfilterMode: NetfilterOff, + NetfilterMode: netfilterOff, }, want: ` up @@ -85,7 +85,7 @@ ip route add 192.168.16.0/24 dev tailscale0 table 52` + basic, LocalAddrs: mustCIDRs("100.101.102.103/10"), Routes: mustCIDRs("100.100.100.100/32", "192.168.16.0/24"), SubnetRoutes: mustCIDRs("200.0.0.0/8"), - NetfilterMode: NetfilterOff, + NetfilterMode: netfilterOff, }, want: ` up @@ -101,7 +101,7 @@ ip route add 192.168.16.0/24 dev tailscale0 table 52` + basic, Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"), SubnetRoutes: mustCIDRs("200.0.0.0/8"), SNATSubnetRoutes: true, - NetfilterMode: NetfilterOn, + NetfilterMode: netfilterOn, }, want: ` up @@ -133,7 +133,7 @@ v6/nat/ts-postrouting -m mark --mark 0x40000 -j MASQUERADE in: &Config{ LocalAddrs: mustCIDRs("100.101.102.104/10"), Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"), - NetfilterMode: NetfilterOn, + NetfilterMode: netfilterOn, }, want: ` up @@ -166,7 +166,7 @@ v6/nat/POSTROUTING -j ts-postrouting Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"), SubnetRoutes: mustCIDRs("200.0.0.0/8"), SNATSubnetRoutes: false, - NetfilterMode: NetfilterOn, + NetfilterMode: netfilterOn, }, want: ` up @@ -196,7 +196,7 @@ v6/nat/POSTROUTING -j ts-postrouting in: &Config{ LocalAddrs: mustCIDRs("100.101.102.104/10"), Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"), - NetfilterMode: NetfilterOn, + NetfilterMode: netfilterOn, }, want: ` up @@ -227,7 +227,7 @@ v6/nat/POSTROUTING -j ts-postrouting in: &Config{ LocalAddrs: mustCIDRs("100.101.102.104/10"), Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"), - NetfilterMode: NetfilterNoDivert, + NetfilterMode: netfilterNoDivert, }, want: ` up @@ -251,7 +251,7 @@ v6/filter/ts-forward -o tailscale0 -j ACCEPT in: &Config{ LocalAddrs: mustCIDRs("100.101.102.104/10"), Routes: mustCIDRs("100.100.100.100/32", "10.0.0.0/8"), - NetfilterMode: NetfilterOn, + NetfilterMode: netfilterOn, }, want: ` up diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 8638b3d38..03b391bca 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -1082,8 +1082,8 @@ func (e *userspaceEngine) getStatus() (*Status, error) { errc <- err }() - pp := make(map[wgkey.Key]*PeerStatus) - p := &PeerStatus{} + pp := make(map[wgkey.Key]*ipnstate.PeerStatusLite) + p := &ipnstate.PeerStatusLite{} var hst1, hst2, n int64 @@ -1115,20 +1115,20 @@ func (e *userspaceEngine) getStatus() (*Status, error) { if err != nil { return nil, fmt.Errorf("IpcGetOperation: invalid key in line %q", line) } - p = &PeerStatus{} + p = &ipnstate.PeerStatusLite{} pp[wgkey.Key(pk)] = p key := tailcfg.NodeKey(pk) p.NodeKey = key case "rx_bytes": n, err = mem.ParseInt(v, 10, 64) - p.RxBytes = ByteCount(n) + p.RxBytes = n if err != nil { return nil, fmt.Errorf("IpcGetOperation: rx_bytes invalid: %#v", line) } case "tx_bytes": n, err = mem.ParseInt(v, 10, 64) - p.TxBytes = ByteCount(n) + p.TxBytes = n if err != nil { return nil, fmt.Errorf("IpcGetOperation: tx_bytes invalid: %#v", line) } @@ -1154,7 +1154,7 @@ func (e *userspaceEngine) getStatus() (*Status, error) { e.mu.Lock() defer e.mu.Unlock() - var peers []PeerStatus + var peers []ipnstate.PeerStatusLite for _, pk := range e.peerSequence { if p, ok := pp[pk]; ok { // ignore idle ones not in wireguard-go's config peers = append(peers, *p) diff --git a/wgengine/wgengine.go b/wgengine/wgengine.go index 563888083..ff3efb6a0 100644 --- a/wgengine/wgengine.go +++ b/wgengine/wgengine.go @@ -6,7 +6,6 @@ package wgengine import ( "errors" - "time" "inet.af/netaddr" "tailscale.com/control/controlclient" @@ -19,23 +18,11 @@ import ( "tailscale.com/wgengine/wgcfg" ) -// ByteCount is the number of bytes that have been sent or received. -// -// TODO: why is this a type? remove? -// TODO: document whether it's payload bytes only or if it includes framing overhead. -type ByteCount int64 - -type PeerStatus struct { - TxBytes, RxBytes ByteCount - LastHandshake time.Time - NodeKey tailcfg.NodeKey -} - // Status is the Engine status. // // TODO(bradfitz): remove this, subset of ipnstate? Need to migrate users. type Status struct { - Peers []PeerStatus + Peers []ipnstate.PeerStatusLite LocalAddrs []string // the set of possible endpoints for the magic conn DERPs int // number of active DERP connections }