mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
wgkey: new package
This is a replacement for the key-related parts of the wireguard-go wgcfg package. This is almost a straight copy/paste from the wgcfg package. I have slightly changed some of the exported functions and types to avoid stutter, added and tweaked some comments, and removed some now-unused code. To avoid having wireguard-go depend on this new package, wgcfg will keep its key types. We translate into and out of those types at the last minute. These few remaining uses will be eliminated alongside the rest of the wgcfg package. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
parent
13b554fed9
commit
56a7652dc9
@ -25,7 +25,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tailscale/wireguard-go/wgcfg"
|
|
||||||
"golang.org/x/crypto/acme/autocert"
|
"golang.org/x/crypto/acme/autocert"
|
||||||
"tailscale.com/atomicfile"
|
"tailscale.com/atomicfile"
|
||||||
"tailscale.com/derp"
|
"tailscale.com/derp"
|
||||||
@ -35,6 +34,7 @@ import (
|
|||||||
"tailscale.com/net/stun"
|
"tailscale.com/net/stun"
|
||||||
"tailscale.com/tsweb"
|
"tailscale.com/tsweb"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
PrivateKey wgcfg.PrivateKey
|
PrivateKey wgkey.Private
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfig() config {
|
func loadConfig() config {
|
||||||
@ -77,8 +77,8 @@ func loadConfig() config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustNewKey() wgcfg.PrivateKey {
|
func mustNewKey() wgkey.Private {
|
||||||
key, err := wgcfg.NewPrivateKey()
|
key, err := wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
tailscale.com/types/opt from tailscale.com/control/controlclient+
|
tailscale.com/types/opt from tailscale.com/control/controlclient+
|
||||||
tailscale.com/types/strbuilder from tailscale.com/net/packet
|
tailscale.com/types/strbuilder from tailscale.com/net/packet
|
||||||
tailscale.com/types/structs from tailscale.com/control/controlclient+
|
tailscale.com/types/structs from tailscale.com/control/controlclient+
|
||||||
|
tailscale.com/types/wgkey from tailscale.com/control/controlclient+
|
||||||
LW tailscale.com/util/endian from tailscale.com/net/netns+
|
LW tailscale.com/util/endian from tailscale.com/net/netns+
|
||||||
tailscale.com/util/lineread from tailscale.com/control/controlclient+
|
tailscale.com/util/lineread from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/systemd from tailscale.com/control/controlclient+
|
tailscale.com/util/systemd from tailscale.com/control/controlclient+
|
||||||
|
@ -81,6 +81,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/types/opt from tailscale.com/control/controlclient+
|
tailscale.com/types/opt from tailscale.com/control/controlclient+
|
||||||
tailscale.com/types/strbuilder from tailscale.com/net/packet
|
tailscale.com/types/strbuilder from tailscale.com/net/packet
|
||||||
tailscale.com/types/structs from tailscale.com/control/controlclient+
|
tailscale.com/types/structs from tailscale.com/control/controlclient+
|
||||||
|
tailscale.com/types/wgkey from tailscale.com/control/controlclient+
|
||||||
LW tailscale.com/util/endian from tailscale.com/net/netns+
|
LW tailscale.com/util/endian from tailscale.com/net/netns+
|
||||||
tailscale.com/util/lineread from tailscale.com/control/controlclient+
|
tailscale.com/util/lineread from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver
|
tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver
|
||||||
|
@ -17,13 +17,13 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tailscale/wireguard-go/wgcfg"
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"tailscale.com/logtail/backoff"
|
"tailscale.com/logtail/backoff"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/empty"
|
"tailscale.com/types/empty"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/structs"
|
"tailscale.com/types/structs"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
// State is the high-level state of the client. It is used only in
|
// State is the high-level state of the client. It is used only in
|
||||||
@ -665,7 +665,7 @@ func (c *Client) Shutdown() {
|
|||||||
|
|
||||||
// NodePublicKey returns the node public key currently in use. This is
|
// NodePublicKey returns the node public key currently in use. This is
|
||||||
// used exclusively in tests.
|
// used exclusively in tests.
|
||||||
func (c *Client) TestOnlyNodePublicKey() wgcfg.Key {
|
func (c *Client) TestOnlyNodePublicKey() wgkey.Key {
|
||||||
priv := c.direct.GetPersist()
|
priv := c.direct.GetPersist()
|
||||||
return priv.PrivateNodeKey.Public()
|
return priv.PrivateNodeKey.Public()
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tailscale/wireguard-go/wgcfg"
|
|
||||||
"golang.org/x/crypto/nacl/box"
|
"golang.org/x/crypto/nacl/box"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
@ -44,6 +43,7 @@ import (
|
|||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/opt"
|
"tailscale.com/types/opt"
|
||||||
"tailscale.com/types/structs"
|
"tailscale.com/types/structs"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/util/systemd"
|
"tailscale.com/util/systemd"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
@ -61,10 +61,10 @@ type Persist struct {
|
|||||||
// needed. This field should be considered read-only from GUI
|
// needed. This field should be considered read-only from GUI
|
||||||
// frontends. The real value should not be written back in
|
// frontends. The real value should not be written back in
|
||||||
// this field, lest the frontend persist it to disk.
|
// this field, lest the frontend persist it to disk.
|
||||||
LegacyFrontendPrivateMachineKey wgcfg.PrivateKey `json:"PrivateMachineKey"`
|
LegacyFrontendPrivateMachineKey wgkey.Private `json:"PrivateMachineKey"`
|
||||||
|
|
||||||
PrivateNodeKey wgcfg.PrivateKey
|
PrivateNodeKey wgkey.Private
|
||||||
OldPrivateNodeKey wgcfg.PrivateKey // needed to request key rotation
|
OldPrivateNodeKey wgkey.Private // needed to request key rotation
|
||||||
Provider string
|
Provider string
|
||||||
LoginName string
|
LoginName string
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ func (p *Persist) Equals(p2 *Persist) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Persist) Pretty() string {
|
func (p *Persist) Pretty() string {
|
||||||
var mk, ok, nk wgcfg.Key
|
var mk, ok, nk wgkey.Key
|
||||||
if !p.LegacyFrontendPrivateMachineKey.IsZero() {
|
if !p.LegacyFrontendPrivateMachineKey.IsZero() {
|
||||||
mk = p.LegacyFrontendPrivateMachineKey.Public()
|
mk = p.LegacyFrontendPrivateMachineKey.Public()
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ func (p *Persist) Pretty() string {
|
|||||||
if !p.PrivateNodeKey.IsZero() {
|
if !p.PrivateNodeKey.IsZero() {
|
||||||
nk = p.PrivateNodeKey.Public()
|
nk = p.PrivateNodeKey.Public()
|
||||||
}
|
}
|
||||||
ss := func(k wgcfg.Key) string {
|
ss := func(k wgkey.Key) string {
|
||||||
if k.IsZero() {
|
if k.IsZero() {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -115,14 +115,14 @@ type Direct struct {
|
|||||||
keepAlive bool
|
keepAlive bool
|
||||||
logf logger.Logf
|
logf logger.Logf
|
||||||
discoPubKey tailcfg.DiscoKey
|
discoPubKey tailcfg.DiscoKey
|
||||||
machinePrivKey wgcfg.PrivateKey
|
machinePrivKey wgkey.Private
|
||||||
debugFlags []string
|
debugFlags []string
|
||||||
|
|
||||||
mu sync.Mutex // mutex guards the following fields
|
mu sync.Mutex // mutex guards the following fields
|
||||||
serverKey wgcfg.Key
|
serverKey wgkey.Key
|
||||||
persist Persist
|
persist Persist
|
||||||
authKey string
|
authKey string
|
||||||
tryingNewKey wgcfg.PrivateKey
|
tryingNewKey wgkey.Private
|
||||||
expiry *time.Time
|
expiry *time.Time
|
||||||
// hostinfo is mutated in-place while mu is held.
|
// hostinfo is mutated in-place while mu is held.
|
||||||
hostinfo *tailcfg.Hostinfo // always non-nil
|
hostinfo *tailcfg.Hostinfo // always non-nil
|
||||||
@ -133,7 +133,7 @@ type Direct struct {
|
|||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Persist Persist // initial persistent data
|
Persist Persist // initial persistent data
|
||||||
MachinePrivateKey wgcfg.PrivateKey // the machine key to use
|
MachinePrivateKey wgkey.Private // the machine key to use
|
||||||
ServerURL string // URL of the tailcontrol server
|
ServerURL string // URL of the tailcontrol server
|
||||||
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
|
||||||
@ -340,7 +340,7 @@ func (c *Direct) doLogin(ctx context.Context, t *oauth2.Token, flags LoginFlags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
c.logf("doLogin(regen=%v, hasUrl=%v)", regen, url != "")
|
c.logf("doLogin(regen=%v, hasUrl=%v)", regen, url != "")
|
||||||
if serverKey == (wgcfg.Key{}) {
|
if serverKey.IsZero() {
|
||||||
var err error
|
var err error
|
||||||
serverKey, err = loadServerKey(ctx, c.httpc, c.serverURL)
|
serverKey, err = loadServerKey(ctx, c.httpc, c.serverURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -352,12 +352,12 @@ func (c *Direct) doLogin(ctx context.Context, t *oauth2.Token, flags LoginFlags,
|
|||||||
c.mu.Unlock()
|
c.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
var oldNodeKey wgcfg.Key
|
var oldNodeKey wgkey.Key
|
||||||
if url != "" {
|
if url != "" {
|
||||||
} else if regen || persist.PrivateNodeKey.IsZero() {
|
} else if regen || persist.PrivateNodeKey.IsZero() {
|
||||||
c.logf("Generating a new nodekey.")
|
c.logf("Generating a new nodekey.")
|
||||||
persist.OldPrivateNodeKey = persist.PrivateNodeKey
|
persist.OldPrivateNodeKey = persist.PrivateNodeKey
|
||||||
key, err := wgcfg.NewPrivateKey()
|
key, err := wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logf("login keygen: %v", err)
|
c.logf("login keygen: %v", err)
|
||||||
return regen, url, err
|
return regen, url, err
|
||||||
@ -793,7 +793,7 @@ func (c *Direct) PollNetMap(ctx context.Context, maxPolls int, cb func(*NetworkM
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decode(res *http.Response, v interface{}, serverKey *wgcfg.Key, mkey *wgcfg.PrivateKey) error {
|
func decode(res *http.Response, v interface{}, serverKey *wgkey.Key, mkey *wgkey.Private) error {
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
msg, err := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20))
|
msg, err := ioutil.ReadAll(io.LimitReader(res.Body, 1<<20))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -848,7 +848,7 @@ func (c *Direct) decodeMsg(msg []byte, v interface{}) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeMsg(msg []byte, v interface{}, serverKey *wgcfg.Key, mkey *wgcfg.PrivateKey) error {
|
func decodeMsg(msg []byte, v interface{}, serverKey *wgkey.Key, mkey *wgkey.Private) error {
|
||||||
decrypted, err := decryptMsg(msg, serverKey, mkey)
|
decrypted, err := decryptMsg(msg, serverKey, mkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -862,7 +862,7 @@ func decodeMsg(msg []byte, v interface{}, serverKey *wgcfg.Key, mkey *wgcfg.Priv
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func decryptMsg(msg []byte, serverKey *wgcfg.Key, mkey *wgcfg.PrivateKey) ([]byte, error) {
|
func decryptMsg(msg []byte, serverKey *wgkey.Key, mkey *wgkey.Private) ([]byte, error) {
|
||||||
var nonce [24]byte
|
var nonce [24]byte
|
||||||
if len(msg) < len(nonce)+1 {
|
if len(msg) < len(nonce)+1 {
|
||||||
return nil, fmt.Errorf("response missing nonce, len=%d", len(msg))
|
return nil, fmt.Errorf("response missing nonce, len=%d", len(msg))
|
||||||
@ -878,7 +878,7 @@ func decryptMsg(msg []byte, serverKey *wgcfg.Key, mkey *wgcfg.PrivateKey) ([]byt
|
|||||||
return decrypted, nil
|
return decrypted, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(v interface{}, serverKey *wgcfg.Key, mkey *wgcfg.PrivateKey) ([]byte, error) {
|
func encode(v interface{}, serverKey *wgkey.Key, mkey *wgkey.Private) ([]byte, error) {
|
||||||
b, err := json.Marshal(v)
|
b, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -897,27 +897,27 @@ func encode(v interface{}, serverKey *wgcfg.Key, mkey *wgcfg.PrivateKey) ([]byte
|
|||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadServerKey(ctx context.Context, httpc *http.Client, serverURL string) (wgcfg.Key, error) {
|
func loadServerKey(ctx context.Context, httpc *http.Client, serverURL string) (wgkey.Key, error) {
|
||||||
req, err := http.NewRequest("GET", serverURL+"/key", nil)
|
req, err := http.NewRequest("GET", serverURL+"/key", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wgcfg.Key{}, fmt.Errorf("create control key request: %v", err)
|
return wgkey.Key{}, fmt.Errorf("create control key request: %v", err)
|
||||||
}
|
}
|
||||||
req = req.WithContext(ctx)
|
req = req.WithContext(ctx)
|
||||||
res, err := httpc.Do(req)
|
res, err := httpc.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wgcfg.Key{}, fmt.Errorf("fetch control key: %v", err)
|
return wgkey.Key{}, fmt.Errorf("fetch control key: %v", err)
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
b, err := ioutil.ReadAll(io.LimitReader(res.Body, 1<<16))
|
b, err := ioutil.ReadAll(io.LimitReader(res.Body, 1<<16))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wgcfg.Key{}, fmt.Errorf("fetch control key response: %v", err)
|
return wgkey.Key{}, fmt.Errorf("fetch control key response: %v", err)
|
||||||
}
|
}
|
||||||
if res.StatusCode != 200 {
|
if res.StatusCode != 200 {
|
||||||
return wgcfg.Key{}, fmt.Errorf("fetch control key: %d: %s", res.StatusCode, string(b))
|
return wgkey.Key{}, fmt.Errorf("fetch control key: %d: %s", res.StatusCode, string(b))
|
||||||
}
|
}
|
||||||
key, err := wgcfg.ParseHexKey(string(b))
|
key, err := wgkey.ParseHex(string(b))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return wgcfg.Key{}, fmt.Errorf("fetch control key: %v", err)
|
return wgkey.Key{}, fmt.Errorf("fetch control key: %v", err)
|
||||||
}
|
}
|
||||||
return key, nil
|
return key, nil
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,7 +25,7 @@ type NetworkMap struct {
|
|||||||
// Core networking
|
// Core networking
|
||||||
|
|
||||||
NodeKey tailcfg.NodeKey
|
NodeKey tailcfg.NodeKey
|
||||||
PrivateKey wgcfg.PrivateKey
|
PrivateKey wgkey.Private
|
||||||
Expiry time.Time
|
Expiry time.Time
|
||||||
// Name is the DNS name assigned to this node.
|
// Name is the DNS name assigned to this node.
|
||||||
Name string
|
Name string
|
||||||
@ -241,7 +242,7 @@ const EndpointDiscoSuffix = ".disco.tailscale:12345"
|
|||||||
func (nm *NetworkMap) WGCfg(logf logger.Logf, flags WGConfigFlags) (*wgcfg.Config, error) {
|
func (nm *NetworkMap) WGCfg(logf logger.Logf, flags WGConfigFlags) (*wgcfg.Config, error) {
|
||||||
cfg := &wgcfg.Config{
|
cfg := &wgcfg.Config{
|
||||||
Name: "tailscale",
|
Name: "tailscale",
|
||||||
PrivateKey: nm.PrivateKey,
|
PrivateKey: wgcfg.PrivateKey(nm.PrivateKey),
|
||||||
Addresses: nm.Addresses,
|
Addresses: nm.Addresses,
|
||||||
ListenPort: nm.LocalPort,
|
ListenPort: nm.LocalPort,
|
||||||
Peers: make([]wgcfg.Peer, 0, len(nm.Peers)),
|
Peers: make([]wgcfg.Peer, 0, len(nm.Peers)),
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tailscale/wireguard-go/wgcfg"
|
"tailscale.com/types/wgkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestPersistEqual(t *testing.T) {
|
func TestPersistEqual(t *testing.T) {
|
||||||
@ -18,8 +18,8 @@ func TestPersistEqual(t *testing.T) {
|
|||||||
have, persistHandles)
|
have, persistHandles)
|
||||||
}
|
}
|
||||||
|
|
||||||
newPrivate := func() wgcfg.PrivateKey {
|
newPrivate := func() wgkey.Private {
|
||||||
k, err := wgcfg.NewPrivateKey()
|
k, err := wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
28
go.sum
28
go.sum
@ -68,7 +68,9 @@ github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
|||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/lxn/walk v0.0.0-20191128110447-55ccb3a9f5c1/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
||||||
github.com/lxn/walk v0.0.0-20201110160827-18ea5e372cdb/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
github.com/lxn/walk v0.0.0-20201110160827-18ea5e372cdb/go.mod h1:E23UucZGqpuUANJooIbHWCufXvOcT6E7Stq81gU+CSQ=
|
||||||
|
github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4/go.mod h1:ouWl4wViUNh8tPSIwxTVMuS014WakR1hqvBc2I0bMoA=
|
||||||
github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
github.com/lxn/win v0.0.0-20201111105847-2a20daff6a55/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
|
||||||
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
|
github.com/mattn/go-zglob v0.0.1 h1:xsEx/XUoVlI6yXjqBK062zYhRTZltCNmYPx6v+8DNaY=
|
||||||
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
|
||||||
@ -104,6 +106,7 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/tailscale/depaware v0.0.0-20201003033024-5d95aab075be/go.mod h1:jissDaJNHiyV2tFdr3QyNEfsZrax/i2yQiSO+CljThI=
|
||||||
github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027 h1:lK99QQdH3yBWY6aGilF+IRlQIdmhzLrsEmF6JgN+Ryw=
|
github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027 h1:lK99QQdH3yBWY6aGilF+IRlQIdmhzLrsEmF6JgN+Ryw=
|
||||||
github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
|
github.com/tailscale/depaware v0.0.0-20201214215404-77d1e9757027/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
|
||||||
github.com/tailscale/wireguard-go v0.0.0-20201220011020-db78fad0bebf h1:HuBwLWbDNIh/G72KSImSEx+dnd7FPGFI1e60LMJtLjU=
|
github.com/tailscale/wireguard-go v0.0.0-20201220011020-db78fad0bebf h1:HuBwLWbDNIh/G72KSImSEx+dnd7FPGFI1e60LMJtLjU=
|
||||||
@ -124,6 +127,7 @@ go4.org/intern v0.0.0-20201223054237-ef8cbcb8edd7 h1:yeDrXaQ3VRXbTN7lHj70DxW4LdP
|
|||||||
go4.org/intern v0.0.0-20201223054237-ef8cbcb8edd7/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
|
go4.org/intern v0.0.0-20201223054237-ef8cbcb8edd7/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
|
||||||
go4.org/intern v0.0.0-20201223061701-969c7e87e7cb h1:yuqO0E4bHRsTPUocDpRKXfLE40lwWplVxENQ2WOV7Gc=
|
go4.org/intern v0.0.0-20201223061701-969c7e87e7cb h1:yuqO0E4bHRsTPUocDpRKXfLE40lwWplVxENQ2WOV7Gc=
|
||||||
go4.org/intern v0.0.0-20201223061701-969c7e87e7cb/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
|
go4.org/intern v0.0.0-20201223061701-969c7e87e7cb/go.mod h1:vLqJ+12kCw61iCWsPto0EOHhBS+o4rO5VIucbc9g2Cc=
|
||||||
|
go4.org/mem v0.0.0-20200706164138-185c595c3ecc/go.mod h1:NEYvpHWemiG/E5UWfaN5QAIGZeT1sa0Z2UNk6oeMb/k=
|
||||||
go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 h1:vSug/WNOi2+4jrKdivxayTN/zd8EA1UrStjpWvvo1jk=
|
go4.org/mem v0.0.0-20201119185036-c04c5a6ff174 h1:vSug/WNOi2+4jrKdivxayTN/zd8EA1UrStjpWvvo1jk=
|
||||||
go4.org/mem v0.0.0-20201119185036-c04c5a6ff174/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
|
go4.org/mem v0.0.0-20201119185036-c04c5a6ff174/go.mod h1:reUoABIJ9ikfM5sgtSF3Wushcza7+WeD01VB9Lirh3g=
|
||||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e h1:ExUmGi0ZsQmiVo9giDQqXkr7vreeXPMkOGIusfsfbzI=
|
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e h1:ExUmGi0ZsQmiVo9giDQqXkr7vreeXPMkOGIusfsfbzI=
|
||||||
@ -131,13 +135,17 @@ go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222175341-b30ae309168e/go.mod h1:
|
|||||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 h1:1tk03FUNpulq2cuWpXZWj649rwJpk0d20rxWiopKRmc=
|
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063 h1:1tk03FUNpulq2cuWpXZWj649rwJpk0d20rxWiopKRmc=
|
||||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
|
go4.org/unsafe/assume-no-moving-gc v0.0.0-20201222180813-1025295fd063/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc=
|
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392 h1:xYJJ3S178yv++9zXV/hnr29plCAGO9vAFG9dorqaFQc=
|
||||||
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
@ -153,6 +161,9 @@ golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
@ -165,6 +176,7 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr
|
|||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -173,10 +185,15 @@ golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200812155832-6a926be9bd1d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -192,6 +209,7 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
|
|||||||
golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b h1:a0ErnNnPKmhDyIXQvdZr+Lq8dc8xpMeqkF8y5PgQU4Q=
|
golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b h1:a0ErnNnPKmhDyIXQvdZr+Lq8dc8xpMeqkF8y5PgQU4Q=
|
||||||
golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201207232118-ee85cb95a76b/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
@ -199,8 +217,11 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqG
|
|||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200609164405-eb789aa7ce50/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200609164405-eb789aa7ce50/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20201001230009-b5b87423c93b/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
|
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag=
|
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag=
|
||||||
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -208,7 +229,11 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
|||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.zx2c4.com/wireguard v0.0.20200321-0.20200715051853-507f148e1c42/go.mod h1:GJvYs5O24/ASlwPiRklVnjMx2xQzrOic0DuU6GvYJL4=
|
||||||
|
golang.zx2c4.com/wireguard v0.0.20200321-0.20201111175144-60b3766b89b9 h1:qowcZ56hhpeoESmWzI4Exhx4Y78TpCyXUJur4/c0CoE=
|
||||||
golang.zx2c4.com/wireguard v0.0.20200321-0.20201111175144-60b3766b89b9/go.mod h1:LMeNfjlcPZTrBC1juwgbQyA4Zy2XVcsrdO/fIJxwyuA=
|
golang.zx2c4.com/wireguard v0.0.20200321-0.20201111175144-60b3766b89b9/go.mod h1:LMeNfjlcPZTrBC1juwgbQyA4Zy2XVcsrdO/fIJxwyuA=
|
||||||
|
golang.zx2c4.com/wireguard/windows v0.1.2-0.20201004085714-dd60d0447f81/go.mod h1:GaK5zcgr5XE98WaRzIDilumDBp5/yP8j2kG/LCDnvAM=
|
||||||
|
golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8 h1:nlXPqGA98n+qcq1pwZ28KjM5EsFQvamKS00A+VUeVjs=
|
||||||
golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8/go.mod h1:psva4yDnAHLuh7lUzOK7J7bLYxNFfo0iKWz+mi9gzkA=
|
golang.zx2c4.com/wireguard/windows v0.1.2-0.20201113162609-9b85be97fdf8/go.mod h1:psva4yDnAHLuh7lUzOK7J7bLYxNFfo0iKWz+mi9gzkA=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@ -219,8 +244,10 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
honnef.co/go/tools v0.1.0 h1:AWNL1W1i7f0wNZ8VwOKNJ0sliKvOF/adn0EHenfUh+c=
|
honnef.co/go/tools v0.1.0 h1:AWNL1W1i7f0wNZ8VwOKNJ0sliKvOF/adn0EHenfUh+c=
|
||||||
honnef.co/go/tools v0.1.0/go.mod h1:XtegFAyX/PfluP4921rXU5IkjkqBCDnUq4W8VCIoKvM=
|
honnef.co/go/tools v0.1.0/go.mod h1:XtegFAyX/PfluP4921rXU5IkjkqBCDnUq4W8VCIoKvM=
|
||||||
|
inet.af/netaddr v0.0.0-20200810144936-56928fe48a98/go.mod h1:qqYzz/2whtrbWJvt+DNWQyvekNN4ePQZcg2xc2/Yjww=
|
||||||
inet.af/netaddr v0.0.0-20201218162718-658fec415e52/go.mod h1:qqYzz/2whtrbWJvt+DNWQyvekNN4ePQZcg2xc2/Yjww=
|
inet.af/netaddr v0.0.0-20201218162718-658fec415e52/go.mod h1:qqYzz/2whtrbWJvt+DNWQyvekNN4ePQZcg2xc2/Yjww=
|
||||||
inet.af/netaddr v0.0.0-20201223185330-97d366981fac h1:aqMW8vft7VmOIhtQhsTWhAuZzOBGYBv+Otyvwj+VGSU=
|
inet.af/netaddr v0.0.0-20201223185330-97d366981fac h1:aqMW8vft7VmOIhtQhsTWhAuZzOBGYBv+Otyvwj+VGSU=
|
||||||
inet.af/netaddr v0.0.0-20201223185330-97d366981fac/go.mod h1:9NdhtHLglxJliAZB6aC5ws3mfnUArdAzHG/iJq7cB/o=
|
inet.af/netaddr v0.0.0-20201223185330-97d366981fac/go.mod h1:9NdhtHLglxJliAZB6aC5ws3mfnUArdAzHG/iJq7cB/o=
|
||||||
@ -232,3 +259,4 @@ inet.af/netaddr v0.0.0-20201228234250-33d0a924ebbf h1:0eHZ8v6j5wIiOVyoYPd70ueZ/R
|
|||||||
inet.af/netaddr v0.0.0-20201228234250-33d0a924ebbf/go.mod h1:9NdhtHLglxJliAZB6aC5ws3mfnUArdAzHG/iJq7cB/o=
|
inet.af/netaddr v0.0.0-20201228234250-33d0a924ebbf/go.mod h1:9NdhtHLglxJliAZB6aC5ws3mfnUArdAzHG/iJq7cB/o=
|
||||||
rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w=
|
rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w=
|
||||||
rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
|
rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
|
||||||
|
tailscale.com v1.2.10/go.mod h1:JEJiCce3MHtPCTdX2ahLc4tcnxZ7b5etish1Yt0B6+w=
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"tailscale.com/types/empty"
|
"tailscale.com/types/empty"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/util/systemd"
|
"tailscale.com/util/systemd"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
"tailscale.com/wgengine"
|
"tailscale.com/wgengine"
|
||||||
@ -83,7 +84,7 @@ type LocalBackend struct {
|
|||||||
userID string // current controlling user ID (for Windows, primarily)
|
userID string // current controlling user ID (for Windows, primarily)
|
||||||
prefs *Prefs
|
prefs *Prefs
|
||||||
inServerMode bool
|
inServerMode bool
|
||||||
machinePrivKey wgcfg.PrivateKey
|
machinePrivKey wgkey.Private
|
||||||
state State
|
state State
|
||||||
// hostinfo is mutated in-place while mu is held.
|
// hostinfo is mutated in-place while mu is held.
|
||||||
hostinfo *tailcfg.Hostinfo
|
hostinfo *tailcfg.Hostinfo
|
||||||
@ -737,7 +738,7 @@ func (b *LocalBackend) initMachineKeyLocked() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var legacyMachineKey wgcfg.PrivateKey
|
var legacyMachineKey wgkey.Private
|
||||||
if b.prefs.Persist != nil {
|
if b.prefs.Persist != nil {
|
||||||
legacyMachineKey = b.prefs.Persist.LegacyFrontendPrivateMachineKey
|
legacyMachineKey = b.prefs.Persist.LegacyFrontendPrivateMachineKey
|
||||||
}
|
}
|
||||||
@ -772,7 +773,7 @@ func (b *LocalBackend) initMachineKeyLocked() (err error) {
|
|||||||
} else {
|
} else {
|
||||||
b.logf("generating new machine key")
|
b.logf("generating new machine key")
|
||||||
var err error
|
var err error
|
||||||
b.machinePrivKey, err = wgcfg.NewPrivateKey()
|
b.machinePrivKey, err = wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("initializing new machine key: %w", err)
|
return fmt.Errorf("initializing new machine key: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,10 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tailscale/wireguard-go/wgcfg"
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
"tailscale.com/control/controlclient"
|
"tailscale.com/control/controlclient"
|
||||||
"tailscale.com/tstest"
|
"tailscale.com/tstest"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/wgengine/router"
|
"tailscale.com/wgengine/router"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -348,7 +348,7 @@ func TestPrefsPretty(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Prefs{
|
Prefs{
|
||||||
Persist: &controlclient.Persist{
|
Persist: &controlclient.Persist{
|
||||||
PrivateNodeKey: wgcfg.PrivateKey{1: 1},
|
PrivateNodeKey: wgkey.Private{1: 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"linux",
|
"linux",
|
||||||
|
@ -24,7 +24,7 @@ var ErrStateNotExist = errors.New("no state with given ID")
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// MachineKeyStateKey is the key under which we store the machine key,
|
// MachineKeyStateKey is the key under which we store the machine key,
|
||||||
// in its wgcfg.PrivateKey.MarshalText representation.
|
// in its wgkey.Private.MarshalText representation.
|
||||||
MachineKeyStateKey = StateKey("_machinekey")
|
MachineKeyStateKey = StateKey("_machinekey")
|
||||||
|
|
||||||
// GlobalDaemonStateKey is the ipn.StateKey that tailscaled
|
// GlobalDaemonStateKey is the ipn.StateKey that tailscaled
|
||||||
|
@ -11,8 +11,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tailscale/wireguard-go/wgcfg"
|
|
||||||
"inet.af/netaddr"
|
"inet.af/netaddr"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
func fieldsOf(t reflect.Type) (fields []string) {
|
func fieldsOf(t reflect.Type) (fields []string) {
|
||||||
@ -194,9 +194,9 @@ func TestNodeEqual(t *testing.T) {
|
|||||||
have, nodeHandles)
|
have, nodeHandles)
|
||||||
}
|
}
|
||||||
|
|
||||||
newPublicKey := func(t *testing.T) wgcfg.Key {
|
newPublicKey := func(t *testing.T) wgkey.Key {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
k, err := wgcfg.NewPrivateKey()
|
k, err := wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ package key
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/tailscale/wireguard-go/wgcfg"
|
"tailscale.com/types/wgkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestTextUnmarshal(t *testing.T) {
|
func TestTextUnmarshal(t *testing.T) {
|
||||||
@ -28,10 +28,10 @@ func TestTextUnmarshal(t *testing.T) {
|
|||||||
func TestClamping(t *testing.T) {
|
func TestClamping(t *testing.T) {
|
||||||
t.Run("NewPrivate", func(t *testing.T) { testClamping(t, NewPrivate) })
|
t.Run("NewPrivate", func(t *testing.T) { testClamping(t, NewPrivate) })
|
||||||
|
|
||||||
// Also test the wgcfg package, as their behavior should match.
|
// Also test the wgkey package, as their behavior should match.
|
||||||
t.Run("wgcfg", func(t *testing.T) {
|
t.Run("wgkey", func(t *testing.T) {
|
||||||
testClamping(t, func() Private {
|
testClamping(t, func() Private {
|
||||||
k, err := wgcfg.NewPrivateKey()
|
k, err := wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
241
types/wgkey/key.go
Normal file
241
types/wgkey/key.go
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package wgkey contains types and helpers for WireGuard keys.
|
||||||
|
// It is very similar to package tailscale.com/types/key,
|
||||||
|
// which is also used for curve25519 keys.
|
||||||
|
// These keys are used for WireGuard clients;
|
||||||
|
// those keys are used in other curve25519 clients.
|
||||||
|
package wgkey
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/subtle"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
|
"golang.org/x/crypto/curve25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Size is the number of bytes in a curve25519 key.
|
||||||
|
const Size = 32
|
||||||
|
|
||||||
|
// A Key is a curve25519 key.
|
||||||
|
// It is used by WireGuard to represent public keys.
|
||||||
|
type Key [Size]byte
|
||||||
|
|
||||||
|
// NewPreshared generates a new random Key.
|
||||||
|
func NewPreshared() (*Key, error) {
|
||||||
|
var k [Size]byte
|
||||||
|
_, err := rand.Read(k[:])
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return (*Key)(&k), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(b64 string) (*Key, error) { return parseBase64(base64.StdEncoding, b64) }
|
||||||
|
|
||||||
|
func ParseHex(s string) (Key, error) {
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return Key{}, fmt.Errorf("invalid hex key (%q): %w", s, err)
|
||||||
|
}
|
||||||
|
if len(b) != Size {
|
||||||
|
return Key{}, fmt.Errorf("invalid hex key (%q): length=%d, want %d", s, len(b), Size)
|
||||||
|
}
|
||||||
|
|
||||||
|
var key Key
|
||||||
|
copy(key[:], b)
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePrivateHex(v string) (Private, error) {
|
||||||
|
k, err := ParseHex(v)
|
||||||
|
if err != nil {
|
||||||
|
return Private{}, err
|
||||||
|
}
|
||||||
|
pk := Private(k)
|
||||||
|
if pk.IsZero() {
|
||||||
|
// Do not clamp a zero key, pass the zero through
|
||||||
|
// (much like NaN propagation) so that IsZero reports
|
||||||
|
// a useful result.
|
||||||
|
return pk, nil
|
||||||
|
}
|
||||||
|
pk.clamp()
|
||||||
|
return pk, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Key) Base64() string { return base64.StdEncoding.EncodeToString(k[:]) }
|
||||||
|
func (k Key) String() string { return k.ShortString() }
|
||||||
|
func (k Key) HexString() string { return hex.EncodeToString(k[:]) }
|
||||||
|
func (k Key) Equal(k2 Key) bool { return subtle.ConstantTimeCompare(k[:], k2[:]) == 1 }
|
||||||
|
|
||||||
|
func (k *Key) ShortString() string {
|
||||||
|
long := k.Base64()
|
||||||
|
return "[" + long[0:5] + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) IsZero() bool {
|
||||||
|
if k == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
var zeros Key
|
||||||
|
return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) MarshalJSON() ([]byte, error) {
|
||||||
|
if k == nil {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
// TODO(josharian): use encoding/hex instead?
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
fmt.Fprintf(buf, `"%x"`, k[:])
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Key) UnmarshalJSON(b []byte) error {
|
||||||
|
if k == nil {
|
||||||
|
return errors.New("wgkey.Key: UnmarshalJSON on nil pointer")
|
||||||
|
}
|
||||||
|
if len(b) < 3 || b[0] != '"' || b[len(b)-1] != '"' {
|
||||||
|
return errors.New("wgkey.Key: UnmarshalJSON not given a string")
|
||||||
|
}
|
||||||
|
b = b[1 : len(b)-1]
|
||||||
|
key, err := ParseHex(string(b))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("wgkey.Key: UnmarshalJSON: %v", err)
|
||||||
|
}
|
||||||
|
copy(k[:], key[:])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Key) LessThan(b *Key) bool {
|
||||||
|
for i := range a {
|
||||||
|
if a[i] < b[i] {
|
||||||
|
return true
|
||||||
|
} else if a[i] > b[i] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// A Private is a curve25519 key.
|
||||||
|
// It is used by WireGuard to represent private keys.
|
||||||
|
type Private [Size]byte
|
||||||
|
|
||||||
|
// NewPrivate generates a new curve25519 secret key.
|
||||||
|
// It conforms to the format described on https://cr.yp.to/ecdh.html.
|
||||||
|
func NewPrivate() (Private, error) {
|
||||||
|
k, err := NewPreshared()
|
||||||
|
if err != nil {
|
||||||
|
return Private{}, err
|
||||||
|
}
|
||||||
|
k[0] &= 248
|
||||||
|
k[31] = (k[31] & 127) | 64
|
||||||
|
return (Private)(*k), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParsePrivate(b64 string) (*Private, error) {
|
||||||
|
k, err := parseBase64(base64.StdEncoding, b64)
|
||||||
|
return (*Private)(k), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Private) String() string { return base64.StdEncoding.EncodeToString(k[:]) }
|
||||||
|
func (k *Private) HexString() string { return hex.EncodeToString(k[:]) }
|
||||||
|
func (k *Private) Equal(k2 Private) bool { return subtle.ConstantTimeCompare(k[:], k2[:]) == 1 }
|
||||||
|
|
||||||
|
func (k *Private) IsZero() bool {
|
||||||
|
pk := Key(*k)
|
||||||
|
return pk.IsZero()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Private) clamp() {
|
||||||
|
k[0] &= 248
|
||||||
|
k[31] = (k[31] & 127) | 64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public computes the public key matching this curve25519 secret key.
|
||||||
|
func (k *Private) Public() Key {
|
||||||
|
pk := Key(*k)
|
||||||
|
if pk.IsZero() {
|
||||||
|
panic("Tried to generate emptyPrivate.Public()")
|
||||||
|
}
|
||||||
|
var p [Size]byte
|
||||||
|
curve25519.ScalarBaseMult(&p, (*[Size]byte)(k))
|
||||||
|
return (Key)(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k Private) MarshalText() ([]byte, error) {
|
||||||
|
// TODO(josharian): use encoding/hex instead?
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
fmt.Fprintf(buf, `privkey:%x`, k[:])
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *Private) UnmarshalText(b []byte) error {
|
||||||
|
s := string(b)
|
||||||
|
if !strings.HasPrefix(s, `privkey:`) {
|
||||||
|
return errors.New("wgkey.Private: UnmarshalText not given a private-key string")
|
||||||
|
}
|
||||||
|
s = strings.TrimPrefix(s, `privkey:`)
|
||||||
|
key, err := ParseHex(s)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("wgkey.Private: UnmarshalText: %v", err)
|
||||||
|
}
|
||||||
|
copy(k[:], key[:])
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBase64(enc *base64.Encoding, s string) (*Key, error) {
|
||||||
|
k, err := enc.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid key (%q): %w", s, err)
|
||||||
|
}
|
||||||
|
if len(k) != Size {
|
||||||
|
return nil, fmt.Errorf("invalid key (%q): length=%d, want %d", s, len(k), Size)
|
||||||
|
}
|
||||||
|
var key Key
|
||||||
|
copy(key[:], k)
|
||||||
|
return &key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseSymmetric(b64 string) (Symmetric, error) {
|
||||||
|
k, err := parseBase64(base64.StdEncoding, b64)
|
||||||
|
if err != nil {
|
||||||
|
return Symmetric{}, err
|
||||||
|
}
|
||||||
|
return Symmetric(*k), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseSymmetricHex(s string) (Symmetric, error) {
|
||||||
|
b, err := hex.DecodeString(s)
|
||||||
|
if err != nil {
|
||||||
|
return Symmetric{}, fmt.Errorf("invalid symmetric hex key (%q): %w", s, err)
|
||||||
|
}
|
||||||
|
if len(b) != chacha20poly1305.KeySize {
|
||||||
|
return Symmetric{}, fmt.Errorf("invalid symmetric hex key length (%q): length=%d, want %d", s, len(b), chacha20poly1305.KeySize)
|
||||||
|
}
|
||||||
|
var key Symmetric
|
||||||
|
copy(key[:], b)
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Symmetric is a chacha20poly1305 key.
|
||||||
|
// It is used by WireGuard to represent pre-shared symmetric keys.
|
||||||
|
type Symmetric [chacha20poly1305.KeySize]byte
|
||||||
|
|
||||||
|
func (k Symmetric) Base64() string { return base64.StdEncoding.EncodeToString(k[:]) }
|
||||||
|
func (k Symmetric) String() string { return "sym:" + k.Base64()[:8] }
|
||||||
|
func (k Symmetric) HexString() string { return hex.EncodeToString(k[:]) }
|
||||||
|
func (k Symmetric) IsZero() bool { return k.Equal(Symmetric{}) }
|
||||||
|
func (k Symmetric) Equal(k2 Symmetric) bool {
|
||||||
|
return subtle.ConstantTimeCompare(k[:], k2[:]) == 1
|
||||||
|
}
|
111
types/wgkey/key_test.go
Normal file
111
types/wgkey/key_test.go
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package wgkey
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestKeyBasics(t *testing.T) {
|
||||||
|
k1, err := NewPreshared()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := k1.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("JSON round-trip", func(t *testing.T) {
|
||||||
|
// should preserve the keys
|
||||||
|
k2 := new(Key)
|
||||||
|
if err := k2.UnmarshalJSON(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(k1[:], k2[:]) {
|
||||||
|
t.Fatalf("k1 %v != k2 %v", k1[:], k2[:])
|
||||||
|
}
|
||||||
|
if b1, b2 := k1.String(), k2.String(); b1 != b2 {
|
||||||
|
t.Fatalf("base64-encoded keys do not match: %s, %s", b1, b2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("JSON incompatible with PrivateKey", func(t *testing.T) {
|
||||||
|
k2 := new(Private)
|
||||||
|
if err := k2.UnmarshalText(b); err == nil {
|
||||||
|
t.Fatalf("successfully decoded key as private key")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("second key", func(t *testing.T) {
|
||||||
|
// A second call to NewPreshared should make a new key.
|
||||||
|
k3, err := NewPreshared()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if bytes.Equal(k1[:], k3[:]) {
|
||||||
|
t.Fatalf("k1 %v == k3 %v", k1[:], k3[:])
|
||||||
|
}
|
||||||
|
// Check for obvious comparables to make sure we are not generating bad strings somewhere.
|
||||||
|
if b1, b2 := k1.String(), k3.String(); b1 == b2 {
|
||||||
|
t.Fatalf("base64-encoded keys match: %s, %s", b1, b2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
func TestPrivateKeyBasics(t *testing.T) {
|
||||||
|
pri, err := NewPrivate()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := pri.MarshalText()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("JSON round-trip", func(t *testing.T) {
|
||||||
|
// should preserve the keys
|
||||||
|
pri2 := new(Private)
|
||||||
|
if err := pri2.UnmarshalText(b); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(pri[:], pri2[:]) {
|
||||||
|
t.Fatalf("pri %v != pri2 %v", pri[:], pri2[:])
|
||||||
|
}
|
||||||
|
if b1, b2 := pri.String(), pri2.String(); b1 != b2 {
|
||||||
|
t.Fatalf("base64-encoded keys do not match: %s, %s", b1, b2)
|
||||||
|
}
|
||||||
|
if pub1, pub2 := pri.Public().String(), pri2.Public().String(); pub1 != pub2 {
|
||||||
|
t.Fatalf("base64-encoded public keys do not match: %s, %s", pub1, pub2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("JSON incompatible with Key", func(t *testing.T) {
|
||||||
|
k2 := new(Key)
|
||||||
|
if err := k2.UnmarshalJSON(b); err == nil {
|
||||||
|
t.Fatalf("successfully decoded private key as key")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("second key", func(t *testing.T) {
|
||||||
|
// A second call to New should make a new key.
|
||||||
|
pri3, err := NewPrivate()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if bytes.Equal(pri[:], pri3[:]) {
|
||||||
|
t.Fatalf("pri %v == pri3 %v", pri[:], pri3[:])
|
||||||
|
}
|
||||||
|
// Check for obvious comparables to make sure we are not generating bad strings somewhere.
|
||||||
|
if b1, b2 := pri.String(), pri3.String(); b1 == b2 {
|
||||||
|
t.Fatalf("base64-encoded keys match: %s, %s", b1, b2)
|
||||||
|
}
|
||||||
|
if pub1, pub2 := pri.Public().String(), pri3.Public().String(); pub1 == pub2 {
|
||||||
|
t.Fatalf("base64-encoded public keys match: %s, %s", pub1, pub2)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -20,6 +20,7 @@ import (
|
|||||||
"tailscale.com/ipn/ipnstate"
|
"tailscale.com/ipn/ipnstate"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
var errNoDestinations = errors.New("magicsock: no destinations")
|
var errNoDestinations = errors.New("magicsock: no destinations")
|
||||||
@ -387,7 +388,7 @@ func (a *addrSet) UpdateDst(new *net.UDPAddr) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
publicKey := wgcfg.Key(a.publicKey)
|
publicKey := wgkey.Key(a.publicKey)
|
||||||
pk := publicKey.ShortString()
|
pk := publicKey.ShortString()
|
||||||
old := "<none>"
|
old := "<none>"
|
||||||
if a.curAddr >= 0 {
|
if a.curAddr >= 0 {
|
||||||
|
@ -52,6 +52,7 @@ import (
|
|||||||
"tailscale.com/types/nettype"
|
"tailscale.com/types/nettype"
|
||||||
"tailscale.com/types/opt"
|
"tailscale.com/types/opt"
|
||||||
"tailscale.com/types/structs"
|
"tailscale.com/types/structs"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1562,7 +1563,7 @@ Top:
|
|||||||
} else if asEp != nil {
|
} else if asEp != nil {
|
||||||
ep = asEp
|
ep = asEp
|
||||||
} else {
|
} else {
|
||||||
key := wgcfg.Key(dm.src)
|
key := wgkey.Key(dm.src)
|
||||||
c.logf("magicsock: DERP packet from unknown key: %s", key.ShortString())
|
c.logf("magicsock: DERP packet from unknown key: %s", key.ShortString())
|
||||||
// TODO(danderson): after we fail to find a DERP endpoint, we
|
// TODO(danderson): after we fail to find a DERP endpoint, we
|
||||||
// seem to be falling through to passing the packet to
|
// seem to be falling through to passing the packet to
|
||||||
@ -1952,7 +1953,7 @@ func (c *Conn) SetNetworkUp(up bool) {
|
|||||||
//
|
//
|
||||||
// If the private key changes, any DERP connections are torn down &
|
// If the private key changes, any DERP connections are torn down &
|
||||||
// recreated when needed.
|
// recreated when needed.
|
||||||
func (c *Conn) SetPrivateKey(privateKey wgcfg.PrivateKey) error {
|
func (c *Conn) SetPrivateKey(privateKey wgkey.Private) error {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
@ -2660,7 +2661,7 @@ func simpleDur(d time.Duration) time.Duration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func peerShort(k key.Public) string {
|
func peerShort(k key.Public) string {
|
||||||
k2 := wgcfg.Key(k)
|
k2 := wgkey.Key(k)
|
||||||
return k2.ShortString()
|
return k2.ShortString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import (
|
|||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/nettype"
|
"tailscale.com/types/nettype"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
"tailscale.com/wgengine/tstun"
|
"tailscale.com/wgengine/tstun"
|
||||||
)
|
)
|
||||||
@ -119,7 +120,7 @@ func runDERPAndStun(t *testing.T, logf logger.Logf, l nettype.PacketListener, st
|
|||||||
// necessary to send and receive packets to test e2e wireguard
|
// necessary to send and receive packets to test e2e wireguard
|
||||||
// happiness.
|
// happiness.
|
||||||
type magicStack struct {
|
type magicStack struct {
|
||||||
privateKey wgcfg.PrivateKey
|
privateKey wgkey.Private
|
||||||
epCh chan []string // endpoint updates produced by this peer
|
epCh chan []string // endpoint updates produced by this peer
|
||||||
conn *Conn // the magicsock itself
|
conn *Conn // the magicsock itself
|
||||||
tun *tuntest.ChannelTUN // TUN device to send/receive packets
|
tun *tuntest.ChannelTUN // TUN device to send/receive packets
|
||||||
@ -133,7 +134,7 @@ type magicStack struct {
|
|||||||
func newMagicStack(t testing.TB, logf logger.Logf, l nettype.PacketListener, derpMap *tailcfg.DERPMap) *magicStack {
|
func newMagicStack(t testing.TB, logf logger.Logf, l nettype.PacketListener, derpMap *tailcfg.DERPMap) *magicStack {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
privateKey, err := wgcfg.NewPrivateKey()
|
privateKey, err := wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("generating private key: %v", err)
|
t.Fatalf("generating private key: %v", err)
|
||||||
}
|
}
|
||||||
@ -347,7 +348,7 @@ func TestNewConn(t *testing.T) {
|
|||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
conn.SetDERPMap(stuntest.DERPMapOf(stunAddr.String()))
|
conn.SetDERPMap(stuntest.DERPMapOf(stunAddr.String()))
|
||||||
conn.SetPrivateKey(wgcfg.PrivateKey(key.NewPrivate()))
|
conn.SetPrivateKey(wgkey.Private(key.NewPrivate()))
|
||||||
conn.Start()
|
conn.Start()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@ -457,11 +458,11 @@ func makeConfigs(t *testing.T, addrs []netaddr.IPPort) []wgcfg.Config {
|
|||||||
var addresses [][]netaddr.IPPrefix
|
var addresses [][]netaddr.IPPrefix
|
||||||
|
|
||||||
for i := range addrs {
|
for i := range addrs {
|
||||||
privKey, err := wgcfg.NewPrivateKey()
|
privKey, err := wgkey.NewPrivate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
privKeys = append(privKeys, privKey)
|
privKeys = append(privKeys, wgcfg.PrivateKey(privKey))
|
||||||
|
|
||||||
addresses = append(addresses, []netaddr.IPPrefix{
|
addresses = append(addresses, []netaddr.IPPrefix{
|
||||||
parseCIDR(t, fmt.Sprintf("1.0.0.%d/32", i+1)),
|
parseCIDR(t, fmt.Sprintf("1.0.0.%d/32", i+1)),
|
||||||
|
@ -37,6 +37,7 @@ import (
|
|||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/types/wgkey"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
"tailscale.com/version/distro"
|
"tailscale.com/version/distro"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
@ -113,9 +114,9 @@ type userspaceEngine struct {
|
|||||||
closing bool // Close was called (even if we're still closing)
|
closing bool // Close was called (even if we're still closing)
|
||||||
statusCallback StatusCallback
|
statusCallback StatusCallback
|
||||||
linkChangeCallback func(major bool, newState *interfaces.State)
|
linkChangeCallback func(major bool, newState *interfaces.State)
|
||||||
peerSequence []wgcfg.Key
|
peerSequence []wgkey.Key
|
||||||
endpoints []string
|
endpoints []string
|
||||||
pingers map[wgcfg.Key]*pinger // legacy pingers for pre-discovery peers
|
pingers map[wgkey.Key]*pinger // legacy pingers for pre-discovery peers
|
||||||
linkState *interfaces.State
|
linkState *interfaces.State
|
||||||
|
|
||||||
// Lock ordering: magicsock.Conn.mu, wgLock, then mu.
|
// Lock ordering: magicsock.Conn.mu, wgLock, then mu.
|
||||||
@ -202,7 +203,7 @@ func newUserspaceEngineAdvanced(conf EngineConfig) (_ Engine, reterr error) {
|
|||||||
waitCh: make(chan struct{}),
|
waitCh: make(chan struct{}),
|
||||||
tundev: tstun.WrapTUN(logf, conf.TUN),
|
tundev: tstun.WrapTUN(logf, conf.TUN),
|
||||||
resolver: tsdns.NewResolver(rconf),
|
resolver: tsdns.NewResolver(rconf),
|
||||||
pingers: make(map[wgcfg.Key]*pinger),
|
pingers: make(map[wgkey.Key]*pinger),
|
||||||
}
|
}
|
||||||
e.localAddrs.Store(map[netaddr.IP]bool{})
|
e.localAddrs.Store(map[netaddr.IP]bool{})
|
||||||
e.linkState, _ = getLinkState()
|
e.linkState, _ = getLinkState()
|
||||||
@ -290,7 +291,7 @@ func newUserspaceEngineAdvanced(conf EngineConfig) (_ Engine, reterr error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
go e.pinger(peerKey, ips)
|
go e.pinger(wgkey.Key(peerKey), ips)
|
||||||
} else {
|
} else {
|
||||||
logf("[unexpected] peer %s has no single-IP routes: %v", peerKey.ShortString(), allowedIPs)
|
logf("[unexpected] peer %s has no single-IP routes: %v", peerKey.ShortString(), allowedIPs)
|
||||||
}
|
}
|
||||||
@ -487,7 +488,7 @@ func (p *pinger) close() {
|
|||||||
<-p.done
|
<-p.done
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *pinger) run(ctx context.Context, peerKey wgcfg.Key, ips []netaddr.IP, srcIP netaddr.IP) {
|
func (p *pinger) run(ctx context.Context, peerKey wgkey.Key, ips []netaddr.IP, srcIP netaddr.IP) {
|
||||||
defer func() {
|
defer func() {
|
||||||
p.e.mu.Lock()
|
p.e.mu.Lock()
|
||||||
if p.e.pingers[peerKey] == p {
|
if p.e.pingers[peerKey] == p {
|
||||||
@ -556,7 +557,7 @@ func (p *pinger) run(ctx context.Context, peerKey wgcfg.Key, ips []netaddr.IP, s
|
|||||||
//
|
//
|
||||||
// This is only used with legacy peers (before 0.100.0) that don't
|
// This is only used with legacy peers (before 0.100.0) that don't
|
||||||
// have advertised discovery keys.
|
// have advertised discovery keys.
|
||||||
func (e *userspaceEngine) pinger(peerKey wgcfg.Key, ips []netaddr.IP) {
|
func (e *userspaceEngine) pinger(peerKey wgkey.Key, ips []netaddr.IP) {
|
||||||
e.logf("[v1] generating initial ping traffic to %s (%v)", peerKey.ShortString(), ips)
|
e.logf("[v1] generating initial ping traffic to %s (%v)", peerKey.ShortString(), ips)
|
||||||
var srcIP netaddr.IP
|
var srcIP netaddr.IP
|
||||||
|
|
||||||
@ -890,7 +891,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config)
|
|||||||
e.mu.Lock()
|
e.mu.Lock()
|
||||||
e.peerSequence = e.peerSequence[:0]
|
e.peerSequence = e.peerSequence[:0]
|
||||||
for _, p := range cfg.Peers {
|
for _, p := range cfg.Peers {
|
||||||
e.peerSequence = append(e.peerSequence, p.PublicKey)
|
e.peerSequence = append(e.peerSequence, wgkey.Key(p.PublicKey))
|
||||||
peerSet[key.Public(p.PublicKey)] = struct{}{}
|
peerSet[key.Public(p.PublicKey)] = struct{}{}
|
||||||
}
|
}
|
||||||
e.mu.Unlock()
|
e.mu.Unlock()
|
||||||
@ -932,7 +933,7 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config)
|
|||||||
// (which is needed by DERP) before wgdev gets it, as wgdev
|
// (which is needed by DERP) before wgdev gets it, as wgdev
|
||||||
// will start trying to handshake, which we want to be able to
|
// will start trying to handshake, which we want to be able to
|
||||||
// go over DERP.
|
// go over DERP.
|
||||||
if err := e.magicConn.SetPrivateKey(cfg.PrivateKey); err != nil {
|
if err := e.magicConn.SetPrivateKey(wgkey.Private(cfg.PrivateKey)); err != nil {
|
||||||
e.logf("wgengine: Reconfig: SetPrivateKey: %v", err)
|
e.logf("wgengine: Reconfig: SetPrivateKey: %v", err)
|
||||||
}
|
}
|
||||||
e.magicConn.UpdatePeers(peerSet)
|
e.magicConn.UpdatePeers(peerSet)
|
||||||
@ -1039,7 +1040,7 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
|
|||||||
errc <- bw.Flush()
|
errc <- bw.Flush()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
pp := make(map[wgcfg.Key]*PeerStatus)
|
pp := make(map[wgkey.Key]*PeerStatus)
|
||||||
p := &PeerStatus{}
|
p := &PeerStatus{}
|
||||||
|
|
||||||
var hst1, hst2, n int64
|
var hst1, hst2, n int64
|
||||||
@ -1062,7 +1063,7 @@ func (e *userspaceEngine) getStatus() (*Status, error) {
|
|||||||
log.Fatalf("IpcGetOperation: invalid key %#v", v)
|
log.Fatalf("IpcGetOperation: invalid key %#v", v)
|
||||||
}
|
}
|
||||||
p = &PeerStatus{}
|
p = &PeerStatus{}
|
||||||
pp[wgcfg.Key(pk)] = p
|
pp[wgkey.Key(pk)] = p
|
||||||
|
|
||||||
key := tailcfg.NodeKey(pk)
|
key := tailcfg.NodeKey(pk)
|
||||||
p.NodeKey = key
|
p.NodeKey = key
|
||||||
|
Loading…
x
Reference in New Issue
Block a user