From be59e8cc3c44e4f4e8711ea10595b54939f5035f Mon Sep 17 00:00:00 2001 From: Juan Font Alonso Date: Sun, 27 Mar 2022 11:32:33 +0200 Subject: [PATCH] Generate and read the Noise private key For TS2021 we need a new private key. It must be different from the one used in the original protocol, as told by Tailscale's Dave Anderson https://github.com/juanfont/headscale/issues/526#issuecomment-1079795935. --- app.go | 28 ++++++++++++++++++++-------- cmd/headscale/cli/utils.go | 7 ++++--- config-example.yaml | 7 +++++++ 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/app.go b/app.go index b87fb33c..c3a7b315 100644 --- a/app.go +++ b/app.go @@ -81,6 +81,7 @@ type Config struct { EphemeralNodeInactivityTimeout time.Duration IPPrefixes []netaddr.IPPrefix PrivateKeyPath string + NoisePrivateKeyPath string BaseDomain string DERP DERPConfig @@ -143,12 +144,13 @@ type CLIConfig struct { // Headscale represents the base app of the service. type Headscale struct { - cfg Config - db *gorm.DB - dbString string - dbType string - dbDebug bool - privateKey *key.MachinePrivate + cfg Config + db *gorm.DB + dbString string + dbType string + dbDebug bool + privateKey *key.MachinePrivate + noisePrivateKey *key.MachinePrivate DERPMap *tailcfg.DERPMap DERPServer *DERPServer @@ -188,11 +190,20 @@ func LookupTLSClientAuthMode(mode string) (tls.ClientAuthType, bool) { } func NewHeadscale(cfg Config) (*Headscale, error) { - privKey, err := readOrCreatePrivateKey(cfg.PrivateKeyPath) + privateKey, err := readOrCreatePrivateKey(cfg.PrivateKeyPath) if err != nil { return nil, fmt.Errorf("failed to read or create private key: %w", err) } + noisePrivateKey, err := readOrCreatePrivateKey(cfg.NoisePrivateKeyPath) + if err != nil { + return nil, fmt.Errorf("failed to read or create noise private key: %w", err) + } + + if privateKey.Equal(*noisePrivateKey) { + return nil, fmt.Errorf("private key and noise private key are the same") + } + var dbString string switch cfg.DBtype { case Postgres: @@ -219,7 +230,8 @@ func NewHeadscale(cfg Config) (*Headscale, error) { cfg: cfg, dbType: cfg.DBtype, dbString: dbString, - privateKey: privKey, + privateKey: privateKey, + noisePrivateKey: noisePrivateKey, aclRules: tailcfg.FilterAllowAll, // default allowall registrationCache: registrationCache, } diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index 768a9713..ae9d3c02 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -326,9 +326,10 @@ func getHeadscaleConfig() headscale.Config { GRPCAddr: viper.GetString("grpc_listen_addr"), GRPCAllowInsecure: viper.GetBool("grpc_allow_insecure"), - IPPrefixes: prefixes, - PrivateKeyPath: absPath(viper.GetString("private_key_path")), - BaseDomain: baseDomain, + IPPrefixes: prefixes, + PrivateKeyPath: absPath(viper.GetString("private_key_path")), + NoisePrivateKeyPath: absPath(viper.GetString("noise_private_key_path")), + BaseDomain: baseDomain, DERP: derpConfig, diff --git a/config-example.yaml b/config-example.yaml index dee25cb3..c4696f33 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -41,6 +41,13 @@ grpc_allow_insecure: false # autogenerated if it's missing private_key_path: /var/lib/headscale/private.key +# The Noise private key is used to encrypt the +# traffic between headscale and Tailscale clients when +# using the new Noise-based TS2021 protocol. +# The noise private key file which will be +# autogenerated if it's missing +noise_private_key_path: /var/lib/headscale/noise_private.key + # List of IP prefixes to allocate tailaddresses from. # Each prefix consists of either an IPv4 or IPv6 address, # and the associated prefix length, delimited by a slash.