wgengine/wgcfg: use just the hexlified node key as the WireGuard endpoint.

The node key is all magicsock needs to find the endpoint that WireGuard
needs.

Updates #2752

Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
David Anderson
2021-08-31 22:37:23 -07:00
committed by Dave Anderson
parent d00341360f
commit bb10443edf
13 changed files with 44 additions and 115 deletions
+4 -22
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; DO NOT EDIT.
// Code generated by tailscale.com/cmd/cloner -type Config,Peer; 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
// tailscale.com/cmd/cloner -type Config,Peer
var _ConfigNeedsRegeneration = Config(struct {
Name string
PrivateKey wgkey.Private
@@ -53,28 +53,10 @@ func (src *Peer) Clone() *Peer {
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints
// tailscale.com/cmd/cloner -type Config,Peer
var _PeerNeedsRegeneration = Peer(struct {
PublicKey wgkey.Key
DiscoKey tailcfg.DiscoKey
AllowedIPs []netaddr.IPPrefix
Endpoints Endpoints
PersistentKeepalive uint16
}{})
// Clone makes a deep copy of Endpoints.
// The result aliases no memory with the original.
func (src *Endpoints) Clone() *Endpoints {
if src == nil {
return nil
}
dst := new(Endpoints)
*dst = *src
return dst
}
// A compilation failure here means this code must be regenerated, with command:
// tailscale.com/cmd/cloner -type Config,Peer,Endpoints
var _EndpointsNeedsRegeneration = Endpoints(struct {
PublicKey wgkey.Key
DiscoKey tailcfg.DiscoKey
}{})
+2 -13
View File
@@ -11,7 +11,7 @@ import (
"tailscale.com/types/wgkey"
)
//go:generate go run tailscale.com/cmd/cloner -type=Config,Peer,Endpoints -output=clone.go
//go:generate go run tailscale.com/cmd/cloner -type=Config,Peer -output=clone.go
// Config is a WireGuard configuration.
// It only supports the set of things Tailscale uses.
@@ -26,22 +26,11 @@ type Config struct {
type Peer struct {
PublicKey wgkey.Key
DiscoKey tailcfg.DiscoKey // present only so we can handle restarts within wgengine, not passed to WireGuard
AllowedIPs []netaddr.IPPrefix
Endpoints Endpoints
PersistentKeepalive uint16
}
// 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"`
}
// PeerWithKey returns the Peer with key k and reports whether it was found.
func (config Config) PeerWithKey(k wgkey.Key) (Peer, bool) {
for _, p := range config.Peers {
+3 -5
View File
@@ -10,7 +10,6 @@ import (
"io"
"net"
"os"
"reflect"
"sort"
"strings"
"sync"
@@ -129,7 +128,7 @@ func TestDeviceConfig(t *testing.T) {
})
t.Run("device1 modify peer", func(t *testing.T) {
cfg1.Peers[0].Endpoints.DiscoKey = tailcfg.DiscoKey{1}
cfg1.Peers[0].DiscoKey = tailcfg.DiscoKey{1}
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
t.Fatal(err)
}
@@ -137,7 +136,7 @@ func TestDeviceConfig(t *testing.T) {
})
t.Run("device1 replace endpoint", func(t *testing.T) {
cfg1.Peers[0].Endpoints.DiscoKey = tailcfg.DiscoKey{2}
cfg1.Peers[0].DiscoKey = tailcfg.DiscoKey{2}
if err := ReconfigDevice(device1, cfg1, t.Logf); err != nil {
t.Fatal(err)
}
@@ -177,8 +176,7 @@ func TestDeviceConfig(t *testing.T) {
return p
}
peersEqual := func(p, q Peer) bool {
return p.PublicKey == q.PublicKey && p.PersistentKeepalive == q.PersistentKeepalive &&
reflect.DeepEqual(p.Endpoints, q.Endpoints) && cidrsEqual(p.AllowedIPs, q.AllowedIPs)
return p.PublicKey == q.PublicKey && p.DiscoKey == q.DiscoKey && p.PersistentKeepalive == q.PersistentKeepalive && cidrsEqual(p.AllowedIPs, q.AllowedIPs)
}
if !peersEqual(peer0(origCfg), peer0(newCfg)) {
t.Error("reconfig modified old peer")
+1 -1
View File
@@ -71,13 +71,13 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
}
cfg.Peers = append(cfg.Peers, wgcfg.Peer{
PublicKey: wgkey.Key(peer.Key),
DiscoKey: peer.DiscoKey,
})
cpeer := &cfg.Peers[len(cfg.Peers)-1]
if peer.KeepAlive {
cpeer.PersistentKeepalive = 25 // seconds
}
cpeer.Endpoints = wgcfg.Endpoints{PublicKey: wgkey.Key(peer.Key), DiscoKey: peer.DiscoKey}
didExitNodeWarn := false
for _, allowedIP := range peer.AllowedIPs {
if allowedIP.Bits() == 0 && peer.StableID != exitNode {
+11 -3
View File
@@ -7,7 +7,6 @@ package wgcfg
import (
"bufio"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net"
@@ -156,8 +155,17 @@ func (cfg *Config) handlePublicKeyLine(valueBytes []byte) (*Peer, error) {
func (cfg *Config) handlePeerLine(peer *Peer, key, value mem.RO, valueBytes []byte) error {
switch {
case key.EqualString("endpoint"):
if err := json.Unmarshal(valueBytes, &peer.Endpoints); err != nil {
return err
// TODO: our key types are all over the place, and this
// particular one can't parse a mem.RO or a []byte without
// allocating. We don't reconfigure wireguard often though, so
// this is okay.
s := value.StringCopy()
k, err := wgkey.ParseHex(s)
if err != nil {
return fmt.Errorf("invalid endpoint %q for peer %q, expected a hex public key", s, peer.PublicKey.ShortString())
}
if k != peer.PublicKey {
return fmt.Errorf("unexpected endpoint %q for peer %q, expected the peer's public key", s, peer.PublicKey.ShortString())
}
case key.EqualString("persistent_keepalive_interval"):
n, err := mem.ParseUint(value, 10, 16)
-1
View File
@@ -75,7 +75,6 @@ func BenchmarkFromUAPI(b *testing.B) {
peer := Peer{
PublicKey: k1,
AllowedIPs: []netaddr.IPPrefix{ip1},
Endpoints: Endpoints{PublicKey: k1},
}
cfg1 := &Config{
PrivateKey: wgkey.Private(pk1),
+6 -8
View File
@@ -5,7 +5,6 @@
package wgcfg
import (
"encoding/json"
"fmt"
"io"
"strconv"
@@ -48,16 +47,15 @@ func (cfg *Config) ToUAPI(w io.Writer, prev *Config) error {
// Add/configure all new peers.
for _, p := range cfg.Peers {
oldPeer := old[p.PublicKey]
oldPeer, wasPresent := old[p.PublicKey]
setPeer(p)
set("protocol_version", "1")
if oldPeer.Endpoints != p.Endpoints {
buf, err := json.Marshal(p.Endpoints)
if err != nil {
return err
}
set("endpoint", string(buf))
// Avoid setting endpoints if the correct one is already known
// to WireGuard, because doing so generates a bit more work in
// calling magicsock's ParseEndpoint for effectively a no-op.
if !wasPresent {
set("endpoint", p.PublicKey.HexString())
}
// TODO: replace_allowed_ips is expensive.