wgengine/magicsock: delete legacy AddrSet endpoints.

Instead of using the legacy codepath, teach discoEndpoint to handle
peers that have a home DERP, but no disco key. We can still communicate
with them, but only over DERP.

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson
2021-08-25 19:39:20 -07:00
committed by Dave Anderson
parent 61c62f48d9
commit 97693f2e42
11 changed files with 596 additions and 1394 deletions
+4 -25
View File
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Code generated by tailscale.com/cmd/cloner -type Config,Peer,Endpoints,IPPortSet; DO NOT EDIT.
// Code generated by tailscale.com/cmd/cloner -type Config,Peer,Endpoints; DO NOT EDIT.
package wgcfg
@@ -30,7 +30,7 @@ func (src *Config) Clone() *Config {
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints,IPPortSet
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints
var _ConfigNeedsRegeneration = Config(struct {
Name string
PrivateKey wgkey.Private
@@ -49,12 +49,11 @@ func (src *Peer) Clone() *Peer {
dst := new(Peer)
*dst = *src
dst.AllowedIPs = append(src.AllowedIPs[:0:0], src.AllowedIPs...)
dst.Endpoints = *src.Endpoints.Clone()
return dst
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints,IPPortSet
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints
var _PeerNeedsRegeneration = Peer(struct {
PublicKey wgkey.Key
AllowedIPs []netaddr.IPPrefix
@@ -70,32 +69,12 @@ func (src *Endpoints) Clone() *Endpoints {
}
dst := new(Endpoints)
*dst = *src
dst.IPPorts = *src.IPPorts.Clone()
return dst
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints,IPPortSet
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints
var _EndpointsNeedsRegeneration = Endpoints(struct {
PublicKey wgkey.Key
DiscoKey tailcfg.DiscoKey
IPPorts IPPortSet
}{})
// Clone makes a deep copy of IPPortSet.
// The result aliases no memory with the original.
func (src *IPPortSet) Clone() *IPPortSet {
if src == nil {
return nil
}
dst := new(IPPortSet)
*dst = *src
dst.ipp = append(src.ipp[:0:0], src.ipp...)
return dst
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints,IPPortSet
var _IPPortSetNeedsRegeneration = IPPortSet(struct {
ipp []netaddr.IPPort
}{})
+3 -77
View File
@@ -6,15 +6,12 @@
package wgcfg
import (
"encoding/json"
"strings"
"inet.af/netaddr"
"tailscale.com/tailcfg"
"tailscale.com/types/wgkey"
)
//go:generate go run tailscale.com/cmd/cloner -type=Config,Peer,Endpoints,IPPortSet -output=clone.go
//go:generate go run tailscale.com/cmd/cloner -type=Config,Peer,Endpoints -output=clone.go
// Config is a WireGuard configuration.
// It only supports the set of things Tailscale uses.
@@ -36,84 +33,13 @@ type Peer struct {
// Endpoints represents the routes to reach a remote node.
// It is serialized and provided to wireguard-go as a conn.Endpoint.
//
// TODO: change name, it's now just a pair of keys representing a peer.
type Endpoints struct {
// PublicKey is the public key for the remote node.
PublicKey wgkey.Key `json:"pk"`
// DiscoKey is the disco key associated with the remote node.
DiscoKey tailcfg.DiscoKey `json:"dk,omitempty"`
// IPPorts is a set of possible ip+ports the remote node can be reached at.
// This is used only for legacy connections to pre-disco (pre-0.100) peers.
IPPorts IPPortSet `json:"ipp,omitempty"`
}
func (e Endpoints) Equal(f Endpoints) bool {
if e.PublicKey != f.PublicKey {
return false
}
if e.DiscoKey != f.DiscoKey {
return false
}
return e.IPPorts.EqualUnordered(f.IPPorts)
}
// IPPortSet is an immutable slice of netaddr.IPPorts.
type IPPortSet struct {
ipp []netaddr.IPPort
}
// NewIPPortSet returns an IPPortSet containing the ports in ipp.
func NewIPPortSet(ipps ...netaddr.IPPort) IPPortSet {
return IPPortSet{ipp: append(ipps[:0:0], ipps...)}
}
// String returns a comma-separated list of all IPPorts in s.
func (s IPPortSet) String() string {
buf := new(strings.Builder)
for i, ipp := range s.ipp {
if i > 0 {
buf.WriteByte(',')
}
buf.WriteString(ipp.String())
}
return buf.String()
}
// IPPorts returns a slice of netaddr.IPPorts containing the IPPorts in s.
func (s IPPortSet) IPPorts() []netaddr.IPPort {
return append(s.ipp[:0:0], s.ipp...)
}
// EqualUnordered reports whether s and t contain the same IPPorts, regardless of order.
func (s IPPortSet) EqualUnordered(t IPPortSet) bool {
if len(s.ipp) != len(t.ipp) {
return false
}
// Check whether the endpoints are the same, regardless of order.
ipps := make(map[netaddr.IPPort]int, len(s.ipp))
for _, ipp := range s.ipp {
ipps[ipp]++
}
for _, ipp := range t.ipp {
ipps[ipp]--
}
for _, n := range ipps {
if n != 0 {
return false
}
}
return true
}
// MarshalJSON marshals s into JSON.
// It is necessary so that IPPortSet's fields can be unexported, to guarantee immutability.
func (s IPPortSet) MarshalJSON() ([]byte, error) {
return json.Marshal(s.ipp)
}
// UnmarshalJSON unmarshals s from JSON.
// It is necessary so that IPPortSet's fields can be unexported, to guarantee immutability.
func (s *IPPortSet) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &s.ipp)
}
// PeerWithKey returns the Peer with key k and reports whether it was found.
+3 -2
View File
@@ -20,6 +20,7 @@ import (
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
"inet.af/netaddr"
"tailscale.com/tailcfg"
"tailscale.com/types/wgkey"
)
@@ -128,7 +129,7 @@ func TestDeviceConfig(t *testing.T) {
})
t.Run("device1 modify peer", func(t *testing.T) {
cfg1.Peers[0].Endpoints.IPPorts = NewIPPortSet(netaddr.MustParseIPPort("1.2.3.4:12345"))
cfg1.Peers[0].Endpoints.DiscoKey = tailcfg.DiscoKey{1}
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
t.Fatal(err)
}
@@ -136,7 +137,7 @@ func TestDeviceConfig(t *testing.T) {
})
t.Run("device1 replace endpoint", func(t *testing.T) {
cfg1.Peers[0].Endpoints.IPPorts = NewIPPortSet(netaddr.MustParseIPPort("1.1.1.1:123"))
cfg1.Peers[0].Endpoints.DiscoKey = tailcfg.DiscoKey{2}
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
t.Fatal(err)
}
-25
View File
@@ -78,19 +78,6 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
}
cpeer.Endpoints = wgcfg.Endpoints{PublicKey: wgkey.Key(peer.Key), DiscoKey: peer.DiscoKey}
if peer.DiscoKey.IsZero() {
// Legacy connection. Add IP+port endpoints.
var ipps []netaddr.IPPort
if err := appendEndpoint(cpeer, &ipps, peer.DERP); err != nil {
return nil, err
}
for _, ep := range peer.Endpoints {
if err := appendEndpoint(cpeer, &ipps, ep); err != nil {
return nil, err
}
}
cpeer.Endpoints.IPPorts = wgcfg.NewIPPortSet(ipps...)
}
didExitNodeWarn := false
for _, allowedIP := range peer.AllowedIPs {
if allowedIP.Bits() == 0 && peer.StableID != exitNode {
@@ -135,15 +122,3 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
return cfg, nil
}
func appendEndpoint(peer *wgcfg.Peer, ipps *[]netaddr.IPPort, epStr string) error {
if epStr == "" {
return nil
}
ipp, err := netaddr.ParseIPPort(epStr)
if err != nil {
return fmt.Errorf("malformed endpoint %q for peer %v", epStr, peer.PublicKey.ShortString())
}
*ipps = append(*ipps, ipp)
return nil
}
+1 -1
View File
@@ -52,7 +52,7 @@ func (cfg *Config) ToUAPI(w io.Writer, prev *Config) error {
setPeer(p)
set("protocol_version", "1")
if !oldPeer.Endpoints.Equal(p.Endpoints) {
if oldPeer.Endpoints != p.Endpoints {
buf, err := json.Marshal(p.Endpoints)
if err != nil {
return err