diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index cbbff7734..2af1dd217 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -27,7 +27,7 @@ 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+ - github.com/tailscale/wireguard-go/wgcfg from github.com/tailscale/wireguard-go/conn+ + github.com/tailscale/wireguard-go/wgcfg from github.com/tailscale/wireguard-go/device+ github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck github.com/toqueteos/webbrowser from tailscale.com/cmd/tailscale/cli 💣 go4.org/intern from inet.af/netaddr diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index faf95f01e..64c949cdd 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -31,7 +31,7 @@ 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+ - github.com/tailscale/wireguard-go/wgcfg from github.com/tailscale/wireguard-go/conn+ + github.com/tailscale/wireguard-go/wgcfg from github.com/tailscale/wireguard-go/device+ github.com/tcnksm/go-httpstat from tailscale.com/net/netcheck 💣 go4.org/intern from inet.af/netaddr 💣 go4.org/mem from tailscale.com/control/controlclient+ diff --git a/control/controlclient/netmap.go b/control/controlclient/netmap.go index a79a5c780..e9cbb4222 100644 --- a/control/controlclient/netmap.go +++ b/control/controlclient/netmap.go @@ -298,7 +298,7 @@ func (nm *NetworkMap) WGCfg(logf logger.Logf, flags WGConfigFlags) (*wgcfg.Confi if err := appendEndpoint(cpeer, fmt.Sprintf("%x%s", peer.DiscoKey[:], EndpointDiscoSuffix)); err != nil { return nil, err } - cpeer.Endpoints = []wgcfg.Endpoint{{Host: fmt.Sprintf("%x.disco.tailscale", peer.DiscoKey[:]), Port: 12345}} + cpeer.Endpoints = fmt.Sprintf("%x.disco.tailscale:12345", peer.DiscoKey[:]) } else { if err := appendEndpoint(cpeer, peer.DERP); err != nil { return nil, err @@ -349,15 +349,18 @@ func appendEndpoint(peer *wgcfg.Peer, epStr string) error { if epStr == "" { return nil } - host, port, err := net.SplitHostPort(epStr) + _, port, err := net.SplitHostPort(epStr) if err != nil { return fmt.Errorf("malformed endpoint %q for peer %v", epStr, peer.PublicKey.ShortString()) } - port16, err := strconv.ParseUint(port, 10, 16) + _, err = strconv.ParseUint(port, 10, 16) if err != nil { return fmt.Errorf("invalid port in endpoint %q for peer %v", epStr, peer.PublicKey.ShortString()) } - peer.Endpoints = append(peer.Endpoints, wgcfg.Endpoint{Host: host, Port: uint16(port16)}) + if peer.Endpoints != "" { + peer.Endpoints += "," + } + peer.Endpoints += epStr return nil } diff --git a/go.mod b/go.mod index 1d43f6d15..17e7fba5d 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,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-20201214215404-77d1e9757027 - github.com/tailscale/wireguard-go v0.0.0-20210113223737-a6213b5eaf98 + github.com/tailscale/wireguard-go v0.0.0-20210114205708-a1377e83f551 github.com/tcnksm/go-httpstat v0.2.0 github.com/toqueteos/webbrowser v1.2.0 go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 diff --git a/go.sum b/go.sum index cb107a7e1..c4f10ad58 100644 --- a/go.sum +++ b/go.sum @@ -290,6 +290,8 @@ github.com/tailscale/wireguard-go v0.0.0-20210109012254-dc30a1b9415e h1:ZXbXfVJO github.com/tailscale/wireguard-go v0.0.0-20210109012254-dc30a1b9415e/go.mod h1:K/wyv4+3PcdVVTV7szyoiEjJ1nVHonM8cJ2mQwG5Fl8= github.com/tailscale/wireguard-go v0.0.0-20210113223737-a6213b5eaf98 h1:khwYPK1eT+4pmEFyCjpf6Br/0JWjdVT3uQ+ILFJPTRo= github.com/tailscale/wireguard-go v0.0.0-20210113223737-a6213b5eaf98/go.mod h1:K/wyv4+3PcdVVTV7szyoiEjJ1nVHonM8cJ2mQwG5Fl8= +github.com/tailscale/wireguard-go v0.0.0-20210114205708-a1377e83f551 h1:hjBVxvVa145kVflAFkVcTr/zwUzBO4SqfSS6xhbcMv8= +github.com/tailscale/wireguard-go v0.0.0-20210114205708-a1377e83f551/go.mod h1:K/wyv4+3PcdVVTV7szyoiEjJ1nVHonM8cJ2mQwG5Fl8= 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= diff --git a/internal/deepprint/deepprint_test.go b/internal/deepprint/deepprint_test.go index 5512c1e11..e2ae45ba7 100644 --- a/internal/deepprint/deepprint_test.go +++ b/internal/deepprint/deepprint_test.go @@ -41,12 +41,7 @@ func getVal() []interface{} { ListenPort: 5, Peers: []wgcfg.Peer{ { - Endpoints: []wgcfg.Endpoint{ - { - Host: "foo", - Port: 5, - }, - }, + Endpoints: "foo:5", }, }, }, diff --git a/wgengine/magicsock/legacy.go b/wgengine/magicsock/legacy.go index 2af2b664a..9bb7bb355 100644 --- a/wgengine/magicsock/legacy.go +++ b/wgengine/magicsock/legacy.go @@ -567,24 +567,18 @@ func (as *addrSet) populatePeerStatus(ps *ipnstate.PeerStatus) { } } -func (a *addrSet) Addrs() []wgcfg.Endpoint { - var eps []wgcfg.Endpoint +func (a *addrSet) Addrs() string { + var addrs []string for _, addr := range a.addrs { - eps = append(eps, wgcfg.Endpoint{ - Host: addr.IP.String(), - Port: uint16(addr.Port), - }) + addrs = append(addrs, addr.String()) } a.mu.Lock() defer a.mu.Unlock() if a.roamAddr != nil { - eps = append(eps, wgcfg.Endpoint{ - Host: a.roamAddr.IP.String(), - Port: uint16(a.roamAddr.Port), - }) + addrs = append(addrs, a.roamAddr.String()) } - return eps + return strings.Join(addrs, ",") } // Message types copied from wireguard-go/device/noise-protocol.go diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go index 1cacc827d..fc1c1a8b4 100644 --- a/wgengine/magicsock/magicsock.go +++ b/wgengine/magicsock/magicsock.go @@ -28,7 +28,6 @@ "time" "github.com/tailscale/wireguard-go/conn" - "github.com/tailscale/wireguard-go/wgcfg" "go4.org/mem" "golang.org/x/crypto/nacl/box" "golang.org/x/time/rate" @@ -2977,19 +2976,11 @@ func (de *discoEndpoint) String() string { return fmt.Sprintf("magicsock.discoEndpoint{%v, %v}", de.publicKey.ShortString(), de.discoShort) } -func (de *discoEndpoint) Addrs() []wgcfg.Endpoint { +func (de *discoEndpoint) Addrs() string { // This has to be the same string that was passed to // CreateEndpoint, otherwise Reconfig will end up recreating // Endpoints and losing state over time. - host, portStr, err := net.SplitHostPort(de.wgEndpointHostPort) - if err != nil { - panic(err) - } - port, err := strconv.ParseUint(portStr, 10, 16) - if err != nil { - panic(err) - } - return []wgcfg.Endpoint{{Host: host, Port: uint16(port)}} + return de.wgEndpointHostPort } func (de *discoEndpoint) ClearSrc() {} diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 72030e962..f23cc58ad 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -483,12 +483,9 @@ func makeConfigs(t *testing.T, addrs []netaddr.IPPort) []wgcfg.Config { continue } peer := wgcfg.Peer{ - PublicKey: privKeys[peerNum].Public(), - AllowedIPs: addresses[peerNum], - Endpoints: []wgcfg.Endpoint{{ - Host: addr.IP.String(), - Port: addr.Port, - }}, + PublicKey: privKeys[peerNum].Public(), + AllowedIPs: addresses[peerNum], + Endpoints: addr.String(), PersistentKeepalive: 25, } cfg.Peers = append(cfg.Peers, peer) @@ -1140,12 +1137,12 @@ func testTwoDevicePing(t *testing.T, d *devices) { }) // Add DERP relay. - derpEp := wgcfg.Endpoint{Host: "127.3.3.40", Port: 1} + derpEp := "127.3.3.40:1" ep0 := cfgs[0].Peers[0].Endpoints - ep0 = append([]wgcfg.Endpoint{derpEp}, ep0...) + ep0 = derpEp + "," + ep0 cfgs[0].Peers[0].Endpoints = ep0 ep1 := cfgs[1].Peers[0].Endpoints - ep1 = append([]wgcfg.Endpoint{derpEp}, ep1...) + ep1 = derpEp + "," + ep1 cfgs[1].Peers[0].Endpoints = ep1 if err := m1.dev.Reconfig(&cfgs[0]); err != nil { t.Fatal(err) @@ -1161,8 +1158,8 @@ func testTwoDevicePing(t *testing.T, d *devices) { }) // Disable real route. - cfgs[0].Peers[0].Endpoints = []wgcfg.Endpoint{derpEp} - cfgs[1].Peers[0].Endpoints = []wgcfg.Endpoint{derpEp} + cfgs[0].Peers[0].Endpoints = derpEp + cfgs[1].Peers[0].Endpoints = derpEp if err := m1.dev.Reconfig(&cfgs[0]); err != nil { t.Fatal(err) } diff --git a/wgengine/router/dns/manager_windows.go b/wgengine/router/dns/manager_windows.go index b71b2255c..5940404e7 100644 --- a/wgengine/router/dns/manager_windows.go +++ b/wgengine/router/dns/manager_windows.go @@ -18,7 +18,6 @@ const ( ipv4RegBase = `SYSTEM\CurrentControlSet\Services\Tcpip\Parameters` ipv6RegBase = `SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters` - tsRegBase = `SOFTWARE\Tailscale IPN` ) type windowsManager struct { @@ -91,11 +90,6 @@ func (m windowsManager) Up(config Config) error { return err } - newSearchList := strings.Join(config.Domains, ",") - if err := setRegistryString(tsRegBase, "SearchList", newSearchList); err != nil { - return err - } - // Force DNS re-registration in Active Directory. What we actually // care about is that this command invokes the undocumented hidden // function that forces Windows to notice that adapter settings diff --git a/wgengine/tsdns/tsdns.go b/wgengine/tsdns/tsdns.go index fad334539..680bf51b3 100644 --- a/wgengine/tsdns/tsdns.go +++ b/wgengine/tsdns/tsdns.go @@ -201,12 +201,11 @@ func (r *Resolver) Resolve(domain string, tp dns.Type) (netaddr.IP, dns.RCode, e break } } - if !anyHasSuffix { - return netaddr.IP{}, dns.RCodeRefused, nil - } - addr, found := dnsMap.nameToIP[domain] if !found { + if !anyHasSuffix { + return netaddr.IP{}, dns.RCodeRefused, nil + } return netaddr.IP{}, dns.RCodeNameError, nil } diff --git a/wgengine/userspace.go b/wgengine/userspace.go index 0921346ea..d15579080 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -675,10 +675,15 @@ func isTrimmablePeer(p *wgcfg.Peer, numPeers int) bool { if forceFullWireguardConfig(numPeers) { return false } - if len(p.Endpoints) != 1 { + if !isSingleEndpoint(p.Endpoints) { return false } - if !strings.HasSuffix(p.Endpoints[0].Host, ".disco.tailscale") { + + host, _, err := net.SplitHostPort(p.Endpoints) + if err != nil { + return false + } + if !strings.HasSuffix(host, ".disco.tailscale") { return false } @@ -742,11 +747,14 @@ func (e *userspaceEngine) isActiveSince(dk tailcfg.DiscoKey, ip netaddr.IP, t ti // Host of form "<64-hex-digits>.disco.tailscale". If invariant is violated, // we return the zero value. func discoKeyFromPeer(p *wgcfg.Peer) tailcfg.DiscoKey { - host := p.Endpoints[0].Host - if len(host) < 64 { + if len(p.Endpoints) < 64 { return tailcfg.DiscoKey{} } - k, err := key.NewPublicFromHexMem(mem.S(host[:64])) + host, rest := p.Endpoints[:64], p.Endpoints[64:] + if !strings.HasPrefix(rest, ".disco.tailscale") { + return tailcfg.DiscoKey{} + } + k, err := key.NewPublicFromHexMem(mem.S(host)) if err != nil { return tailcfg.DiscoKey{} } @@ -947,21 +955,21 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config) // and a second time with it. discoChanged := make(map[key.Public]bool) { - prevEP := make(map[key.Public]wgcfg.Endpoint) + prevEP := make(map[key.Public]string) for i := range e.lastCfgFull.Peers { - if p := &e.lastCfgFull.Peers[i]; len(p.Endpoints) == 1 { - prevEP[key.Public(p.PublicKey)] = p.Endpoints[0] + if p := &e.lastCfgFull.Peers[i]; isSingleEndpoint(p.Endpoints) { + prevEP[key.Public(p.PublicKey)] = p.Endpoints } } for i := range cfg.Peers { p := &cfg.Peers[i] - if len(p.Endpoints) != 1 { + if !isSingleEndpoint(p.Endpoints) { continue } pub := key.Public(p.PublicKey) - if old, ok := prevEP[pub]; ok && old != p.Endpoints[0] { + if old, ok := prevEP[pub]; ok && old != p.Endpoints { discoChanged[pub] = true - e.logf("wgengine: Reconfig: %s changed from %s to %s", pub.ShortString(), &old, &p.Endpoints[0]) + e.logf("wgengine: Reconfig: %s changed from %q to %q", pub.ShortString(), old, p.Endpoints) } } } @@ -1006,6 +1014,11 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config) return nil } +// isSingleEndpoint reports whether endpoints contains exactly one host:port pair. +func isSingleEndpoint(s string) bool { + return s != "" && !strings.Contains(s, ",") +} + func (e *userspaceEngine) GetFilter() *filter.Filter { return e.tundev.GetFilter() } diff --git a/wgengine/userspace_test.go b/wgengine/userspace_test.go index 817b03960..eed9ab941 100644 --- a/wgengine/userspace_test.go +++ b/wgengine/userspace_test.go @@ -103,12 +103,7 @@ func TestUserspaceEngineReconfig(t *testing.T) { AllowedIPs: []netaddr.IPPrefix{ {IP: netaddr.IPv4(100, 100, 99, 1), Bits: 32}, }, - Endpoints: []wgcfg.Endpoint{ - { - Host: discoHex + ".disco.tailscale", - Port: 12345, - }, - }, + Endpoints: discoHex + ".disco.tailscale:12345", }, }, } diff --git a/wgengine/wgengine.go b/wgengine/wgengine.go index 6f2af2002..3139dc1f2 100644 --- a/wgengine/wgengine.go +++ b/wgengine/wgengine.go @@ -36,7 +36,7 @@ type PeerStatus struct { // TODO(bradfitz): remove this, subset of ipnstate? Need to migrate users. type Status struct { Peers []PeerStatus - LocalAddrs []string // TODO(crawshaw): []wgcfg.Endpoint? + LocalAddrs []string // the set of possible endpoints for the magic conn DERPs int // number of active DERP connections }