summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJosh Bleecher Snyder <josh@tailscale.com>2021-03-27 14:07:50 -0700
committerJosh Bleecher Snyder <josh@tailscale.com>2021-03-27 14:07:50 -0700
commit969a8540e286b09e72c38e568ddbbf7e383ce7d7 (patch)
treed2a65bdda4d5808d34773f53a741121d951350c4
parent4954fbfda670361ffb963725fbb6dc2773f5681e (diff)
downloadtailscale-josh/wip/create-endpoint-no-public-key.tar.xz
tailscale-josh/wip/create-endpoint-no-public-key.zip
WIP: encode peer public key in endpointjosh/wip/create-endpoint-no-public-key
incomplete new idea is to make a new type in wgcfg an Endpoints type that can be serialized/deserialized nicely at the edges and be easy to deal with other places.
-rw-r--r--internal/deepprint/deepprint_test.go5
-rw-r--r--wgengine/magicsock/magicsock.go1
-rw-r--r--wgengine/userspace.go12
-rw-r--r--wgengine/wgcfg/config.go15
-rw-r--r--wgengine/wgcfg/nmcfg/nmcfg.go12
-rw-r--r--wgengine/wgcfg/parser.go2
-rw-r--r--wgengine/wgcfg/writer.go12
7 files changed, 42 insertions, 17 deletions
diff --git a/internal/deepprint/deepprint_test.go b/internal/deepprint/deepprint_test.go
index c7e2031f2..d7198185c 100644
--- a/internal/deepprint/deepprint_test.go
+++ b/internal/deepprint/deepprint_test.go
@@ -6,6 +6,7 @@ package deepprint
import (
"bytes"
+ "strings"
"testing"
"inet.af/netaddr"
@@ -33,6 +34,8 @@ func TestDeepPrint(t *testing.T) {
}
}
+var dummyHeyKey = strings.Repeat("0", wgcfg.HexKeyLen)
+
func getVal() []interface{} {
return []interface{}{
&wgcfg.Config{
@@ -41,7 +44,7 @@ func getVal() []interface{} {
ListenPort: 5,
Peers: []wgcfg.Peer{
{
- Endpoints: "foo:5",
+ Endpoints2: dummyHeyKey + "@foo:5",
},
},
},
diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go
index 7a437f9e8..58f6751a4 100644
--- a/wgengine/magicsock/magicsock.go
+++ b/wgengine/magicsock/magicsock.go
@@ -2745,7 +2745,6 @@ func (c *Conn) CreateBind(uint16) (conn.Bind, uint16, error) {
// is running code that supports active discovery, so CreateEndpoint returns
// a discoEndpoint.
//
-
func (c *Conn) CreateEndpoint(pubKey [32]byte, addrs string) (conn.Endpoint, error) {
c.mu.Lock()
defer c.mu.Unlock()
diff --git a/wgengine/userspace.go b/wgengine/userspace.go
index 199604614..37ffd89c4 100644
--- a/wgengine/userspace.go
+++ b/wgengine/userspace.go
@@ -639,11 +639,11 @@ func isTrimmablePeer(p *wgcfg.Peer, numPeers int) bool {
if forceFullWireguardConfig(numPeers) {
return false
}
- if !isSingleEndpoint(p.Endpoints) {
+ if !isSingleEndpoint(p.Endpoints2) {
return false
}
- host, _, err := net.SplitHostPort(p.Endpoints)
+ host, _, err := splitEndpointHostPort(p.Endpoints2)
if err != nil {
return false
}
@@ -986,7 +986,13 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config)
// isSingleEndpoint reports whether endpoints contains exactly one host:port pair.
func isSingleEndpoint(s string) bool {
- return s != "" && !strings.Contains(s, ",")
+ return len(s) > wgcfg.HexKeyPrefixLen && !strings.Contains(s, ",")
+}
+
+// splitEndpointHostPort returns net.SplitHostPort of the sole endpoint in s.
+func splitEndpointHostPort(s string) (host, port string, err error) {
+ ep := s[wgcfg.HexKeyPrefixLen:]
+ return net.SplitHostPort(ep)
}
func (e *userspaceEngine) GetFilter() *filter.Filter {
diff --git a/wgengine/wgcfg/config.go b/wgengine/wgcfg/config.go
index 2928e47d2..73497f5e9 100644
--- a/wgengine/wgcfg/config.go
+++ b/wgengine/wgcfg/config.go
@@ -27,12 +27,21 @@ type Config struct {
}
type Peer struct {
- PublicKey Key
- AllowedIPs []netaddr.IPPrefix
- Endpoints string // comma-separated host/port pairs: "1.2.3.4:56,[::]:80"
+ PublicKey Key
+ AllowedIPs []netaddr.IPPrefix
+ // Endpoints encodes information about the Peer.
+ // It has the form: "<HEXKEY>@1.2.3.4:56,[::]:80".
+ // The first 65 bytes are a hex-encoded public key, then '@'.
+ // The remainder is a comma-separated list of host/port pairs.
+ Endpoints2 string
PersistentKeepalive uint16
}
+const (
+ HexKeyLength = KeySize * 2 // KeySize when encoded as hex bytes
+ HexKeyPrefixLen = HexKeyLength + len("@")
+)
+
// Copy makes a deep copy of Config.
// The result aliases no memory with the original.
func (cfg Config) Copy() Config {
diff --git a/wgengine/wgcfg/nmcfg/nmcfg.go b/wgengine/wgcfg/nmcfg/nmcfg.go
index 57053ea78..1ea42c431 100644
--- a/wgengine/wgcfg/nmcfg/nmcfg.go
+++ b/wgengine/wgcfg/nmcfg/nmcfg.go
@@ -51,7 +51,7 @@ func cidrIsSubnet(node *tailcfg.Node, cidr netaddr.IPPrefix) bool {
return true
}
-// WGCfg returns the NetworkMaps's Wireguard configuration.
+// WGCfg returns the NetworkMaps's WireGuard configuration.
func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags, exitNode tailcfg.StableNodeID) (*wgcfg.Config, error) {
cfg := &wgcfg.Config{
Name: "tailscale",
@@ -77,7 +77,7 @@ func WGCfg(nm *netmap.NetworkMap, logf logger.Logf, flags netmap.WGConfigFlags,
if err := appendEndpoint(cpeer, fmt.Sprintf("%x%s", peer.DiscoKey[:], wgcfg.EndpointDiscoSuffix)); err != nil {
return nil, err
}
- cpeer.Endpoints = fmt.Sprintf("%x.disco.tailscale:12345", peer.DiscoKey[:])
+ cpeer.Endpoints2 = fmt.Sprintf("%x@%x.disco.tailscale:12345", peer.Key, peer.DiscoKey[:])
} else {
if err := appendEndpoint(cpeer, peer.DERP); err != nil {
return nil, err
@@ -122,9 +122,11 @@ func appendEndpoint(peer *wgcfg.Peer, epStr string) error {
if err != nil {
return fmt.Errorf("invalid port in endpoint %q for peer %v", epStr, peer.PublicKey.ShortString())
}
- if peer.Endpoints != "" {
- peer.Endpoints += ","
+ if peer.Endpoints2 == "" {
+ peer.Endpoints2 = peer.PublicKey.HexString() + "@"
+ } else {
+ peer.Endpoints2 += ","
}
- peer.Endpoints += epStr
+ peer.Endpoints2 += epStr
return nil
}
diff --git a/wgengine/wgcfg/parser.go b/wgengine/wgcfg/parser.go
index bf0b45835..6120ceb58 100644
--- a/wgengine/wgcfg/parser.go
+++ b/wgengine/wgcfg/parser.go
@@ -175,7 +175,7 @@ func (cfg *Config) handlePeerLine(peer *Peer, key, value string) error {
if err != nil {
return err
}
- peer.Endpoints = value
+ peer.Endpoints2 = peer.PublicKey.HexString() + "@" + value
case "persistent_keepalive_interval":
n, err := strconv.ParseUint(value, 10, 16)
if err != nil {
diff --git a/wgengine/wgcfg/writer.go b/wgengine/wgcfg/writer.go
index 079c1eb5e..89c592f67 100644
--- a/wgengine/wgcfg/writer.go
+++ b/wgengine/wgcfg/writer.go
@@ -55,8 +55,8 @@ func (cfg *Config) ToUAPI(w io.Writer, prev *Config) error {
setPeer(p)
set("protocol_version", "1")
- if !endpointsEqual(oldPeer.Endpoints, p.Endpoints) {
- set("endpoint", p.Endpoints)
+ if !endpointsEqual(oldPeer.Endpoints2, p.Endpoints2) {
+ set("endpoint", p.Endpoints2)
}
// TODO: replace_allowed_ips is expensive.
@@ -97,12 +97,18 @@ func endpointsEqual(x, y string) bool {
if x == y {
return true
}
+ // Public keys must match.
+ if x[:HexKeyPrefixLen] != y[:HexKeyPrefixLen] {
+ return false
+ }
+ // See whether the addresses are the same, but out of order.
+ x = x[HexKeyPrefixLen:]
+ y = y[HexKeyPrefixLen:]
xs := strings.Split(x, ",")
ys := strings.Split(y, ",")
if len(xs) != len(ys) {
return false
}
- // Otherwise, see if they're the same, but out of order.
sort.Strings(xs)
sort.Strings(ys)
x = strings.Join(xs, ",")