From 2c48b4ee144109dc894dddaaac9d017a4b7c98d3 Mon Sep 17 00:00:00 2001 From: David Crawshaw Date: Mon, 23 Nov 2020 09:28:32 -0500 Subject: [PATCH 01/36] tailcfg: remove outdated comments about Clone methods The cloner tool adds static checks that the Clone methods are up to date, so failing to update Clone causes a compiler error. Signed-off-by: David Crawshaw --- tailcfg/tailcfg.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index a93c11c5b..466567e8a 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -112,8 +112,6 @@ type User struct { Logins []LoginID Roles []RoleID Created time.Time - - // Note: be sure to update Clone when adding new fields } type Login struct { @@ -156,9 +154,6 @@ type Node struct { KeepAlive bool // open and keep open a connection to this peer MachineAuthorized bool // TODO(crawshaw): replace with MachineStatus - - // NOTE: any new fields containing pointers in this type - // require changes to Node.Clone. } type MachineStatus int @@ -275,9 +270,6 @@ type Service struct { Description string `json:",omitempty"` // text description of service // TODO(apenwarr): allow advertising services on subnet IPs? // TODO(apenwarr): add "tags" here for each service? - - // NOTE: any new fields containing pointers in this type - // require changes to Hostinfo.Clone. } // Hostinfo contains a summary of a Tailscale host. @@ -302,7 +294,7 @@ type Hostinfo struct { NetInfo *NetInfo `json:",omitempty"` // NOTE: any new fields containing pointers in this type - // require changes to Hostinfo.Clone and Hostinfo.Equal. + // require changes to Hostinfo.Equal. } // NetInfo contains information about the host's network state. @@ -354,7 +346,7 @@ type NetInfo struct { // the control plane. DERPLatency map[string]float64 `json:",omitempty"` - // Update Clone and BasicallyEqual when adding fields. + // Update BasicallyEqual when adding fields. } func (ni *NetInfo) String() string { From 72e082aaf5845c3e99ef085bbad07cabbb916286 Mon Sep 17 00:00:00 2001 From: Alex Brainman Date: Sun, 22 Nov 2020 11:34:26 +1100 Subject: [PATCH 02/36] ipn: make LoadPrefs return os.ErrNotExist when reading corrupted files It appears some users have corrupted pref.conf files. Have LoadPrefs treat these files as non-existent. This way tailscale will make user login, and not crash. Fixes #954 Signed-off-by: Alex Brainman --- ipn/prefs.go | 4 ++++ ipn/prefs_test.go | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/ipn/prefs.go b/ipn/prefs.go index d70dded6a..539d8df5b 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -5,6 +5,7 @@ package ipn import ( + "bytes" "encoding/json" "fmt" "io/ioutil" @@ -276,6 +277,9 @@ func LoadPrefs(filename string) (*Prefs, error) { if err != nil { return nil, fmt.Errorf("LoadPrefs open: %w", err) // err includes path } + if bytes.Contains(data, jsonEscapedZero) { + return nil, os.ErrNotExist + } p, err := PrefsFromBytes(data, false) if err != nil { return nil, fmt.Errorf("LoadPrefs(%q) decode: %w", filename, err) diff --git a/ipn/prefs_test.go b/ipn/prefs_test.go index 8b95d87a4..105683511 100644 --- a/ipn/prefs_test.go +++ b/ipn/prefs_test.go @@ -7,6 +7,7 @@ package ipn import ( "errors" "fmt" + "io/ioutil" "os" "reflect" "testing" @@ -371,3 +372,25 @@ func TestLoadPrefsNotExist(t *testing.T) { } t.Fatalf("unexpected prefs=%#v, err=%v", p, err) } + +// TestLoadPrefsFileWithZeroInIt verifies that LoadPrefs hanldes corrupted input files. +// See issue #954 for details. +func TestLoadPrefsFileWithZeroInIt(t *testing.T) { + f, err := ioutil.TempFile("", "TestLoadPrefsFileWithZeroInIt") + if err != nil { + t.Fatal(err) + } + path := f.Name() + if _, err := f.Write(jsonEscapedZero); err != nil { + t.Fatal(err) + } + f.Close() + defer os.Remove(path) + + p, err := LoadPrefs(path) + if errors.Is(err, os.ErrNotExist) { + // expected. + return + } + t.Fatalf("unexpected prefs=%#v, err=%v", p, err) +} From cd6099113fa037ed43a71ce764506f608d6007c5 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 24 Nov 2020 11:07:49 -0800 Subject: [PATCH 03/36] ipn: add a comment about skipping files with null bytes Updates #954 --- ipn/prefs.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ipn/prefs.go b/ipn/prefs.go index 539d8df5b..c65ca6095 100644 --- a/ipn/prefs.go +++ b/ipn/prefs.go @@ -278,6 +278,11 @@ func LoadPrefs(filename string) (*Prefs, error) { return nil, fmt.Errorf("LoadPrefs open: %w", err) // err includes path } if bytes.Contains(data, jsonEscapedZero) { + // Tailscale 1.2.0 - 1.2.8 on Windows had a memory corruption bug + // in the backend process that ended up sending NULL bytes over JSON + // to the frontend which wrote them out to JSON files on disk. + // So if we see one, treat is as corrupt and the user will need + // to log in again. (better than crashing) return nil, os.ErrNotExist } p, err := PrefsFromBytes(data, false) From 3a7402aa2d02f1d65db395e346f9d081699fb8bd Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 23 Nov 2020 18:35:49 -0800 Subject: [PATCH 04/36] logtail: help the server be more efficient Add content length hints to headers. The server can use these hints to more efficiently select buffers. Stop attempting to compress tiny requests. The bandwidth savings are negligible (and sometimes negative!), and it makes extra work for the server. Signed-off-by: Josh Bleecher Snyder --- logtail/logtail.go | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/logtail/logtail.go b/logtail/logtail.go index 9cedb6bc3..b9c94e98f 100644 --- a/logtail/logtail.go +++ b/logtail/logtail.go @@ -14,6 +14,7 @@ import ( "io/ioutil" "net/http" "os" + "strconv" "time" "tailscale.com/logtail/backoff" @@ -259,8 +260,17 @@ func (l *logger) uploading(ctx context.Context) { for { body := l.drainPending() - if l.zstdEncoder != nil { - body = l.zstdEncoder.EncodeAll(body, nil) + origlen := -1 // sentinel value: uncompressed + // Don't attempt to compress tiny bodies; not worth the CPU cycles. + if l.zstdEncoder != nil && len(body) > 256 { + zbody := l.zstdEncoder.EncodeAll(body, nil) + // Only send it compressed if the bandwidth savings are sufficient. + // Just the extra headers associated with enabling compression + // are 50 bytes by themselves. + if len(body)-len(zbody) > 64 { + origlen = len(body) + body = zbody + } } for len(body) > 0 { @@ -269,7 +279,7 @@ func (l *logger) uploading(ctx context.Context) { return default: } - uploaded, err := l.upload(ctx, body) + uploaded, err := l.upload(ctx, body, origlen) if err != nil { fmt.Fprintf(l.stderr, "logtail: upload: %v\n", err) } @@ -287,7 +297,10 @@ func (l *logger) uploading(ctx context.Context) { } } -func (l *logger) upload(ctx context.Context, body []byte) (uploaded bool, err error) { +// upload uploads body to the log server. +// origlen indicates the pre-compression body length. +// origlen of -1 indicates that the body is not compressed. +func (l *logger) upload(ctx context.Context, body []byte, origlen int) (uploaded bool, err error) { req, err := http.NewRequest("POST", l.url, bytes.NewReader(body)) if err != nil { // I know of no conditions under which this could fail. @@ -295,8 +308,9 @@ func (l *logger) upload(ctx context.Context, body []byte) (uploaded bool, err er // TODO record logs to disk panic("logtail: cannot build http request: " + err.Error()) } - if l.zstdEncoder != nil { + if origlen != -1 { req.Header.Add("Content-Encoding", "zstd") + req.Header.Add("Orig-Content-Length", strconv.Itoa(origlen)) } req.Header["User-Agent"] = nil // not worth writing one; save some bytes @@ -306,7 +320,7 @@ func (l *logger) upload(ctx context.Context, body []byte) (uploaded bool, err er req = req.WithContext(ctx) compressedNote := "not-compressed" - if l.zstdEncoder != nil { + if origlen != -1 { compressedNote = "compressed" } From c43138272073ef6566e117a92a8bcc0d23effd7f Mon Sep 17 00:00:00 2001 From: Dmytro Tananayskiy Date: Thu, 19 Nov 2020 23:50:26 +0200 Subject: [PATCH 05/36] Fix receiver in order to be consistent: syncs.WaitGroupChan Signed-off-by: Dmytro Tananayskiy --- syncs/syncs.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/syncs/syncs.go b/syncs/syncs.go index c0208c996..0139ad925 100644 --- a/syncs/syncs.go +++ b/syncs/syncs.go @@ -33,7 +33,7 @@ func NewWaitGroupChan() *WaitGroupChan { } // DoneChan returns a channel that's closed on completion. -func (c *WaitGroupChan) DoneChan() <-chan struct{} { return c.done } +func (wg *WaitGroupChan) DoneChan() <-chan struct{} { return wg.done } // Add adds delta, which may be negative, to the WaitGroupChan // counter. If the counter becomes zero, all goroutines blocked on @@ -46,10 +46,10 @@ func (c *WaitGroupChan) DoneChan() <-chan struct{} { return c.done } // than zero, may happen at any time. Typically this means the calls // to Add should execute before the statement creating the goroutine // or other event to be waited for. -func (c *WaitGroupChan) Add(delta int) { - n := atomic.AddInt64(&c.n, int64(delta)) +func (wg *WaitGroupChan) Add(delta int) { + n := atomic.AddInt64(&wg.n, int64(delta)) if n == 0 { - close(c.done) + close(wg.done) } } From ab482118ad7e04bcf871fffec0f880fe44429b5d Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 25 Nov 2020 10:27:01 -0800 Subject: [PATCH 06/36] tailcfg: add some missing json omitempty Noticed these in MapResponses to clients. MachineAuthorized was set true, but once we fix the coordination server to zero out that field, then it can be omittted. --- tailcfg/tailcfg.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 466567e8a..d766a55b3 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -151,9 +151,9 @@ type Node struct { Created time.Time LastSeen *time.Time `json:",omitempty"` - KeepAlive bool // open and keep open a connection to this peer + KeepAlive bool `json:",omitempty"` // open and keep open a connection to this peer - MachineAuthorized bool // TODO(crawshaw): replace with MachineStatus + MachineAuthorized bool `json:",omitempty"` // TODO(crawshaw): replace with MachineStatus } type MachineStatus int @@ -279,7 +279,7 @@ type Service struct { type Hostinfo struct { // TODO(crawshaw): mark all these fields ",omitempty" when all the // iOS apps are updated with the latest swift version of this struct. - IPNVersion string // version of this code + IPNVersion string `json:",omitempty"` // version of this code FrontendLogID string `json:",omitempty"` // logtail ID of frontend instance BackendLogID string `json:",omitempty"` // logtail ID of backend instance OS string // operating system the client runs on (a version.OS value) From c0af7deb867a0c2fa95be4a37b941643e1d5f962 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 30 Nov 2020 18:05:51 -0800 Subject: [PATCH 07/36] tailcfg, cmd/tailscale: add Hostinfo.ShareeNode, hide in "tailscale status" --- cmd/tailscale/cli/status.go | 3 +++ ipn/ipnstate/ipnstate.go | 9 +++++++++ ipn/local.go | 1 + tailcfg/tailcfg.go | 1 + tailcfg/tailcfg_clone.go | 1 + tailcfg/tailcfg_test.go | 14 +++++++++++--- 6 files changed, 26 insertions(+), 3 deletions(-) diff --git a/cmd/tailscale/cli/status.go b/cmd/tailscale/cli/status.go index 54476f1b0..782c4d8ef 100644 --- a/cmd/tailscale/cli/status.go +++ b/cmd/tailscale/cli/status.go @@ -169,6 +169,9 @@ func runStatus(ctx context.Context, args []string) error { } for _, peer := range st.Peers() { ps := st.Peer[peer] + if ps.ShareeNode { + continue + } active := peerActive(ps) if statusArgs.active && !active { continue diff --git a/ipn/ipnstate/ipnstate.go b/ipn/ipnstate/ipnstate.go index 703dca26c..06559ce44 100644 --- a/ipn/ipnstate/ipnstate.go +++ b/ipn/ipnstate/ipnstate.go @@ -64,6 +64,12 @@ type PeerStatus struct { LastHandshake time.Time // with local wireguard KeepAlive bool + // ShareeNode indicates this node exists in the netmap because + // it's owned by a shared-to user and that node might connect + // to us. These nodes should be hidden by "tailscale status" + // etc by default. + ShareeNode bool `json:",omitempty"` + // InNetworkMap means that this peer was seen in our latest network map. // In theory, all of InNetworkMap and InMagicSock and InEngine should all be true. InNetworkMap bool @@ -218,6 +224,9 @@ func (sb *StatusBuilder) AddPeer(peer key.Public, st *PeerStatus) { if st.KeepAlive { e.KeepAlive = true } + if st.ShareeNode { + e.ShareeNode = true + } } type StatusUpdater interface { diff --git a/ipn/local.go b/ipn/local.go index 1bc5b3e9d..a27384224 100644 --- a/ipn/local.go +++ b/ipn/local.go @@ -221,6 +221,7 @@ func (b *LocalBackend) UpdateStatus(sb *ipnstate.StatusBuilder) { KeepAlive: p.KeepAlive, Created: p.Created, LastSeen: lastSeen, + ShareeNode: p.Hostinfo.ShareeNode, }) } } diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index d766a55b3..e4a16176b 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -287,6 +287,7 @@ type Hostinfo struct { DeviceModel string `json:",omitempty"` // mobile phone model ("Pixel 3a", "iPhone 11 Pro") Hostname string // name of the host the client runs on ShieldsUp bool `json:",omitempty"` // indicates whether the host is blocking incoming connections + ShareeNode bool `json:",omitempty"` // indicates this node exists in netmap because it's owned by a shared-to user GoArch string `json:",omitempty"` // the host's GOARCH value (of the running binary) RoutableIPs []wgcfg.CIDR `json:",omitempty"` // set of IP ranges this client can route RequestTags []string `json:",omitempty"` // set of ACL tags this node wants to claim diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 01473d0ed..d89607dd4 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -106,6 +106,7 @@ var _HostinfoNeedsRegeneration = Hostinfo(struct { DeviceModel string Hostname string ShieldsUp bool + ShareeNode bool GoArch string RoutableIPs []wgcfg.CIDR RequestTags []string diff --git a/tailcfg/tailcfg_test.go b/tailcfg/tailcfg_test.go index 8a2e1e5ab..3f8cbcf69 100644 --- a/tailcfg/tailcfg_test.go +++ b/tailcfg/tailcfg_test.go @@ -23,9 +23,12 @@ func fieldsOf(t reflect.Type) (fields []string) { func TestHostinfoEqual(t *testing.T) { hiHandles := []string{ - "IPNVersion", "FrontendLogID", "BackendLogID", "OS", "OSVersion", - "DeviceModel", "Hostname", "ShieldsUp", "GoArch", "RoutableIPs", - "RequestTags", "Services", "NetInfo", + "IPNVersion", "FrontendLogID", "BackendLogID", + "OS", "OSVersion", "DeviceModel", "Hostname", + "ShieldsUp", "ShareeNode", + "GoArch", + "RoutableIPs", "RequestTags", + "Services", "NetInfo", } if have := fieldsOf(reflect.TypeOf(Hostinfo{})); !reflect.DeepEqual(have, hiHandles) { t.Errorf("Hostinfo.Equal check might be out of sync\nfields: %q\nhandled: %q\n", @@ -169,6 +172,11 @@ func TestHostinfoEqual(t *testing.T) { &Hostinfo{Services: []Service{Service{Proto: TCP, Port: 1234, Description: "foo"}}}, true, }, + { + &Hostinfo{ShareeNode: true}, + &Hostinfo{}, + false, + }, } for i, tt := range tests { got := tt.a.Equal(tt.b) From 4c8ccd6dd623089e1934a9d2f9fe44e1ea8a97b3 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 1 Dec 2020 18:16:39 -0800 Subject: [PATCH 08/36] tailcfg: document new debug flag. --- tailcfg/tailcfg.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index e4a16176b..ea3055285 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -512,6 +512,8 @@ type MapRequest struct { // router but their IP forwarding is broken. // * "v6-overlay": IPv6 development flag to have control send // v6 node addrs + // * "minimize-netmap": have control minimize the netmap, removing + // peers that are unreachable per ACLS. DebugFlags []string `json:",omitempty"` } From dfbde3d3aaedbe04510d780d071a200004bd53fe Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 1 Dec 2020 20:08:55 -0800 Subject: [PATCH 09/36] ipn: pass through the prefix length from control. Control sets this to /32 for IPv4 and /128 for IPv6. Signed-off-by: David Anderson --- ipn/local.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipn/local.go b/ipn/local.go index a27384224..c17a0a8b6 100644 --- a/ipn/local.go +++ b/ipn/local.go @@ -1257,7 +1257,7 @@ func routerConfig(cfg *wgcfg.Config, prefs *Prefs) *router.Config { for _, addr := range cfg.Addresses { addrs = append(addrs, wgcfg.CIDR{ IP: addr.IP, - Mask: 32, + Mask: addr.Mask, }) } From be6fe393c5b43e055e2c4b5601d0d89822852aba Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 1 Dec 2020 20:09:20 -0800 Subject: [PATCH 10/36] wgengine: don't try pinging IPv6 addresses in legacy pinger. Signed-off-by: David Anderson --- wgengine/userspace.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 9c3253ea5..997b39719 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -515,6 +515,13 @@ func (p *pinger) run(ctx context.Context, peerKey wgcfg.Key, ips []wgcfg.IP, src start := time.Now() var dstIPs []packet.IP4 for _, ip := range ips { + if ip.Is6() { + // This code is only used for legacy (pre-discovery) + // peers. They're not going to work right with IPv6 on the + // overlay anyway, so don't bother trying to make ping + // work. + continue + } dstIPs = append(dstIPs, packet.IP4FromNetaddr(netaddr.IPFrom16(ip.Addr))) } From 713cbe84c12fe67e3b92c1d8e98f9b9b7b3418cd Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 2 Dec 2020 20:18:49 -0800 Subject: [PATCH 11/36] wgengine/magicsock: use net.JoinHostPort when host might have colons (udp6) Only affected tests. (where it just generated log spam) --- wgengine/magicsock/magicsock.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 09ead62d4..15af3326b 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -2500,13 +2500,13 @@ func (c *Conn) bind1(ruc **RebindingUDPConn, which string) error { var err error listenCtx := context.Background() // unused without DNS name to resolve if c.pconnPort == 0 && DefaultPort != 0 { - pc, err = c.listenPacket(listenCtx, which, fmt.Sprintf("%s:%d", host, DefaultPort)) + pc, err = c.listenPacket(listenCtx, which, net.JoinHostPort(host, fmt.Sprint(DefaultPort))) if err != nil { c.logf("magicsock: bind: default port %s/%v unavailable; picking random", which, DefaultPort) } } if pc == nil { - pc, err = c.listenPacket(listenCtx, which, fmt.Sprintf("%s:%d", host, c.pconnPort)) + pc, err = c.listenPacket(listenCtx, which, net.JoinHostPort(host, fmt.Sprint(c.pconnPort))) } if err != nil { c.logf("magicsock: bind(%s/%v): %v", which, c.pconnPort, err) From 7b92f8e7186cc491605b6f1cb24dda304c735a95 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 2 Dec 2020 20:12:14 -0800 Subject: [PATCH 12/36] wgengine/magicsock: add start of magicsock benchmarks (Conn.ReceiveIPv4 for now) And only single-threaded for now. Will get fancier later. Updates #414 --- wgengine/magicsock/magicsock_test.go | 78 ++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 17d931e1f..a308e8dd7 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -56,7 +56,7 @@ func init() { // conditions in tests. In particular, you can't expect two test magicsocks // to be able to connect to each other through a test DERP unless they are // both fully initialized before you try. -func (c *Conn) WaitReady(t *testing.T) { +func (c *Conn) WaitReady(t testing.TB) { t.Helper() timer := time.NewTimer(10 * time.Second) defer timer.Stop() @@ -130,7 +130,7 @@ type magicStack struct { // newMagicStack builds and initializes an idle magicsock and // friends. You need to call conn.SetNetworkMap and dev.Reconfig // before anything interesting happens. -func newMagicStack(t *testing.T, logf logger.Logf, l nettype.PacketListener, derpMap *tailcfg.DERPMap) *magicStack { +func newMagicStack(t testing.TB, logf logger.Logf, l nettype.PacketListener, derpMap *tailcfg.DERPMap) *magicStack { t.Helper() privateKey, err := wgcfg.NewPrivateKey() @@ -377,7 +377,7 @@ collectEndpoints: } } -func pickPort(t *testing.T) uint16 { +func pickPort(t testing.TB) uint16 { t.Helper() conn, err := net.ListenPacket("udp4", "127.0.0.1:0") if err != nil { @@ -1344,3 +1344,75 @@ func TestDiscoEndpointAlignment(t *testing.T) { t.Error("expected false on second call") } } + +func BenchmarkReceiveFrom(b *testing.B) { + port := pickPort(b) + conn, err := NewConn(Options{ + Logf: b.Logf, + Port: port, + EndpointsFunc: func(eps []string) { + b.Logf("endpoints: %q", eps) + }, + }) + if err != nil { + b.Fatal(err) + } + defer conn.Close() + + sendConn, err := net.ListenPacket("udp4", "127.0.0.1:0") + if err != nil { + b.Fatal(err) + } + defer sendConn.Close() + + var dstAddr net.Addr = conn.pconn4.LocalAddr() + sendBuf := make([]byte, 1<<10) + for i := range sendBuf { + sendBuf[i] = 'x' + } + + buf := make([]byte, 2<<10) + for i := 0; i < b.N; i++ { + if _, err := sendConn.WriteTo(sendBuf, dstAddr); err != nil { + b.Fatalf("WriteTo: %v", err) + } + n, ep, addr, err := conn.ReceiveIPv4(buf) + if err != nil { + b.Fatal(err) + } + _ = n + _ = ep + _ = addr + } +} + +func BenchmarkReceiveFrom_Native(b *testing.B) { + recvConn, err := net.ListenPacket("udp4", "127.0.0.1:0") + if err != nil { + b.Fatal(err) + } + defer recvConn.Close() + recvConnUDP := recvConn.(*net.UDPConn) + + sendConn, err := net.ListenPacket("udp4", "127.0.0.1:0") + if err != nil { + b.Fatal(err) + } + defer sendConn.Close() + + var dstAddr net.Addr = recvConn.LocalAddr() + sendBuf := make([]byte, 1<<10) + for i := range sendBuf { + sendBuf[i] = 'x' + } + + buf := make([]byte, 2<<10) + for i := 0; i < b.N; i++ { + if _, err := sendConn.WriteTo(sendBuf, dstAddr); err != nil { + b.Fatalf("WriteTo: %v", err) + } + if _, _, err := recvConnUDP.ReadFromUDP(buf); err != nil { + b.Fatalf("ReadFromUDP: %v", err) + } + } +} From 88179121e384afce8c33cf9b4c20684d2ffab722 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 3 Dec 2020 12:08:07 -0800 Subject: [PATCH 13/36] version: bump date --- version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/version.go b/version/version.go index eb6033dbd..87d6507fd 100644 --- a/version/version.go +++ b/version/version.go @@ -10,7 +10,7 @@ package version // Long is a full version number for this build, of the form // "x.y.z-commithash", or "date.yyyymmdd" if no actual version was // provided. -const Long = "date.20201107" +const Long = "date.20201203" // Short is a short version number for this build, of the form // "x.y.z", or "date.yyyymmdd" if no actual version was provided. From 9503be083ddaa72d208be1fbbd3bab1a5cd80c91 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 3 Dec 2020 12:16:10 -0800 Subject: [PATCH 14/36] tailcfg: update comments a bit --- tailcfg/tailcfg.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index ea3055285..1036b7517 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -475,7 +475,7 @@ type MapRequest struct { // History of versions: // 3: implicit compression, keep-alives // 4: opt-in keep-alives via KeepAlive field, opt-in compression via Compress - // 5: 2020-10-19, implies IncludeIPv6, DeltaPeers/DeltaUserProfiles, supports MagicDNS + // 5: 2020-10-19, implies IncludeIPv6, delta Peers/UserProfiles, supports MagicDNS Version int Compress string // "zstd" or "" (no compression) KeepAlive bool // whether server should send keep-alives back to us @@ -596,14 +596,15 @@ type MapResponse struct { // Peers, if non-empty, is the complete list of peers. // It will be set in the first MapResponse for a long-polled request/response. - // Subsequent responses will be delta-encoded if DeltaPeers was set in the request. + // Subsequent responses will be delta-encoded if MapRequest.Version >= 5 and server + // chooses, in which case Peers will be nil or zero length. // If Peers is non-empty, PeersChanged and PeersRemoved should // be ignored (and should be empty). // Peers is always returned sorted by Node.ID. Peers []*Node `json:",omitempty"` // PeersChanged are the Nodes (identified by their ID) that // have changed or been added since the past update on the - // HTTP response. It's only set if MapRequest.DeltaPeers was true. + // HTTP response. It's not used by the server if MapRequest.Version < 5. // PeersChanged is always returned sorted by Node.ID. PeersChanged []*Node `json:",omitempty"` // PeersRemoved are the NodeIDs that are no longer in the peer list. From 05e5233e07857dea256c3d1b0088b368cf9f5243 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Sun, 6 Dec 2020 19:46:11 -0800 Subject: [PATCH 15/36] net/netcheck: don't send flood of PCP unmap requests to router Updates #810 --- net/netcheck/netcheck.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index cdb767bff..ff6f9ddb7 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -710,6 +710,7 @@ func (rs *reportState) probePortMapServices() { uc.WriteTo(pcpPacket(myIP, tempPort, false), port5351) res := make([]byte, 1500) + sentPCPDelete := false for { n, addr, err := uc.ReadFrom(res) if err != nil { @@ -727,11 +728,14 @@ func (rs *reportState) probePortMapServices() { if n == 60 && res[0] == 0x02 { // right length and version 2 rs.setOptBool(&rs.report.PCP, true) - // And now delete the mapping. - // (PCP is the only protocol of the three that requires - // we cause a side effect to detect whether it's present, - // so we need to redo that side effect now.) - uc.WriteTo(pcpPacket(myIP, tempPort, true), port5351) + if !sentPCPDelete { + sentPCPDelete = true + // And now delete the mapping. + // (PCP is the only protocol of the three that requires + // we cause a side effect to detect whether it's present, + // so we need to redo that side effect now.) + uc.WriteTo(pcpPacket(myIP, tempPort, true), port5351) + } } } } From b3c7b631c267b75e17ac32cf1aa37aef4b12fb60 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 7 Dec 2020 09:13:26 -0800 Subject: [PATCH 16/36] tailcfg, control/controlclient: make nil PacketFilter mean unchanged (mapver 6) After mapver 5's incremental netmap updates & user profiles, much of the remaining bandwidth for streamed MapResponses were redundant, unchanged PacketFilters. So make MapRequest.Version 6 mean that nil means unchanged from the previous value. --- control/controlclient/direct.go | 10 ++++++++-- tailcfg/tailcfg.go | 21 ++++++++++++++++++--- version/version.go | 2 +- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index 72ea0b4ba..36f5e45c9 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -45,6 +45,7 @@ import ( "tailscale.com/types/opt" "tailscale.com/types/structs" "tailscale.com/version" + "tailscale.com/wgengine/filter" ) type Persist struct { @@ -541,7 +542,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM } request := tailcfg.MapRequest{ - Version: 5, + Version: 6, KeepAlive: c.keepAlive, NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()), DiscoKey: c.discoPubKey, @@ -636,6 +637,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM var lastDERPMap *tailcfg.DERPMap var lastUserProfile = map[tailcfg.UserID]tailcfg.UserProfile{} + var lastParsedPacketFilter []filter.Match // If allowStream, then the server will use an HTTP long poll to // return incremental results. There is always one response right @@ -713,6 +715,10 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM resp.Peers = filtered } + if pf := resp.PacketFilter; pf != nil { + lastParsedPacketFilter = c.parsePacketFilter(pf) + } + nm := &NetworkMap{ NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()), PrivateKey: persist.PrivateNodeKey, @@ -727,7 +733,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM Domain: resp.Domain, DNS: resp.DNSConfig, Hostinfo: resp.Node.Hostinfo, - PacketFilter: c.parsePacketFilter(resp.PacketFilter), + PacketFilter: lastParsedPacketFilter, DERPMap: lastDERPMap, Debug: resp.Debug, } diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 1036b7517..191ec0615 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -476,6 +476,7 @@ type MapRequest struct { // 3: implicit compression, keep-alives // 4: opt-in keep-alives via KeepAlive field, opt-in compression via Compress // 5: 2020-10-19, implies IncludeIPv6, delta Peers/UserProfiles, supports MagicDNS + // 6: 2020-12-07: means MapResponse.PacketFilter nil means unchanged Version int Compress string // "zstd" or "" (no compression) KeepAlive bool // whether server should send keep-alives back to us @@ -620,11 +621,25 @@ type MapResponse struct { SearchPaths []string `json:",omitempty"` DNSConfig DNSConfig `json:",omitempty"` - // ACLs - Domain string + // Domain is the name of the network that this node is + // in. It's either of the form "example.com" (for user + // foo@example.com, for multi-user networks) or + // "foo@gmail.com" (for siloed users on shared email + // providers). Its exact form should not be depended on; new + // forms are coming later. + Domain string + + // PacketFilter are the firewall rules. + // + // For MapRequest.Version >= 6, a nil value means the most + // previously streamed non-nil MapResponse.PacketFilter within + // the same HTTP response. A non-nil but empty list always means + // no PacketFilter (that is, to block everything). PacketFilter []FilterRule - UserProfiles []UserProfile // as of 1.1.541: may be new or updated user profiles only + + UserProfiles []UserProfile // as of 1.1.541 (mapver 5): may be new or updated user profiles only Roles []Role // deprecated; clients should not rely on Roles + // TODO: Groups []Group // TODO: Capabilities []Capability diff --git a/version/version.go b/version/version.go index 87d6507fd..fbab0e6f4 100644 --- a/version/version.go +++ b/version/version.go @@ -10,7 +10,7 @@ package version // Long is a full version number for this build, of the form // "x.y.z-commithash", or "date.yyyymmdd" if no actual version was // provided. -const Long = "date.20201203" +const Long = "date.20201207" // Short is a short version number for this build, of the form // "x.y.z", or "date.yyyymmdd" if no actual version was provided. From 19c2c6403d597c3ff1757fc84b59354c7f7bff6c Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 7 Dec 2020 14:00:53 -0800 Subject: [PATCH 17/36] Update go.sum --- go.sum | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.sum b/go.sum index 2e2723d18..7a0582990 100644 --- a/go.sum +++ b/go.sum @@ -191,6 +191,8 @@ golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= From 442d1873ec7b8ca211e18041c1be7edb48e70d48 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 7 Dec 2020 14:02:05 -0800 Subject: [PATCH 18/36] go.mod: bump tailscale/wireguard-go --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 872604897..c1af846e9 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 github.com/peterbourgon/ff/v2 v2.0.0 github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be - github.com/tailscale/wireguard-go v0.0.0-20201021041318-a6168fd06b3f + github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb github.com/tcnksm/go-httpstat v0.2.0 github.com/toqueteos/webbrowser v1.2.0 go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 From 08f94b3b504b8b59d0f1c0bbce654e29c55019de Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 8 Dec 2020 15:22:26 -0800 Subject: [PATCH 19/36] net/netcheck: fix offset of unspecified address in PCP request packet Fixes #810 --- net/netcheck/netcheck.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/net/netcheck/netcheck.go b/net/netcheck/netcheck.go index ff6f9ddb7..26c8d118b 100644 --- a/net/netcheck/netcheck.go +++ b/net/netcheck/netcheck.go @@ -751,6 +751,7 @@ var uPnPPacket = []byte("M-SEARCH * HTTP/1.1\r\n" + var v4unspec, _ = netaddr.ParseIP("0.0.0.0") +// pcpPacket generates a PCP packet with a MAP opcode. func pcpPacket(myIP netaddr.IP, mapToLocalPort int, delete bool) []byte { const udpProtoNumber = 17 lifetimeSeconds := uint32(1) @@ -758,17 +759,24 @@ func pcpPacket(myIP netaddr.IP, mapToLocalPort int, delete bool) []byte { lifetimeSeconds = 0 } const opMap = 1 + + // 24 byte header + 36 byte map opcode pkt := make([]byte, (32+32+128)/8+(96+8+24+16+16+128)/8) + + // The header (https://tools.ietf.org/html/rfc6887#section-7.1) pkt[0] = 2 // version pkt[1] = opMap binary.BigEndian.PutUint32(pkt[4:8], lifetimeSeconds) myIP16 := myIP.As16() copy(pkt[8:], myIP16[:]) - rand.Read(pkt[24 : 24+12]) - pkt[36] = udpProtoNumber - binary.BigEndian.PutUint16(pkt[40:], uint16(mapToLocalPort)) + + // The map opcode body (https://tools.ietf.org/html/rfc6887#section-11.1) + mapOp := pkt[24:] + rand.Read(mapOp[:12]) // 96 bit mappping nonce + mapOp[12] = udpProtoNumber + binary.BigEndian.PutUint16(mapOp[16:], uint16(mapToLocalPort)) v4unspec16 := v4unspec.As16() - copy(pkt[40:], v4unspec16[:]) + copy(mapOp[20:], v4unspec16[:]) return pkt } From 9cb6ee377744102bff5afc19171fbbe7a7eaea38 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 8 Dec 2020 15:23:56 -0800 Subject: [PATCH 20/36] go.mod, go.sum: update --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index c1af846e9..0071fb005 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( golang.org/x/net v0.0.0-20201110031124-69a78807bb2b golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 - golang.org/x/sys v0.0.0-20201112073958-5cba982894dd + golang.org/x/sys v0.0.0-20201202213521-69691e467435 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8 diff --git a/go.sum b/go.sum index 7a0582990..aaa8c97c9 100644 --- a/go.sum +++ b/go.sum @@ -114,6 +114,8 @@ github.com/tailscale/wireguard-go v0.0.0-20201008164108-2c83f43a9859 h1:Z7bXXCYR github.com/tailscale/wireguard-go v0.0.0-20201008164108-2c83f43a9859/go.mod h1:WXq+IkSOJGIgfF1XW+4z4oW+LX/TXzU9DcKlT5EZLi4= github.com/tailscale/wireguard-go v0.0.0-20201021041318-a6168fd06b3f h1:KMx58dbn2YCutzOvjNHgmvbwQH7nGE8H+J42Nenjl/M= github.com/tailscale/wireguard-go v0.0.0-20201021041318-a6168fd06b3f/go.mod h1:WXq+IkSOJGIgfF1XW+4z4oW+LX/TXzU9DcKlT5EZLi4= +github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb h1:lPrU+j3X85IpVF8saRAAnhER6/RmtpV9mSZFx/rQXJc= +github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb/go.mod h1:RMjerRBNxOIkYHMFnxMWLFYngXD6zexR/v5Dn4a5Zcc= github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= From 57cd7738c29e1f1bc7ceb0b73b06884902a79696 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Tue, 8 Dec 2020 16:45:34 -0800 Subject: [PATCH 21/36] tsweb: add an endpoint to manually trigger a GC. Signed-off-by: David Anderson --- tsweb/tsweb.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tsweb/tsweb.go b/tsweb/tsweb.go index 134f034cf..411e615a4 100644 --- a/tsweb/tsweb.go +++ b/tsweb/tsweb.go @@ -44,6 +44,16 @@ func registerCommonDebug(mux *http.ServeMux) { mux.Handle("/debug/pprof/", Protected(http.DefaultServeMux)) // to net/http/pprof mux.Handle("/debug/vars", Protected(http.DefaultServeMux)) // to expvar mux.Handle("/debug/varz", Protected(http.HandlerFunc(varzHandler))) + mux.Handle("/debug/gc", Protected(http.HandlerFunc(gcHandler))) +} + +func gcHandler(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("running GC...\n")) + if f, ok := w.(http.Flusher); ok { + f.Flush() + } + runtime.GC() + w.Write([]byte("Done.\n")) } func DefaultCertDir(leafDir string) string { From bce865b61b46d41ac3c4d1018a520103965989c7 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 9 Dec 2020 15:28:31 -0800 Subject: [PATCH 22/36] logpolicy: migrate from x/crypto/ssh/terminal to x/term --- cmd/tailscaled/depaware.txt | 2 +- go.mod | 1 + go.sum | 3 +++ logpolicy/logpolicy.go | 4 ++-- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 15439e0c6..2c67f59aa 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -110,7 +110,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de 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/crypto/ssh/terminal from tailscale.com/logpolicy golang.org/x/net/bpf from github.com/mdlayher/netlink+ golang.org/x/net/context/ctxhttp from golang.org/x/oauth2/internal golang.org/x/net/dns/dnsmessage from net+ @@ -130,6 +129,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de LD golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ W golang.org/x/sys/windows from github.com/apenwarr/fixconsole+ W golang.org/x/sys/windows/registry from github.com/tailscale/wireguard-go/tun/wintun+ + golang.org/x/term from tailscale.com/logpolicy 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+ diff --git a/go.mod b/go.mod index 0071fb005..4b8157e40 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,7 @@ require ( golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 golang.org/x/sys v0.0.0-20201202213521-69691e467435 + golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8 diff --git a/go.sum b/go.sum index aaa8c97c9..d0ffb3bba 100644 --- a/go.sum +++ b/go.sum @@ -193,8 +193,11 @@ golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b h1:a0ErnNnPKmhDyIXQvdZr+Lq8dc8xpMeqkF8y5PgQU4Q= +golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= diff --git a/logpolicy/logpolicy.go b/logpolicy/logpolicy.go index 4174a6b4b..fba389e15 100644 --- a/logpolicy/logpolicy.go +++ b/logpolicy/logpolicy.go @@ -25,7 +25,7 @@ import ( "strings" "time" - "golang.org/x/crypto/ssh/terminal" + "golang.org/x/term" "tailscale.com/atomicfile" "tailscale.com/logtail" "tailscale.com/logtail/filch" @@ -311,7 +311,7 @@ func tryFixLogStateLocation(dir, cmdname string) { // given collection name. func New(collection string) *Policy { var lflags int - if terminal.IsTerminal(2) || runtime.GOOS == "windows" { + if term.IsTerminal(2) || runtime.GOOS == "windows" { lflags = 0 } else { lflags = log.LstdFlags From 943860fde7f059097b3491c2aa081d868ae3d5c5 Mon Sep 17 00:00:00 2001 From: Adrian Dewhurst Date: Wed, 9 Dec 2020 21:03:56 -0500 Subject: [PATCH 23/36] version: relax git detection logic (again) This is a repeat of commit 3aa68cd3978b880b451cd41ac4f4ee4ff5c4cb2f which was lost in a rework of version.sh. git worktrees have a .git file rather than a .git directory, so building in a worktree caused version.sh to generate an error. Signed-off-by: Adrian Dewhurst --- version/version.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version/version.sh b/version/version.sh index 1fe1f9a49..121ed1726 100755 --- a/version/version.sh +++ b/version/version.sh @@ -31,7 +31,7 @@ case $# in if [ -z "$extra_hash_or_dir" ]; then # Nothing, empty extra hash is fine. extra_hash="" - elif [ -d "$extra_hash_or_dir/.git" ]; then + elif [ -e "$extra_hash_or_dir/.git" ]; then extra_hash=$(git_hash_dirty "$extra_hash_or_dir" HEAD) elif ! expr "$extra_hash_or_dir" : "^[0-9a-f]*$"; then echo "Invalid extra hash '$extra_hash_or_dir', must be a git commit or path to a git repo" >&2 From 274d32d0aa5bc7c8bc6a908590dcbc8741fd8872 Mon Sep 17 00:00:00 2001 From: Aleksandar Pesic Date: Fri, 4 Dec 2020 14:56:34 +0100 Subject: [PATCH 24/36] Prepare for the new wireguard-go API. Signed-off-by: Aleksandar Pesic --- wgengine/router/ifconfig_windows.go | 35 +++++++++++++---------------- wgengine/router/router_windows.go | 9 ++++++-- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/wgengine/router/ifconfig_windows.go b/wgengine/router/ifconfig_windows.go index ee4a62b13..2bbd29eb9 100644 --- a/wgengine/router/ifconfig_windows.go +++ b/wgengine/router/ifconfig_windows.go @@ -39,12 +39,8 @@ import ( // address a few rare corner cases, but is unlikely to significantly // help with MTU issues compared to a static 1280B implementation. func monitorDefaultRoutes(tun *tun.NativeTun) (*winipcfg.RouteChangeCallback, error) { - guid := tun.GUID() - ourLuid, err := winipcfg.LUIDFromGUID(&guid) + ourLuid := winipcfg.LUID(tun.LUID()) lastMtu := uint32(0) - if err != nil { - return nil, fmt.Errorf("error mapping GUID %v to LUID: %w", guid, err) - } doIt := func() error { mtu, err := getDefaultRouteMTU() if err != nil { @@ -91,7 +87,7 @@ func monitorDefaultRoutes(tun *tun.NativeTun) (*winipcfg.RouteChangeCallback, er } return nil } - err = doIt() + err := doIt() if err != nil { return nil, err } @@ -159,7 +155,7 @@ func getDefaultRouteMTU() (uint32, error) { // setPrivateNetwork marks the provided network adapter's category to private. // It returns (false, nil) if the adapter was not found. -func setPrivateNetwork(ifcGUID *windows.GUID) (bool, error) { +func setPrivateNetwork(ifcLUID winipcfg.LUID) (bool, error) { // NLM_NETWORK_CATEGORY values. const ( categoryPublic = 0 @@ -167,6 +163,11 @@ func setPrivateNetwork(ifcGUID *windows.GUID) (bool, error) { categoryDomain = 2 ) + ifcGUID, err := ifcLUID.GUID() + if err != nil { + return false, fmt.Errorf("ifcLUID.GUID: %v", err) + } + // Lock OS thread when using OLE, which seems to be a requirement // from the Microsoft docs. go-ole doesn't seem to handle it automatically. // https://github.com/tailscale/tailscale/issues/921#issuecomment-727526807 @@ -222,12 +223,8 @@ func setPrivateNetwork(ifcGUID *windows.GUID) (bool, error) { return false, nil } -// interfaceFromGUID returns IPAdapterAddresses with specified GUID. -func interfaceFromGUID(guid *windows.GUID, flags winipcfg.GAAFlags) (*winipcfg.IPAdapterAddresses, error) { - luid, err := winipcfg.LUIDFromGUID(guid) - if err != nil { - return nil, err - } +// interfaceFromLUID returns IPAdapterAddresses with specified GUID. +func interfaceFromLUID(luid winipcfg.LUID, flags winipcfg.GAAFlags) (*winipcfg.IPAdapterAddresses, error) { addresses, err := winipcfg.GetAdaptersAddresses(windows.AF_UNSPEC, flags) if err != nil { return nil, err @@ -237,13 +234,13 @@ func interfaceFromGUID(guid *windows.GUID, flags winipcfg.GAAFlags) (*winipcfg.I return addr, nil } } - return nil, fmt.Errorf("interfaceFromGUID: interface with LUID %v (from GUID %v) not found", luid, guid) + return nil, fmt.Errorf("interfaceFromLUID: interface with LUID %v not found", luid) } func configureInterface(cfg *Config, tun *tun.NativeTun) error { const mtu = 0 - guid := tun.GUID() - iface, err := interfaceFromGUID(&guid, + luid := winipcfg.LUID(tun.LUID()) + iface, err := interfaceFromLUID(luid, // Issue 474: on early boot, when the network is still // coming up, if the Tailscale service comes up first, // the Tailscale adapter it finds might not have the @@ -260,7 +257,7 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) error { // does. const tries = 20 for i := 0; i < tries; i++ { - found, err := setPrivateNetwork(&guid) + found, err := setPrivateNetwork(luid) if err != nil { log.Printf("setPrivateNetwork(try=%d): %v", i, err) } else { @@ -271,7 +268,7 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) error { } time.Sleep(1 * time.Second) } - log.Printf("setPrivateNetwork: adapter %v not found after %d tries, giving up", guid, tries) + log.Printf("setPrivateNetwork: adapter LUID %v not found after %d tries, giving up", luid, tries) }() var firstGateway4 *net.IP @@ -353,7 +350,7 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) error { } // Re-read interface after syncAddresses. - iface, err = interfaceFromGUID(&guid, + iface, err = interfaceFromLUID(luid, // Issue 474: on early boot, when the network is still // coming up, if the Tailscale service comes up first, // the Tailscale adapter it finds might not have the diff --git a/wgengine/router/router_windows.go b/wgengine/router/router_windows.go index 50e65dd32..0194ef0a1 100644 --- a/wgengine/router/router_windows.go +++ b/wgengine/router/router_windows.go @@ -37,10 +37,15 @@ func newUserspaceRouter(logf logger.Logf, wgdev *device.Device, tundev tun.Devic } nativeTun := tundev.(*tun.NativeTun) - guid := nativeTun.GUID().String() + luid := winipcfg.LUID(nativeTun.LUID()) + guid, err := luid.GUID() + if err != nil { + return nil, err + } + mconfig := dns.ManagerConfig{ Logf: logf, - InterfaceName: guid, + InterfaceName: guid.String(), } return &winRouter{ From 338fd4465732f2297208301cc17d4c7384f77a29 Mon Sep 17 00:00:00 2001 From: Aleksandar Pesic Date: Fri, 11 Dec 2020 00:37:24 +0100 Subject: [PATCH 25/36] Replace registry-access code, update wireguard-go and x/sys/windows. Signed-off-by: Aleksandar Pesic --- go.mod | 6 +- go.sum | 9 +++ wgengine/router/dns/manager_windows.go | 77 +++++++++++++++++++++++--- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 4b8157e40..72302adae 100644 --- a/go.mod +++ b/go.mod @@ -23,15 +23,15 @@ require ( github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 github.com/peterbourgon/ff/v2 v2.0.0 github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be - github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb + github.com/tailscale/wireguard-go v0.0.0-20201210001956-32a957fb6709 github.com/tcnksm/go-httpstat v0.2.0 github.com/toqueteos/webbrowser v1.2.0 go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 - golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 + golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 - golang.org/x/sys v0.0.0-20201202213521-69691e467435 + golang.org/x/sys v0.0.0-20201210223839-7e3030f88018 golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d diff --git a/go.sum b/go.sum index d0ffb3bba..f3260a82d 100644 --- a/go.sum +++ b/go.sum @@ -116,6 +116,9 @@ github.com/tailscale/wireguard-go v0.0.0-20201021041318-a6168fd06b3f h1:KMx58dbn github.com/tailscale/wireguard-go v0.0.0-20201021041318-a6168fd06b3f/go.mod h1:WXq+IkSOJGIgfF1XW+4z4oW+LX/TXzU9DcKlT5EZLi4= github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb h1:lPrU+j3X85IpVF8saRAAnhER6/RmtpV9mSZFx/rQXJc= github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb/go.mod h1:RMjerRBNxOIkYHMFnxMWLFYngXD6zexR/v5Dn4a5Zcc= +github.com/tailscale/wireguard-go v0.0.0-20201210001956-32a957fb6709 h1:cxiYxd+Kb+LuXBpv6rp2CpWGhhcVB5b07B6h+kA7LP4= +github.com/tailscale/wireguard-go v0.0.0-20201210001956-32a957fb6709/go.mod h1:9PbAnF5CAklkURoO0uQhm+YUjDmm9T9oCyTGlCHuTPQ= +github.com/tailscale/wireguard-go v0.0.20201118 h1:gtjCCz7el67M8M3BmOLlsaTBnWqVJ3uH7Z8+uO1fjeI= github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= @@ -141,6 +144,8 @@ golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc= +golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= @@ -182,6 +187,7 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -196,6 +202,9 @@ golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201210223839-7e3030f88018 h1:XKi8B/gRBuTZN1vU9gFsLMm6zVz5FSCDzm8JYACnjy8= +golang.org/x/sys v0.0.0-20201210223839-7e3030f88018/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b h1:a0ErnNnPKmhDyIXQvdZr+Lq8dc8xpMeqkF8y5PgQU4Q= golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/wgengine/router/dns/manager_windows.go b/wgengine/router/dns/manager_windows.go index 685a471d4..ed5fdc620 100644 --- a/wgengine/router/dns/manager_windows.go +++ b/wgengine/router/dns/manager_windows.go @@ -7,12 +7,13 @@ package dns import ( "fmt" "os/exec" + "runtime" "strings" "syscall" "time" "github.com/tailscale/wireguard-go/tun" - wgregistry "github.com/tailscale/wireguard-go/tun/wintun/registry" + "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" "tailscale.com/types/logger" ) @@ -35,14 +36,76 @@ func newManager(mconfig ManagerConfig) managerImpl { } } -// keyOpenTimeout is how long we wait for a registry key to -// appear. For some reason, registry keys tied to ephemeral interfaces -// can take a long while to appear after interface creation, and we -// can end up racing with that. -const keyOpenTimeout = time.Minute +const ( + // keyOpenTimeout is how long we wait for a registry key to + // appear. For some reason, registry keys tied to ephemeral interfaces + // can take a long while to appear after interface creation, and we + // can end up racing with that. + keyOpenTimeout = time.Minute + + // REG_NOTIFY_CHANGE_NAME notifies the caller if a subkey is added or deleted. + REG_NOTIFY_CHANGE_NAME uint32 = 0x00000001 +) + +func openKeyWait(k registry.Key, path string, access uint32, timeout time.Duration) (registry.Key, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + deadline := time.Now().Add(timeout) + pathSpl := strings.Split(path, "\\") + for i := 0; ; i++ { + keyName := pathSpl[i] + isLast := i+1 == len(pathSpl) + + event, err := windows.CreateEvent(nil, 0, 0, nil) + if err != nil { + return 0, fmt.Errorf("windows.CreateEvent: %v", err) + } + defer windows.CloseHandle(event) + + var key registry.Key + for { + err = windows.RegNotifyChangeKeyValue(windows.Handle(k), false, REG_NOTIFY_CHANGE_NAME, event, true) + if err != nil { + return 0, fmt.Errorf("windows.RegNotifyChangeKeyValue: %v", err) + } + + var accessFlags uint32 + if isLast { + accessFlags = access + } else { + accessFlags = registry.NOTIFY + } + key, err = registry.OpenKey(k, keyName, accessFlags) + if err == windows.ERROR_FILE_NOT_FOUND || err == windows.ERROR_PATH_NOT_FOUND { + timeout := time.Until(deadline) / time.Millisecond + if timeout < 0 { + timeout = 0 + } + s, err := windows.WaitForSingleObject(event, uint32(timeout)) + if err != nil { + return 0, fmt.Errorf("windows.WaitForSingleObject: %v", err) + } + if s == uint32(windows.WAIT_TIMEOUT) { // windows.WAIT_TIMEOUT status const is misclassified as error in golang.org/x/sys/windows + return 0, fmt.Errorf("timeout waiting for registry key") + } + } else if err != nil { + return 0, fmt.Errorf("registry.OpenKey(%v): %v", path, err) + } else { + if isLast { + return key, nil + } + defer key.Close() + break + } + } + + k = key + } +} func setRegistryString(path, name, value string) error { - key, err := wgregistry.OpenKeyWait(registry.LOCAL_MACHINE, path, registry.SET_VALUE, keyOpenTimeout) + key, err := openKeyWait(registry.LOCAL_MACHINE, path, registry.SET_VALUE, keyOpenTimeout) if err != nil { return fmt.Errorf("opening %s: %w", path, err) } From 4749a96a5bb8a2fd7f0c77f134736bb2ac3b0a85 Mon Sep 17 00:00:00 2001 From: Aleksandar Pesic Date: Fri, 11 Dec 2020 00:45:31 +0100 Subject: [PATCH 26/36] Update depaware.txt files. Signed-off-by: Aleksandar Pesic --- cmd/tailscale/depaware.txt | 11 +++-------- cmd/tailscaled/depaware.txt | 11 +++-------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 5c5071ca2..8ca3b2616 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -27,11 +27,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep 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 - W 💣 github.com/tailscale/wireguard-go/tun/wintun/iphlpapi from github.com/tailscale/wireguard-go/tun/wintun - W 💣 github.com/tailscale/wireguard-go/tun/wintun/namespaceapi from github.com/tailscale/wireguard-go/tun/wintun - W 💣 github.com/tailscale/wireguard-go/tun/wintun/nci from github.com/tailscale/wireguard-go/tun/wintun - W 💣 github.com/tailscale/wireguard-go/tun/wintun/registry from github.com/tailscale/wireguard-go/tun/wintun+ - W 💣 github.com/tailscale/wireguard-go/tun/wintun/setupapi from github.com/tailscale/wireguard-go/tun/wintun github.com/tailscale/wireguard-go/wgcfg from github.com/tailscale/wireguard-go/conn+ github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck github.com/toqueteos/webbrowser from tailscale.com/cmd/tailscale/cli @@ -89,7 +84,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep tailscale.com/wgengine/tstun from tailscale.com/wgengine W 💣 tailscale.com/wgengine/winnet from tailscale.com/wgengine/router 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+ @@ -118,11 +113,11 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+ LD golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ W golang.org/x/sys/windows from github.com/apenwarr/fixconsole+ - W golang.org/x/sys/windows/registry from github.com/tailscale/wireguard-go/tun/wintun+ + 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+ - golang.org/x/text/unicode/norm from github.com/tailscale/wireguard-go/tun/wintun+ + golang.org/x/text/unicode/norm from golang.org/x/net/idna golang.org/x/time/rate from tailscale.com/types/logger+ bufio from compress/flate+ bytes from bufio+ diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 2c67f59aa..fa7ab7899 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -30,11 +30,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de 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 - W 💣 github.com/tailscale/wireguard-go/tun/wintun/iphlpapi from github.com/tailscale/wireguard-go/tun/wintun - W 💣 github.com/tailscale/wireguard-go/tun/wintun/namespaceapi from github.com/tailscale/wireguard-go/tun/wintun - W 💣 github.com/tailscale/wireguard-go/tun/wintun/nci from github.com/tailscale/wireguard-go/tun/wintun - W 💣 github.com/tailscale/wireguard-go/tun/wintun/registry from github.com/tailscale/wireguard-go/tun/wintun+ - W 💣 github.com/tailscale/wireguard-go/tun/wintun/setupapi from github.com/tailscale/wireguard-go/tun/wintun github.com/tailscale/wireguard-go/wgcfg from github.com/tailscale/wireguard-go/conn+ github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck 💣 go4.org/mem from tailscale.com/control/controlclient+ @@ -99,7 +94,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de tailscale.com/wgengine/tstun from tailscale.com/wgengine W 💣 tailscale.com/wgengine/winnet from tailscale.com/wgengine/router 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+ @@ -128,12 +123,12 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+ LD golang.org/x/sys/unix from github.com/jsimonetti/rtnetlink/internal/unix+ W golang.org/x/sys/windows from github.com/apenwarr/fixconsole+ - W golang.org/x/sys/windows/registry from github.com/tailscale/wireguard-go/tun/wintun+ + W golang.org/x/sys/windows/registry from golang.zx2c4.com/wireguard/windows/tunnel/winipcfg+ golang.org/x/term from tailscale.com/logpolicy 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+ - golang.org/x/text/unicode/norm from github.com/tailscale/wireguard-go/tun/wintun+ + golang.org/x/text/unicode/norm from golang.org/x/net/idna golang.org/x/time/rate from tailscale.com/types/logger+ bufio from compress/flate+ bytes from bufio+ From d854fe95d2caf5d3d439b129a14cdccbc7943893 Mon Sep 17 00:00:00 2001 From: Aleksandar Pesic Date: Fri, 11 Dec 2020 00:55:37 +0100 Subject: [PATCH 27/36] Trivial change in function description. Signed-off-by: Aleksandar Pesic --- wgengine/router/ifconfig_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgengine/router/ifconfig_windows.go b/wgengine/router/ifconfig_windows.go index 2bbd29eb9..b4a8d406e 100644 --- a/wgengine/router/ifconfig_windows.go +++ b/wgengine/router/ifconfig_windows.go @@ -223,7 +223,7 @@ func setPrivateNetwork(ifcLUID winipcfg.LUID) (bool, error) { return false, nil } -// interfaceFromLUID returns IPAdapterAddresses with specified GUID. +// interfaceFromLUID returns IPAdapterAddresses with specified LUID. func interfaceFromLUID(luid winipcfg.LUID, flags winipcfg.GAAFlags) (*winipcfg.IPAdapterAddresses, error) { addresses, err := winipcfg.GetAdaptersAddresses(windows.AF_UNSPEC, flags) if err != nil { From 0dc295a640f7e35691bd71e7a36810c0f2f4027a Mon Sep 17 00:00:00 2001 From: Aleksandar Pesic Date: Fri, 11 Dec 2020 01:08:41 +0100 Subject: [PATCH 28/36] Isolate WireGuard code into a separate file with appropriate copyright info in header. Signed-off-by: Aleksandar Pesic --- wgengine/router/dns/manager_windows.go | 74 ++--------------------- wgengine/router/dns/registry_windows.go | 79 +++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 69 deletions(-) create mode 100644 wgengine/router/dns/registry_windows.go diff --git a/wgengine/router/dns/manager_windows.go b/wgengine/router/dns/manager_windows.go index ed5fdc620..718f5ecbe 100644 --- a/wgengine/router/dns/manager_windows.go +++ b/wgengine/router/dns/manager_windows.go @@ -7,13 +7,11 @@ package dns import ( "fmt" "os/exec" - "runtime" "strings" "syscall" "time" "github.com/tailscale/wireguard-go/tun" - "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" "tailscale.com/types/logger" ) @@ -36,73 +34,11 @@ func newManager(mconfig ManagerConfig) managerImpl { } } -const ( - // keyOpenTimeout is how long we wait for a registry key to - // appear. For some reason, registry keys tied to ephemeral interfaces - // can take a long while to appear after interface creation, and we - // can end up racing with that. - keyOpenTimeout = time.Minute - - // REG_NOTIFY_CHANGE_NAME notifies the caller if a subkey is added or deleted. - REG_NOTIFY_CHANGE_NAME uint32 = 0x00000001 -) - -func openKeyWait(k registry.Key, path string, access uint32, timeout time.Duration) (registry.Key, error) { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - - deadline := time.Now().Add(timeout) - pathSpl := strings.Split(path, "\\") - for i := 0; ; i++ { - keyName := pathSpl[i] - isLast := i+1 == len(pathSpl) - - event, err := windows.CreateEvent(nil, 0, 0, nil) - if err != nil { - return 0, fmt.Errorf("windows.CreateEvent: %v", err) - } - defer windows.CloseHandle(event) - - var key registry.Key - for { - err = windows.RegNotifyChangeKeyValue(windows.Handle(k), false, REG_NOTIFY_CHANGE_NAME, event, true) - if err != nil { - return 0, fmt.Errorf("windows.RegNotifyChangeKeyValue: %v", err) - } - - var accessFlags uint32 - if isLast { - accessFlags = access - } else { - accessFlags = registry.NOTIFY - } - key, err = registry.OpenKey(k, keyName, accessFlags) - if err == windows.ERROR_FILE_NOT_FOUND || err == windows.ERROR_PATH_NOT_FOUND { - timeout := time.Until(deadline) / time.Millisecond - if timeout < 0 { - timeout = 0 - } - s, err := windows.WaitForSingleObject(event, uint32(timeout)) - if err != nil { - return 0, fmt.Errorf("windows.WaitForSingleObject: %v", err) - } - if s == uint32(windows.WAIT_TIMEOUT) { // windows.WAIT_TIMEOUT status const is misclassified as error in golang.org/x/sys/windows - return 0, fmt.Errorf("timeout waiting for registry key") - } - } else if err != nil { - return 0, fmt.Errorf("registry.OpenKey(%v): %v", path, err) - } else { - if isLast { - return key, nil - } - defer key.Close() - break - } - } - - k = key - } -} +// keyOpenTimeout is how long we wait for a registry key to +// appear. For some reason, registry keys tied to ephemeral interfaces +// can take a long while to appear after interface creation, and we +// can end up racing with that. +const keyOpenTimeout = time.Minute func setRegistryString(path, name, value string) error { key, err := openKeyWait(registry.LOCAL_MACHINE, path, registry.SET_VALUE, keyOpenTimeout) diff --git a/wgengine/router/dns/registry_windows.go b/wgengine/router/dns/registry_windows.go new file mode 100644 index 000000000..ec365e239 --- /dev/null +++ b/wgengine/router/dns/registry_windows.go @@ -0,0 +1,79 @@ +// 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. +// +// The code in this file originates from https://git.zx2c4.com/wireguard-go: +// Copyright (C) 2017-2020 WireGuard LLC. All Rights Reserved. +// Copying license: https://git.zx2c4.com/wireguard-go/tree/COPYING + +package dns + +import ( + "fmt" + "runtime" + "strings" + "time" + + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/registry" +) + +// REG_NOTIFY_CHANGE_NAME notifies the caller if a subkey is added or deleted. +const REG_NOTIFY_CHANGE_NAME uint32 = 0x00000001 + +func openKeyWait(k registry.Key, path string, access uint32, timeout time.Duration) (registry.Key, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + deadline := time.Now().Add(timeout) + pathSpl := strings.Split(path, "\\") + for i := 0; ; i++ { + keyName := pathSpl[i] + isLast := i+1 == len(pathSpl) + + event, err := windows.CreateEvent(nil, 0, 0, nil) + if err != nil { + return 0, fmt.Errorf("windows.CreateEvent: %v", err) + } + defer windows.CloseHandle(event) + + var key registry.Key + for { + err = windows.RegNotifyChangeKeyValue(windows.Handle(k), false, REG_NOTIFY_CHANGE_NAME, event, true) + if err != nil { + return 0, fmt.Errorf("windows.RegNotifyChangeKeyValue: %v", err) + } + + var accessFlags uint32 + if isLast { + accessFlags = access + } else { + accessFlags = registry.NOTIFY + } + key, err = registry.OpenKey(k, keyName, accessFlags) + if err == windows.ERROR_FILE_NOT_FOUND || err == windows.ERROR_PATH_NOT_FOUND { + timeout := time.Until(deadline) / time.Millisecond + if timeout < 0 { + timeout = 0 + } + s, err := windows.WaitForSingleObject(event, uint32(timeout)) + if err != nil { + return 0, fmt.Errorf("windows.WaitForSingleObject: %v", err) + } + if s == uint32(windows.WAIT_TIMEOUT) { // windows.WAIT_TIMEOUT status const is misclassified as error in golang.org/x/sys/windows + return 0, fmt.Errorf("timeout waiting for registry key") + } + } else if err != nil { + return 0, fmt.Errorf("registry.OpenKey(%v): %v", path, err) + } else { + if isLast { + return key, nil + } + defer key.Close() + break + } + } + + k = key + } +} From 6db9c4a17333cf88fbef5de281f20f83b85e4bdf Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 10 Dec 2020 17:23:01 -0800 Subject: [PATCH 29/36] wgenginer/router/dns: use constant from golang.org/x/sys/windows Made available in https://golang.org/cl/277153 --- go.mod | 2 +- go.sum | 2 ++ wgengine/router/dns/registry_windows.go | 5 +---- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 72302adae..2b4634f03 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( golang.org/x/net v0.0.0-20201110031124-69a78807bb2b golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 - golang.org/x/sys v0.0.0-20201210223839-7e3030f88018 + golang.org/x/sys v0.0.0-20201211002650-1f0c578a6b29 golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b golang.org/x/time v0.0.0-20191024005414-555d28b269f0 golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d diff --git a/go.sum b/go.sum index f3260a82d..424159b6e 100644 --- a/go.sum +++ b/go.sum @@ -204,6 +204,8 @@ golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201210223839-7e3030f88018 h1:XKi8B/gRBuTZN1vU9gFsLMm6zVz5FSCDzm8JYACnjy8= golang.org/x/sys v0.0.0-20201210223839-7e3030f88018/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201211002650-1f0c578a6b29 h1:hAYi5mzhvBeCfkgaIHGZ8R+Q04WjSW5ZvQO3BZ94dHY= +golang.org/x/sys v0.0.0-20201211002650-1f0c578a6b29/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b h1:a0ErnNnPKmhDyIXQvdZr+Lq8dc8xpMeqkF8y5PgQU4Q= golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/wgengine/router/dns/registry_windows.go b/wgengine/router/dns/registry_windows.go index ec365e239..f8e1f514a 100644 --- a/wgengine/router/dns/registry_windows.go +++ b/wgengine/router/dns/registry_windows.go @@ -18,9 +18,6 @@ import ( "golang.org/x/sys/windows/registry" ) -// REG_NOTIFY_CHANGE_NAME notifies the caller if a subkey is added or deleted. -const REG_NOTIFY_CHANGE_NAME uint32 = 0x00000001 - func openKeyWait(k registry.Key, path string, access uint32, timeout time.Duration) (registry.Key, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() @@ -39,7 +36,7 @@ func openKeyWait(k registry.Key, path string, access uint32, timeout time.Durati var key registry.Key for { - err = windows.RegNotifyChangeKeyValue(windows.Handle(k), false, REG_NOTIFY_CHANGE_NAME, event, true) + err = windows.RegNotifyChangeKeyValue(windows.Handle(k), false, windows.REG_NOTIFY_CHANGE_NAME, event, true) if err != nil { return 0, fmt.Errorf("windows.RegNotifyChangeKeyValue: %v", err) } From 8a57f920ae235b6e923b73e2bf359caa1435eea1 Mon Sep 17 00:00:00 2001 From: Smitty Date: Sat, 12 Dec 2020 17:58:11 -0500 Subject: [PATCH 30/36] Remove unused .gitignore lines These ignore built files that don't exist anymore, and just serve to clutter up the .gitignore file. (I was initially confused when I saw those lines, since I (correctly) thought that the only Tailscale binaries were tailscale and tailscaled): - taillogin was removed in d052586 - relaynode was removed in a56e853 Signed-off-by: Smitty --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5d2bdc181..c443556f5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,6 @@ *.so *.dylib -cmd/relaynode/relaynode -cmd/taillogin/taillogin cmd/tailscale/tailscale cmd/tailscaled/tailscaled From b895bf853ae7c11a71dacf7298c853d8995792a8 Mon Sep 17 00:00:00 2001 From: Smitty Date: Sun, 13 Dec 2020 19:18:52 -0500 Subject: [PATCH 31/36] Require at least Go 1.15 This was actually required before this commit, this just updates go.mod with that fact. Signed-off-by: Smitty --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2b4634f03..6d9f4f4ff 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module tailscale.com -go 1.14 +go 1.15 require ( github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 From a0a8b9d76a6b7f57618d0cf1a1f6024d2f2ca76a Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 14 Dec 2020 10:10:01 -0800 Subject: [PATCH 32/36] control/controlclient: don't spin when starting up when node key is expired Fixes #1018 Signed-off-by: Brad Fitzpatrick --- control/controlclient/auto.go | 60 +++++++---------------------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/control/controlclient/auto.go b/control/controlclient/auto.go index 768418d5d..b35df9d5b 100644 --- a/control/controlclient/auto.go +++ b/control/controlclient/auto.go @@ -268,11 +268,13 @@ func (c *Client) authRoutine() { for { c.mu.Lock() - c.logf("authRoutine: %s", c.state) - expiry := c.expiry goal := c.loginGoal ctx := c.authCtx - synced := c.synced + if goal != nil { + c.logf("authRoutine: %s; wantLoggedIn=%v", c.state, goal.wantLoggedIn) + } else { + c.logf("authRoutine: %s; goal=nil", c.state) + } c.mu.Unlock() select { @@ -293,51 +295,13 @@ func (c *Client) authRoutine() { } if goal == nil { - // Wait for something interesting to happen - var exp <-chan time.Time - var expTimer *time.Timer - if expiry != nil && !expiry.IsZero() { - // if expiry is in the future, don't delay - // past that time. - // If it's in the past, then it's already - // being handled by someone, so no need to - // wake ourselves up again. - now := c.timeNow() - if expiry.Before(now) { - delay := expiry.Sub(now) - if delay > 5*time.Second { - delay = time.Second - } - expTimer = time.NewTimer(delay) - exp = expTimer.C - } - } - select { - case <-ctx.Done(): - if expTimer != nil { - expTimer.Stop() - } - c.logf("authRoutine: context done.") - case <-exp: - // Unfortunately the key expiry isn't provided - // by the control server until mapRequest. - // So we have to do some hackery with c.expiry - // in here. - // TODO(apenwarr): add a key expiry field in RegisterResponse. - c.logf("authRoutine: key expiration check.") - if synced && expiry != nil && !expiry.IsZero() && expiry.Before(c.timeNow()) { - c.logf("Key expired; setting loggedIn=false.") - - c.mu.Lock() - c.loginGoal = &LoginGoal{ - wantLoggedIn: c.loggedIn, - } - c.loggedIn = false - c.expiry = nil - c.mu.Unlock() - } - } - } else if !goal.wantLoggedIn { + // Wait for user to Login or Logout. + <-ctx.Done() + c.logf("authRoutine: context done.") + continue + } + + if !goal.wantLoggedIn { err := c.direct.TryLogout(ctx) if err != nil { report(err, "TryLogout") From a6cad71fb262e3b7243df64495c9f12240c5cc85 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 14 Dec 2020 11:43:09 -0800 Subject: [PATCH 33/36] go.mod: upgrade staticcheck to 0.1.0 Also run go.mod and fix some staticcheck warnings. Signed-off-by: Josh Bleecher Snyder --- go.mod | 7 +-- go.sum | 74 ++++++----------------------- ipn/local.go | 1 - net/interfaces/interfaces_darwin.go | 4 +- tempfork/pprof/pprof.go | 3 +- 5 files changed, 22 insertions(+), 67 deletions(-) diff --git a/go.mod b/go.mod index 6d9f4f4ff..10bc0edf2 100644 --- a/go.mod +++ b/go.mod @@ -28,15 +28,16 @@ require ( github.com/toqueteos/webbrowser v1.2.0 go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 + golang.org/x/mod v0.4.0 // indirect golang.org/x/net v0.0.0-20201110031124-69a78807bb2b golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d - golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 + golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 golang.org/x/sys v0.0.0-20201211002650-1f0c578a6b29 golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b golang.org/x/time v0.0.0-20191024005414-555d28b269f0 - golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d + golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8 - honnef.co/go/tools v0.0.1-2020.1.4 + honnef.co/go/tools v0.1.0 inet.af/netaddr v0.0.0-20200810144936-56928fe48a98 rsc.io/goversion v1.2.0 ) diff --git a/go.sum b/go.sum index 424159b6e..14997bac7 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,8 @@ -cloud.google.com/go v0.0.0-20170206221025-ce650573d812/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14= github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= -github.com/aclements/go-moremath v0.0.0-20161014184102-0ff62e0875ff/go.mod h1:idZL3yvz4kzx1dsBOAC+oYv6L92P1oFEhUXUB1A/lwQ= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= @@ -35,27 +31,19 @@ github.com/go-multierror/multierror v1.0.2 h1:AwsKbEXkmf49ajdFJgcFXqSG0aLo0HEyAE github.com/go-multierror/multierror v1.0.2/go.mod h1:U7SZR/D9jHgt2nkSj8XcbCWdmVM2igraCHQ3HC1HiKY= github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= -github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= -github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= -github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= -github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0 h1:BW6OvS3kpT5UEPbCZ+KyX/OB4Ks9/MNMhWjqPPkZxsE= github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= -github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/goreleaser/nfpm v1.1.10 h1:0nwzKUJTcygNxTzVKq2Dh9wpVP1W2biUH6SNKmoxR3w= github.com/goreleaser/nfpm v1.1.10/go.mod h1:oOcoGRVwvKIODz57NUfiRwFWGfn00NXdgnn6MrYtO5k= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= @@ -72,11 +60,8 @@ github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lxn/walk v0.0.0-20191128110447-55ccb3a9f5c1/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= github.com/lxn/walk v0.0.0-20201110160827-18ea5e372cdb/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ= -github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA= github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk= -github.com/mattn/go-sqlite3 v0.0.0-20161215041557-2d44decb4941/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= @@ -108,17 +93,6 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be h1:ZKe3kVGbu/goUVxXcaCPbQ4b0STQ5NsCpG90CG6mw/c= github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be/go.mod h1:jissDaJNHiyV2tFdr3QyNEfsZrax/i2yQiSO+CljThI= -github.com/tailscale/wireguard-go v0.0.0-20200921221757-11a958a67bdd h1:yEWpro9EdxGgkt24NInVnONIJxRLURH5c37Ki5+06EE= -github.com/tailscale/wireguard-go v0.0.0-20200921221757-11a958a67bdd/go.mod h1:WXq+IkSOJGIgfF1XW+4z4oW+LX/TXzU9DcKlT5EZLi4= -github.com/tailscale/wireguard-go v0.0.0-20201008164108-2c83f43a9859 h1:Z7bXXCYRg/8sjSyKTk0V8Yso/gQjNvPb10DBemKuz+A= -github.com/tailscale/wireguard-go v0.0.0-20201008164108-2c83f43a9859/go.mod h1:WXq+IkSOJGIgfF1XW+4z4oW+LX/TXzU9DcKlT5EZLi4= -github.com/tailscale/wireguard-go v0.0.0-20201021041318-a6168fd06b3f h1:KMx58dbn2YCutzOvjNHgmvbwQH7nGE8H+J42Nenjl/M= -github.com/tailscale/wireguard-go v0.0.0-20201021041318-a6168fd06b3f/go.mod h1:WXq+IkSOJGIgfF1XW+4z4oW+LX/TXzU9DcKlT5EZLi4= -github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb h1:lPrU+j3X85IpVF8saRAAnhER6/RmtpV9mSZFx/rQXJc= -github.com/tailscale/wireguard-go v0.0.0-20201204174856-4a319d8d5bfb/go.mod h1:RMjerRBNxOIkYHMFnxMWLFYngXD6zexR/v5Dn4a5Zcc= -github.com/tailscale/wireguard-go v0.0.0-20201210001956-32a957fb6709 h1:cxiYxd+Kb+LuXBpv6rp2CpWGhhcVB5b07B6h+kA7LP4= -github.com/tailscale/wireguard-go v0.0.0-20201210001956-32a957fb6709/go.mod h1:9PbAnF5CAklkURoO0uQhm+YUjDmm9T9oCyTGlCHuTPQ= -github.com/tailscale/wireguard-go v0.0.20201118 h1:gtjCCz7el67M8M3BmOLlsaTBnWqVJ3uH7Z8+uO1fjeI= github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= @@ -127,29 +101,26 @@ github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8= github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go4.org/mem v0.0.0-20200706164138-185c595c3ecc h1:paujszgN6SpsO/UsXC7xax3gQAKz/XQKCYZLQdU34Tw= -go4.org/mem v0.0.0-20200706164138-185c595c3ecc/go.mod h1:NEYvpHWemiG/E5UWfaN5QAIGZeT1sa0Z2UNk6oeMb/k= go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 h1:vSug/WNOi2+4jrKdivxayTN/zd8EA1UrStjpWvvo1jk= go4.org/mem v0.0.0-20201119185036-c04c5a6ff174/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 h1:DZhuSZLsGlFL4CmhA8BcRA0mnthyA/nZ00AqCUo7vHg= -golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9 h1:umElSU9WZirRdgu2yFHY0ayQkEnKiOC1TtM3fWXFnoU= golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc= golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -157,43 +128,35 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/perf v0.0.0-20200918155509-d949658356f9 h1:yVBHF5pcQLKR9B+y+dOJ6y68nqJBDWaZ9DhB1Ohg0qE= -golang.org/x/perf v0.0.0-20200918155509-d949658356f9/go.mod h1:FrqOtQDO3iMDVUtw5nNTDFpR1HUCGh00M3kj2wiSzLQ= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d h1:QQrM/CCYEzTs91GZylDCQjGHudbPTxF/1fvXdVh5lMo= -golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201107080550-4d91cf3a1aaf/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -202,15 +165,12 @@ golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435 h1:25AvDqqB9PrNqj1FLf2/70I4W0L19qqoaFq3gjNwbKk= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201210223839-7e3030f88018 h1:XKi8B/gRBuTZN1vU9gFsLMm6zVz5FSCDzm8JYACnjy8= -golang.org/x/sys v0.0.0-20201210223839-7e3030f88018/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201211002650-1f0c578a6b29 h1:hAYi5mzhvBeCfkgaIHGZ8R+Q04WjSW5ZvQO3BZ94dHY= golang.org/x/sys v0.0.0-20201211002650-1f0c578a6b29/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b h1:a0ErnNnPKmhDyIXQvdZr+Lq8dc8xpMeqkF8y5PgQU4Q= golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= @@ -219,28 +179,22 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqG golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200609164405-eb789aa7ce50/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201001230009-b5b87423c93b/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= -golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d h1:vWQvJ/Z0Lu+9/8oQ/pAYXNzbc7CMnBl+tULGVHOy3oE= -golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.zx2c4.com/wireguard v0.0.20200321-0.20200715051853-507f148e1c42 h1:SrR1hmxGKKarHEEDvaHxatwnqE3uT+7jvMcin6SHOkw= -golang.zx2c4.com/wireguard v0.0.20200321-0.20200715051853-507f148e1c42/go.mod h1:GJvYs5O24/ASlwPiRklVnjMx2xQzrOic0DuU6GvYJL4= golang.zx2c4.com/wireguard v0.0.20200321-0.20201111175144-60b3766b89b9 h1:qowcZ56hhpeoESmWzI4Exhx4Y78TpCyXUJur4/c0CoE= golang.zx2c4.com/wireguard v0.0.20200321-0.20201111175144-60b3766b89b9/go.mod h1:LMeNfjlcPZTrBC1juwgbQyA4Zy2XVcsrdO/fIJxwyuA= -golang.zx2c4.com/wireguard/windows v0.1.2-0.20201004085714-dd60d0447f81 h1:cT2oWlz8v9g7bjFZclT362akxJJfGv9d7ccKu6GQUbA= -golang.zx2c4.com/wireguard/windows v0.1.2-0.20201004085714-dd60d0447f81/go.mod h1:GaK5zcgr5XE98WaRzIDilumDBp5/yP8j2kG/LCDnvAM= golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8 h1:nlXPqGA98n+qcq1pwZ28KjM5EsFQvamKS00A+VUeVjs= golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8/go.mod h1:psva4yDnAHLuh7lUzOK7J7bLYxNFfo0iKWz+mi9gzkA= -google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= @@ -250,8 +204,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.0 h1:AWNL1W1i7f0wNZ8VwOKNJ0sliKvOF/adn0EHenfUh+c= +honnef.co/go/tools v0.1.0/go.mod h1:XtegFAyX/PfluP4921rXU5IkjkqBCDnUq4W8VCIoKvM= inet.af/netaddr v0.0.0-20200810144936-56928fe48a98 h1:bWyWDZP0l6VnQ1TDKf6yNwuiEDV6Q3q1Mv34m+lzT1I= inet.af/netaddr v0.0.0-20200810144936-56928fe48a98/go.mod h1:qqYzz/2whtrbWJvt+DNWQyvekNN4ePQZcg2xc2/Yjww= rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w= diff --git a/ipn/local.go b/ipn/local.go index c17a0a8b6..68de79616 100644 --- a/ipn/local.go +++ b/ipn/local.go @@ -1550,7 +1550,6 @@ func (b *LocalBackend) TestOnlyPublicKeys() (machineKey tailcfg.MachineKey, node // 1.0.x. But eventually we want to stop sending the machine key to // clients. We can't do that until 1.0.x is no longer supported. func temporarilySetMachineKeyInPersist() bool { - //lint:ignore S1008 for comments switch runtime.GOOS { case "darwin", "ios", "android": // iOS, macOS, Android users can't downgrade anyway. diff --git a/net/interfaces/interfaces_darwin.go b/net/interfaces/interfaces_darwin.go index 77d975f1c..c502255a9 100644 --- a/net/interfaces/interfaces_darwin.go +++ b/net/interfaces/interfaces_darwin.go @@ -64,11 +64,11 @@ func likelyHomeRouterIPDarwinExec() (ret netaddr.IP, ok bool) { if err == nil && isPrivateIP(ip) { ret = ip // We've found what we're looking for. - return stopReadingNetstatTable + return errStopReadingNetstatTable } return nil }) return ret, !ret.IsZero() } -var stopReadingNetstatTable = errors.New("found private gateway") +var errStopReadingNetstatTable = errors.New("found private gateway") diff --git a/tempfork/pprof/pprof.go b/tempfork/pprof/pprof.go index 99e0ac125..b6af2319f 100644 --- a/tempfork/pprof/pprof.go +++ b/tempfork/pprof/pprof.go @@ -44,11 +44,12 @@ func AddHandlers(mux *http.ServeMux) { func Cmdline(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Content-Type-Options", "nosniff") w.Header().Set("Content-Type", "text/plain; charset=utf-8") - fmt.Fprintf(w, strings.Join(os.Args, "\x00")) + fmt.Fprint(w, strings.Join(os.Args, "\x00")) } func sleep(w http.ResponseWriter, d time.Duration) { var clientGone <-chan bool + //lint:ignore SA1019 CloseNotifier is deprecated but it functions and this is a temporary fork if cn, ok := w.(http.CloseNotifier); ok { clientGone = cn.CloseNotify() } From ce4d68b4164bd2e35c20a70eae8a5fd5e4fc3ccd Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 14 Dec 2020 11:45:15 -0800 Subject: [PATCH 34/36] go.mod: upgrade depaware version Signed-off-by: Josh Bleecher Snyder --- go.mod | 2 +- go.sum | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 10bc0edf2..ea7caa61a 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/miekg/dns v1.1.30 github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 github.com/peterbourgon/ff/v2 v2.0.0 - github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be + github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027 github.com/tailscale/wireguard-go v0.0.0-20201210001956-32a957fb6709 github.com/tcnksm/go-httpstat v0.2.0 github.com/toqueteos/webbrowser v1.2.0 diff --git a/go.sum b/go.sum index 14997bac7..c62104f23 100644 --- a/go.sum +++ b/go.sum @@ -93,6 +93,10 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be h1:ZKe3kVGbu/goUVxXcaCPbQ4b0STQ5NsCpG90CG6mw/c= github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be/go.mod h1:jissDaJNHiyV2tFdr3QyNEfsZrax/i2yQiSO+CljThI= +github.com/tailscale/depaware v0.0.0-20201210233412-71b54857b5d9 h1:IquU2Mhy4Q+xUYoRLHMiEamd80OShhYXhTNywEbQu3g= +github.com/tailscale/depaware v0.0.0-20201210233412-71b54857b5d9/go.mod h1:jissDaJNHiyV2tFdr3QyNEfsZrax/i2yQiSO+CljThI= +github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027 h1:lK99QQdH3yBWY6aGilF+IRlQIdmhzLrsEmF6JgN+Ryw= +github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= github.com/tcnksm/go-httpstat v0.2.0 h1:rP7T5e5U2HfmOBmZzGgGZjBQ5/GluWUylujl0tJ04I0= github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZwPG41aurT8= github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ= From 34a0292433f5d8fd10db699468d6aa7583cdbd89 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Mon, 14 Dec 2020 11:50:10 -0800 Subject: [PATCH 35/36] depaware.txt: update Upgrading staticcheck upgraded golang.org/x/sync (one downside of mixing our tools in with our regular go.mod), which introduced a new dependency via https://go-review.googlesource.com/c/sync/+/251677 That CL could and probably should be written without runtime/debug, but it's not clear to me that that is better at this moment than simply accepting the additional package as a dependency. Signed-off-by: Josh Bleecher Snyder --- cmd/tailscale/depaware.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 8ca3b2616..7b8705ba8 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -192,6 +192,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep reflect from crypto/x509+ regexp from github.com/coreos/go-iptables/iptables+ regexp/syntax from regexp + runtime/debug from golang.org/x/sync/singleflight runtime/pprof from tailscale.com/log/logheap+ sort from compress/flate+ strconv from compress/flate+ From 9cee0bfa8c0d2123071dc4392fc61b32854e03de Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 14 Dec 2020 23:58:35 -0800 Subject: [PATCH 36/36] wgengine/magicsock: sprinkle more docstrings. Magicsock is too damn big, but this might help me page it back in faster next time. Signed-off-by: David Anderson --- wgengine/magicsock/magicsock.go | 136 +++++++++++++++++++++++--------- 1 file changed, 100 insertions(+), 36 deletions(-) diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 15af3326b..a7bc74dd4 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -110,37 +110,58 @@ func inTest() bool { // A Conn routes UDP packets and actively manages a list of its endpoints. // It implements wireguard/conn.Bind. type Conn struct { - pconnPort uint16 // the preferred port from opts.Port; 0 means auto - pconn4 *RebindingUDPConn - pconn6 *RebindingUDPConn // non-nil if IPv6 available + // This block mirrors the contents and field order of the Options + // struct. Initialized once at construction, then constant. + + logf logger.Logf + port uint16 // the preferred port from opts.Port; 0 means auto epFunc func(endpoints []string) derpActiveFunc func() - logf logger.Logf - sendLogLimit *rate.Limiter - netChecker *netcheck.Client - idleFunc func() time.Duration // nil means unknown + idleFunc func() time.Duration // nil means unknown + packetListener nettype.PacketListener noteRecvActivity func(tailcfg.DiscoKey) // or nil, see Options.NoteRecvActivity simulatedNetwork bool + // ================================================================ + // No locking required to access these fields, either because + // they're static after construction, or are wholly owned by a + // single goroutine. + + connCtx context.Context // closed on Conn.Close + connCtxCancel func() // closes connCtx + + // pconn4 and pconn6 are the underlying UDP sockets used to + // send/receive packets for wireguard and other magicsock + // protocols. + pconn4 *RebindingUDPConn + pconn6 *RebindingUDPConn + + // netChecker is the prober that discovers local network + // conditions, including the closest DERP relay and NAT mappings. + netChecker *netcheck.Client + + // sendLogLimit is a rate limiter for errors logged in the (hot) + // packet sending codepath. It's so that, if magicsock gets into a + // bad state, we don't spam one error per wireguard packet being + // transmitted. + // TODO(danderson): now that we have global rate-limiting, is this still useful? + sendLogLimit *rate.Limiter + // bufferedIPv4From and bufferedIPv4Packet are owned by // ReceiveIPv4, and used when both a DERP and IPv4 packet arrive // at the same time. It stores the IPv4 packet for use in the next call. bufferedIPv4From netaddr.IPPort // if non-zero, then bufferedIPv4Packet is valid bufferedIPv4Packet []byte // the received packet (reused, owned by ReceiveIPv4) - connCtx context.Context // closed on Conn.Close - connCtxCancel func() // closes connCtx - // stunReceiveFunc holds the current STUN packet processing func. // Its Loaded value is always non-nil. stunReceiveFunc atomic.Value // of func(p []byte, fromAddr *net.UDPAddr) + // udpRecvCh and derpRecvCh are used by ReceiveIPv4 to multiplex + // reads from DERP and the pconn4. udpRecvCh chan udpReadResult derpRecvCh chan derpReadResult - // packetListener optionally specifies a test hook to open a PacketConn. - packetListener nettype.PacketListener - // ============================================================ mu sync.Mutex // guards all following fields; see userspaceEngine lock ordering rules muCond *sync.Cond @@ -148,17 +169,43 @@ type Conn struct { started bool // Start was called closed bool // Close was called + // endpointsUpdateActive indicates that updateEndpoints is + // currently running. It's used to deduplicate concurrent endpoint + // update requests. endpointsUpdateActive bool - wantEndpointsUpdate string // true if non-empty; string is reason - lastEndpoints []string - peerSet map[key.Public]struct{} - - discoPrivate key.Private - discoPublic tailcfg.DiscoKey // public of discoPrivate - discoShort string // ShortString of discoPublic (to save logging work later) - nodeOfDisco map[tailcfg.DiscoKey]*tailcfg.Node - discoOfNode map[tailcfg.NodeKey]tailcfg.DiscoKey - discoOfAddr map[netaddr.IPPort]tailcfg.DiscoKey // validated non-DERP paths only + // wantEndpointsUpdate, if non-empty, means that a new endpoints + // update should begin immediately after the currently-running one + // completes. It can only be non-empty if + // endpointsUpdateActive==true. + wantEndpointsUpdate string // true if non-empty; string is reason + // lastEndpoints records the endpoints found during the previous + // endpoint discovery. It's used to avoid duplicate endpoint + // change notifications. + lastEndpoints []string + + // peerSet is the set of peers that are currently configured in + // WireGuard. These are not used to filter inbound or outbound + // traffic at all, but only to track what state can be cleaned up + // in other maps below that are keyed by peer public key. + peerSet map[key.Public]struct{} + + // discoPrivate is the private naclbox key used for active + // discovery traffic. It's created once near (but not during) + // construction. + discoPrivate key.Private + discoPublic tailcfg.DiscoKey // public of discoPrivate + discoShort string // ShortString of discoPublic (to save logging work later) + // nodeOfDisco tracks the networkmap Node entity for each peer + // discovery key. + // + // TODO(danderson): the only thing we ever use from this is the + // peer's WireGuard public key. This could be a map of DiscoKey to + // NodeKey. + nodeOfDisco map[tailcfg.DiscoKey]*tailcfg.Node + discoOfNode map[tailcfg.NodeKey]tailcfg.DiscoKey + discoOfAddr map[netaddr.IPPort]tailcfg.DiscoKey // validated non-DERP paths only + // endpointsOfDisco tracks the wireguard-go endpoints for peers + // with recent activity. endpointOfDisco map[tailcfg.DiscoKey]*discoEndpoint // those with activity only sharedDiscoKey map[tailcfg.DiscoKey]*[32]byte // nacl/box precomputed key @@ -173,18 +220,35 @@ type Conn struct { // 10.0.0.1:1 -> [10.0.0.1:1, 10.0.0.2:2] // 10.0.0.2:2 -> [10.0.0.1:1, 10.0.0.2:2] // 10.0.0.3:3 -> [10.0.0.3:3] + // + // Used only to communicate with legacy, pre-active-discovery + // clients. addrsByUDP map[netaddr.IPPort]*AddrSet - // addrsByKey maps from public keys (as seen by incoming DERP // packets) to its AddrSet (the same values as in addrsByUDP). + // + // Used only to communicate with legacy, pre-active-discovery + // clients. addrsByKey map[key.Public]*AddrSet + // netInfoFunc is a callback that provides a tailcfg.NetInfo when + // discovered network conditions change. + // + // TODO(danderson): why can't it be set at construction time? + // There seem to be a few natural places in ipn/local.go to + // swallow untimely invocations. netInfoFunc func(*tailcfg.NetInfo) // nil until set + // netInfoLast is the NetInfo provided in the last call to + // netInfoFunc. It's used to deduplicate calls to netInfoFunc. + // + // TODO(danderson): should all the deduping happen in + // ipn/local.go? We seem to be doing dedupe at several layers, and + // magicsock could do with any complexity reduction it can get. netInfoLast *tailcfg.NetInfo derpMap *tailcfg.DERPMap // nil (or zero regions/nodes) means DERP is disabled netMap *controlclient.NetworkMap - privateKey key.Private + privateKey key.Private // WireGuard private key for this node everHadKey bool // whether we ever had a non-zero private key myDerp int // nearest DERP region ID; 0 means none/unknown derpStarted chan struct{} // closed on first connection to DERP; for tests & cleaner Close @@ -370,7 +434,7 @@ func newConn() *Conn { // It doesn't start doing anything until Start is called. func NewConn(opts Options) (*Conn, error) { c := newConn() - c.pconnPort = opts.Port + c.port = opts.Port c.logf = opts.logf() c.epFunc = opts.endpointsFunc() c.derpActiveFunc = opts.derpActiveFunc() @@ -834,9 +898,9 @@ func (c *Conn) determineEndpoints(ctx context.Context) (ipPorts []string, reason // port mapping on their router to the same explicit // port that tailscaled is running with. Worst case // it's an invalid candidate mapping. - if nr.MappingVariesByDestIP.EqualBool(true) && c.pconnPort != 0 { + if nr.MappingVariesByDestIP.EqualBool(true) && c.port != 0 { if ip, _, err := net.SplitHostPort(nr.GlobalV4); err == nil { - addAddr(net.JoinHostPort(ip, strconv.Itoa(int(c.pconnPort))), "port_in") + addAddr(net.JoinHostPort(ip, strconv.Itoa(int(c.port))), "port_in") } } } @@ -2499,18 +2563,18 @@ func (c *Conn) bind1(ruc **RebindingUDPConn, which string) error { var pc net.PacketConn var err error listenCtx := context.Background() // unused without DNS name to resolve - if c.pconnPort == 0 && DefaultPort != 0 { + if c.port == 0 && DefaultPort != 0 { pc, err = c.listenPacket(listenCtx, which, net.JoinHostPort(host, fmt.Sprint(DefaultPort))) if err != nil { c.logf("magicsock: bind: default port %s/%v unavailable; picking random", which, DefaultPort) } } if pc == nil { - pc, err = c.listenPacket(listenCtx, which, net.JoinHostPort(host, fmt.Sprint(c.pconnPort))) + pc, err = c.listenPacket(listenCtx, which, net.JoinHostPort(host, fmt.Sprint(c.port))) } if err != nil { - c.logf("magicsock: bind(%s/%v): %v", which, c.pconnPort, err) - return fmt.Errorf("magicsock: bind: %s/%d: %v", which, c.pconnPort, err) + c.logf("magicsock: bind(%s/%v): %v", which, c.port, err) + return fmt.Errorf("magicsock: bind: %s/%d: %v", which, c.port, err) } if *ruc == nil { *ruc = new(RebindingUDPConn) @@ -2527,19 +2591,19 @@ func (c *Conn) Rebind() { host = "127.0.0.1" } listenCtx := context.Background() // unused without DNS name to resolve - if c.pconnPort != 0 { + if c.port != 0 { c.pconn4.mu.Lock() if err := c.pconn4.pconn.Close(); err != nil { c.logf("magicsock: link change close failed: %v", err) } - packetConn, err := c.listenPacket(listenCtx, "udp4", fmt.Sprintf("%s:%d", host, c.pconnPort)) + packetConn, err := c.listenPacket(listenCtx, "udp4", fmt.Sprintf("%s:%d", host, c.port)) if err == nil { - c.logf("magicsock: link change rebound port: %d", c.pconnPort) + c.logf("magicsock: link change rebound port: %d", c.port) c.pconn4.pconn = packetConn.(*net.UDPConn) c.pconn4.mu.Unlock() return } - c.logf("magicsock: link change unable to bind fixed port %d: %v, falling back to random port", c.pconnPort, err) + c.logf("magicsock: link change unable to bind fixed port %d: %v, falling back to random port", c.port, err) c.pconn4.mu.Unlock() } c.logf("magicsock: link change, binding new port")