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:
committed by
Dave Anderson
parent
61c62f48d9
commit
97693f2e42
+4
-25
@@ -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
|
||||
}{})
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user