all: generate discovery key, plumb it around

Not actually used yet.

Updates #483
pull/492/head
Brad Fitzpatrick 4 years ago
parent 88c305c8af
commit 53fb25fc2f

@ -85,6 +85,7 @@ type Direct struct {
newDecompressor func() (Decompressor, error) newDecompressor func() (Decompressor, error)
keepAlive bool keepAlive bool
logf logger.Logf logf logger.Logf
discoPubKey tailcfg.DiscoKey
mu sync.Mutex // mutex guards the following fields mu sync.Mutex // mutex guards the following fields
serverKey wgcfg.Key serverKey wgcfg.Key
@ -104,6 +105,7 @@ type Options struct {
AuthKey string // optional node auth key for auto registration AuthKey string // optional node auth key for auto registration
TimeNow func() time.Time // time.Now implementation used by Client 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 Hostinfo *tailcfg.Hostinfo // non-nil passes ownership, nil means to use default using os.Hostname, etc
DiscoPublicKey tailcfg.DiscoKey
NewDecompressor func() (Decompressor, error) NewDecompressor func() (Decompressor, error)
KeepAlive bool KeepAlive bool
Logf logger.Logf Logf logger.Logf
@ -153,6 +155,7 @@ func NewDirect(opts Options) (*Direct, error) {
keepAlive: opts.KeepAlive, keepAlive: opts.KeepAlive,
persist: opts.Persist, persist: opts.Persist,
authKey: opts.AuthKey, authKey: opts.AuthKey,
discoPubKey: opts.DiscoPublicKey,
} }
if opts.Hostinfo == nil { if opts.Hostinfo == nil {
c.SetHostinfo(NewHostinfo()) c.SetHostinfo(NewHostinfo())
@ -478,6 +481,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
IncludeIPv6: includeIPv6(), IncludeIPv6: includeIPv6(),
KeepAlive: c.keepAlive, KeepAlive: c.keepAlive,
NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()), NodeKey: tailcfg.NodeKey(persist.PrivateNodeKey.Public()),
DiscoKey: c.discoPubKey,
Endpoints: ep, Endpoints: ep,
Stream: allowStream, Stream: allowStream,
Hostinfo: hostinfo, Hostinfo: hostinfo,

@ -358,6 +358,10 @@ func (b *LocalBackend) Start(opts Options) error {
b.updateFilter(nil) b.updateFilter(nil)
discoPrivate := key.NewPrivate()
b.e.SetDiscoPrivateKey(discoPrivate)
discoPublic := tailcfg.DiscoKey(discoPrivate.Public())
var err error var err error
if persist == nil { if persist == nil {
// let controlclient initialize it // let controlclient initialize it
@ -372,6 +376,7 @@ func (b *LocalBackend) Start(opts Options) error {
KeepAlive: true, KeepAlive: true,
NewDecompressor: b.newDecompressor, NewDecompressor: b.newDecompressor,
HTTPTestClient: opts.HTTPTestClient, HTTPTestClient: opts.HTTPTestClient,
DiscoPublicKey: discoPublic,
}) })
if err != nil { if err != nil {
return err return err

@ -449,6 +449,7 @@ type MapRequest struct {
Compress string // "zstd" or "" (no compression) Compress string // "zstd" or "" (no compression)
KeepAlive bool // server sends keep-alives KeepAlive bool // server sends keep-alives
NodeKey NodeKey NodeKey NodeKey
DiscoKey DiscoKey
Endpoints []string // caller's endpoints (IPv4 or IPv6) Endpoints []string // caller's endpoints (IPv4 or IPv6)
IncludeIPv6 bool // include IPv6 endpoints in returned Node Endpoints IncludeIPv6 bool // include IPv6 endpoints in returned Node Endpoints
Stream bool // if true, multiple MapResponse objects are returned Stream bool // if true, multiple MapResponse objects are returned

@ -6,9 +6,11 @@
package key package key
import ( import (
crand "crypto/rand"
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"io"
"go4.org/mem" "go4.org/mem"
"golang.org/x/crypto/curve25519" "golang.org/x/crypto/curve25519"
@ -20,6 +22,15 @@ type Private [32]byte
// Private reports whether p is the zero value. // Private reports whether p is the zero value.
func (p Private) IsZero() bool { return p == Private{} } 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 // B32 returns k as the *[32]byte type that's used by the
// golang.org/x/crypto packages. This allocates; it might // golang.org/x/crypto packages. This allocates; it might
// not be appropriate for performance-sensitive paths. // not be appropriate for performance-sensitive paths.

@ -84,6 +84,8 @@ type Conn struct {
lastEndpoints []string lastEndpoints []string
peerSet map[key.Public]struct{} peerSet map[key.Public]struct{}
discoPrivate key.Private
// addrsByUDP is a map of every remote ip:port to a priority // addrsByUDP is a map of every remote ip:port to a priority
// list of endpoint addresses for a peer. // list of endpoint addresses for a peer.
// The priority list is provided by wgengine configuration. // 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. // c.mu must NOT be held.
func (c *Conn) setNearestDERP(derpNum int) (wantDERP bool) { func (c *Conn) setNearestDERP(derpNum int) (wantDERP bool) {
c.mu.Lock() c.mu.Lock()

@ -830,6 +830,10 @@ func (e *userspaceEngine) SetDERPMap(dm *tailcfg.DERPMap) {
e.magicConn.SetDERPMap(dm) e.magicConn.SetDERPMap(dm)
} }
func (e *userspaceEngine) SetDiscoPrivateKey(k key.Private) {
e.magicConn.SetDiscoPrivateKey(k)
}
func (e *userspaceEngine) UpdateStatus(sb *ipnstate.StatusBuilder) { func (e *userspaceEngine) UpdateStatus(sb *ipnstate.StatusBuilder) {
st, err := e.getStatus() st, err := e.getStatus()
if err != nil { if err != nil {

@ -13,6 +13,7 @@ import (
"github.com/tailscale/wireguard-go/wgcfg" "github.com/tailscale/wireguard-go/wgcfg"
"tailscale.com/ipn/ipnstate" "tailscale.com/ipn/ipnstate"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/key"
"tailscale.com/wgengine/filter" "tailscale.com/wgengine/filter"
"tailscale.com/wgengine/router" "tailscale.com/wgengine/router"
"tailscale.com/wgengine/tsdns" "tailscale.com/wgengine/tsdns"
@ -96,6 +97,9 @@ func (e *watchdogEngine) LinkChange(isExpensive bool) {
func (e *watchdogEngine) SetDERPMap(m *tailcfg.DERPMap) { func (e *watchdogEngine) SetDERPMap(m *tailcfg.DERPMap) {
e.watchdog("SetDERPMap", func() { e.wrap.SetDERPMap(m) }) 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() { func (e *watchdogEngine) Close() {
e.watchdog("Close", e.wrap.Close) e.watchdog("Close", e.wrap.Close)
} }

@ -11,6 +11,7 @@ import (
"github.com/tailscale/wireguard-go/wgcfg" "github.com/tailscale/wireguard-go/wgcfg"
"tailscale.com/ipn/ipnstate" "tailscale.com/ipn/ipnstate"
"tailscale.com/tailcfg" "tailscale.com/tailcfg"
"tailscale.com/types/key"
"tailscale.com/wgengine/filter" "tailscale.com/wgengine/filter"
"tailscale.com/wgengine/router" "tailscale.com/wgengine/router"
"tailscale.com/wgengine/tsdns" "tailscale.com/wgengine/tsdns"
@ -56,6 +57,7 @@ type Engine interface {
// //
// This is called whenever the tailcontrol (control plane) // This is called whenever the tailcontrol (control plane)
// sends an updated network map. // sends an updated network map.
// //
// The returned error is ErrNoChanges if no changes were made. // The returned error is ErrNoChanges if no changes were made.
Reconfig(*wgcfg.Config, *router.Config) error Reconfig(*wgcfg.Config, *router.Config) error
@ -108,6 +110,10 @@ type Engine interface {
// new NetInfo summary is available. // new NetInfo summary is available.
SetNetInfoCallback(NetInfoCallback) SetNetInfoCallback(NetInfoCallback)
// SetDiscoPrivateKey sets the private key used for path discovery
// messages.
SetDiscoPrivateKey(key.Private)
// UpdateStatus populates the network state using the provided // UpdateStatus populates the network state using the provided
// status builder. // status builder.
UpdateStatus(*ipnstate.StatusBuilder) UpdateStatus(*ipnstate.StatusBuilder)

Loading…
Cancel
Save