Przeglądaj źródła

all: generate discovery key, plumb it around

Not actually used yet.

Updates #483
Brad Fitzpatrick 5 lat temu
rodzic
commit
53fb25fc2f

+ 4 - 0
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,

+ 5 - 0
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

+ 1 - 0
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

+ 11 - 0
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.

+ 10 - 0
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()

+ 4 - 0
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 {

+ 4 - 0
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)
 }

+ 6 - 0
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)