summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@tailscale.com>2020-06-19 12:06:49 -0700
committerBrad Fitzpatrick <bradfitz@tailscale.com>2020-06-19 12:12:00 -0700
commit53fb25fc2fc49deaae48e36044f80ff1eded9aa9 (patch)
tree4a4759a4b0a27c1786610198c1503e60497093e6
parent88c305c8afa15dbee5a6cb8b98e5547cd19f4e7e (diff)
downloadtailscale-53fb25fc2fc49deaae48e36044f80ff1eded9aa9.tar.xz
tailscale-53fb25fc2fc49deaae48e36044f80ff1eded9aa9.zip
all: generate discovery key, plumb it around
Not actually used yet. Updates #483
-rw-r--r--control/controlclient/direct.go4
-rw-r--r--ipn/local.go5
-rw-r--r--tailcfg/tailcfg.go1
-rw-r--r--types/key/key.go11
-rw-r--r--wgengine/magicsock/magicsock.go10
-rw-r--r--wgengine/userspace.go4
-rw-r--r--wgengine/watchdog.go4
-rw-r--r--wgengine/wgengine.go6
8 files changed, 45 insertions, 0 deletions
diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go
index b6cc66939..3ffeaba87 100644
--- a/control/controlclient/direct.go
+++ b/control/controlclient/direct.go
@@ -85,6 +85,7 @@ type Direct struct {
newDecompressor func() (Decompressor, error)
keepAlive bool
logf logger.Logf
+ discoPubKey tailcfg.DiscoKey
mu sync.Mutex // mutex guards the following fields
serverKey wgcfg.Key
@@ -104,6 +105,7 @@ type Options struct {
AuthKey string // optional node auth key for auto registration
TimeNow func() time.Time // time.Now implementation used by Client
Hostinfo *tailcfg.Hostinfo // non-nil passes ownership, nil means to use default using os.Hostname, etc
+ DiscoPublicKey tailcfg.DiscoKey
NewDecompressor func() (Decompressor, error)
KeepAlive bool
Logf logger.Logf
@@ -153,6 +155,7 @@ func NewDirect(opts Options) (*Direct, error) {
keepAlive: opts.KeepAlive,
persist: opts.Persist,
authKey: opts.AuthKey,
+ discoPubKey: opts.DiscoPublicKey,
}
if opts.Hostinfo == nil {
c.SetHostinfo(NewHostinfo())
@@ -478,6 +481,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
IncludeIPv6: includeIPv6(),
KeepAlive: c.keepAlive,
NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()),
+ DiscoKey: c.discoPubKey,
Endpoints: ep,
Stream: allowStream,
Hostinfo: hostinfo,
diff --git a/ipn/local.go b/ipn/local.go
index 2778960b3..fdea6a35a 100644
--- a/ipn/local.go
+++ b/ipn/local.go
@@ -358,6 +358,10 @@ func (b *LocalBackend) Start(opts Options) error {
b.updateFilter(nil)
+ discoPrivate := key.NewPrivate()
+ b.e.SetDiscoPrivateKey(discoPrivate)
+ discoPublic := tailcfg.DiscoKey(discoPrivate.Public())
+
var err error
if persist == nil {
// let controlclient initialize it
@@ -372,6 +376,7 @@ func (b *LocalBackend) Start(opts Options) error {
KeepAlive: true,
NewDecompressor: b.newDecompressor,
HTTPTestClient: opts.HTTPTestClient,
+ DiscoPublicKey: discoPublic,
})
if err != nil {
return err
diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go
index e6b363e1b..9f4668019 100644
--- a/tailcfg/tailcfg.go
+++ b/tailcfg/tailcfg.go
@@ -449,6 +449,7 @@ type MapRequest struct {
Compress string // "zstd" or "" (no compression)
KeepAlive bool // server sends keep-alives
NodeKey NodeKey
+ DiscoKey DiscoKey
Endpoints []string // caller's endpoints (IPv4 or IPv6)
IncludeIPv6 bool // include IPv6 endpoints in returned Node Endpoints
Stream bool // if true, multiple MapResponse objects are returned
diff --git a/types/key/key.go b/types/key/key.go
index cf29da9a5..5aeaa0f7c 100644
--- a/types/key/key.go
+++ b/types/key/key.go
@@ -6,9 +6,11 @@
package key
import (
+ crand "crypto/rand"
"encoding/base64"
"errors"
"fmt"
+ "io"
"go4.org/mem"
"golang.org/x/crypto/curve25519"
@@ -20,6 +22,15 @@ type Private [32]byte
// Private reports whether p is the zero value.
func (p Private) IsZero() bool { return p == Private{} }
+// NewPrivate returns a new private key.
+func NewPrivate() Private {
+ var p Private
+ if _, err := io.ReadFull(crand.Reader, p[:]); err != nil {
+ panic(err)
+ }
+ return p
+}
+
// B32 returns k as the *[32]byte type that's used by the
// golang.org/x/crypto packages. This allocates; it might
// not be appropriate for performance-sensitive paths.
diff --git a/wgengine/magicsock/magicsock.go b/wgengine/magicsock/magicsock.go
index 2c7eb7e36..5aba3bbbd 100644
--- a/wgengine/magicsock/magicsock.go
+++ b/wgengine/magicsock/magicsock.go
@@ -84,6 +84,8 @@ type Conn struct {
lastEndpoints []string
peerSet map[key.Public]struct{}
+ discoPrivate key.Private
+
// addrsByUDP is a map of every remote ip:port to a priority
// list of endpoint addresses for a peer.
// The priority list is provided by wgengine configuration.
@@ -476,6 +478,14 @@ func (c *Conn) SetNetInfoCallback(fn func(*tailcfg.NetInfo)) {
}
}
+// SetDiscoPrivateKey sets the discovery key.
+func (c *Conn) SetDiscoPrivateKey(k key.Private) {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+ c.discoPrivate = k
+ c.logf("magicsock: disco key set; public: %x", k.Public())
+}
+
// c.mu must NOT be held.
func (c *Conn) setNearestDERP(derpNum int) (wantDERP bool) {
c.mu.Lock()
diff --git a/wgengine/userspace.go b/wgengine/userspace.go
index 154cee057..c3b8b93f5 100644
--- a/wgengine/userspace.go
+++ b/wgengine/userspace.go
@@ -830,6 +830,10 @@ func (e *userspaceEngine) SetDERPMap(dm *tailcfg.DERPMap) {
e.magicConn.SetDERPMap(dm)
}
+func (e *userspaceEngine) SetDiscoPrivateKey(k key.Private) {
+ e.magicConn.SetDiscoPrivateKey(k)
+}
+
func (e *userspaceEngine) UpdateStatus(sb *ipnstate.StatusBuilder) {
st, err := e.getStatus()
if err != nil {
diff --git a/wgengine/watchdog.go b/wgengine/watchdog.go
index 70568e504..06e07a134 100644
--- a/wgengine/watchdog.go
+++ b/wgengine/watchdog.go
@@ -13,6 +13,7 @@ import (
"github.com/tailscale/wireguard-go/wgcfg"
"tailscale.com/ipn/ipnstate"
"tailscale.com/tailcfg"
+ "tailscale.com/types/key"
"tailscale.com/wgengine/filter"
"tailscale.com/wgengine/router"
"tailscale.com/wgengine/tsdns"
@@ -96,6 +97,9 @@ func (e *watchdogEngine) LinkChange(isExpensive bool) {
func (e *watchdogEngine) SetDERPMap(m *tailcfg.DERPMap) {
e.watchdog("SetDERPMap", func() { e.wrap.SetDERPMap(m) })
}
+func (e *watchdogEngine) SetDiscoPrivateKey(k key.Private) {
+ e.watchdog("SetDiscoPrivateKey", func() { e.wrap.SetDiscoPrivateKey(k) })
+}
func (e *watchdogEngine) Close() {
e.watchdog("Close", e.wrap.Close)
}
diff --git a/wgengine/wgengine.go b/wgengine/wgengine.go
index b583af2da..723067f7b 100644
--- a/wgengine/wgengine.go
+++ b/wgengine/wgengine.go
@@ -11,6 +11,7 @@ import (
"github.com/tailscale/wireguard-go/wgcfg"
"tailscale.com/ipn/ipnstate"
"tailscale.com/tailcfg"
+ "tailscale.com/types/key"
"tailscale.com/wgengine/filter"
"tailscale.com/wgengine/router"
"tailscale.com/wgengine/tsdns"
@@ -56,6 +57,7 @@ type Engine interface {
//
// This is called whenever the tailcontrol (control plane)
// sends an updated network map.
+
//
// The returned error is ErrNoChanges if no changes were made.
Reconfig(*wgcfg.Config, *router.Config) error
@@ -108,6 +110,10 @@ type Engine interface {
// new NetInfo summary is available.
SetNetInfoCallback(NetInfoCallback)
+ // SetDiscoPrivateKey sets the private key used for path discovery
+ // messages.
+ SetDiscoPrivateKey(key.Private)
+
// UpdateStatus populates the network state using the provided
// status builder.
UpdateStatus(*ipnstate.StatusBuilder)