From 9e619fc020963bc0c1c7664d163d93a1b5dc4d0a Mon Sep 17 00:00:00 2001 From: Justin Angel Date: Sat, 29 Jan 2022 12:59:31 -0500 Subject: [PATCH] Making client authentication mode configurable --- app.go | 24 +++++++++++++++++++++--- cmd/headscale/cli/utils.go | 8 ++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/app.go b/app.go index 3ba384b..6accaf9 100644 --- a/app.go +++ b/app.go @@ -87,8 +87,9 @@ type Config struct { TLSLetsEncryptCacheDir string TLSLetsEncryptChallengeType string - TLSCertPath string - TLSKeyPath string + TLSCertPath string + TLSKeyPath string + TLSClientAuthMode string ACMEURL string ACMEEmail string @@ -644,12 +645,29 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) { if !strings.HasPrefix(h.cfg.ServerURL, "https://") { log.Warn().Msg("Listening with TLS but ServerURL does not start with https://") } + + // Leaving flexibility here to support other authentication modes + // if desired. + var client_auth_mode tls.ClientAuthType + msg := "Client authentication (mTLS) " + if(h.cfg.TLSClientAuthMode == "disabled"){ + log.Warn().Msg(msg + "is disabled") + client_auth_mode = tls.NoClientCert + }else if (h.cfg.TLSClientAuthMode == "relaxed"){ + log.Warn().Msg(msg + "is relaxed. Client certs will be required but will not be verified.") + client_auth_mode = tls.RequireAnyClientCert + }else{ + log.Warn().Msg(msg + "is enforced. Disable or relax in the configuration file.") + client_auth_mode = tls.RequireAndVerifyClientCert + } + tlsConfig := &tls.Config{ - ClientAuth: tls.RequireAnyClientCert, + ClientAuth: client_auth_mode, NextProtos: []string{"http/1.1"}, Certificates: make([]tls.Certificate, 1), MinVersion: tls.VersionTLS12, } + tlsConfig.Certificates[0], err = tls.LoadX509KeyPair(h.cfg.TLSCertPath, h.cfg.TLSKeyPath) return tlsConfig, err diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index a485664..4faf905 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -40,6 +40,7 @@ func LoadConfig(path string) error { viper.SetDefault("tls_letsencrypt_cache_dir", "/var/www/.cache") viper.SetDefault("tls_letsencrypt_challenge_type", "HTTP-01") + viper.SetDefault("tls_client_auth_mode", "disabled") viper.SetDefault("ip_prefix", "100.64.0.0/10") @@ -80,6 +81,12 @@ func LoadConfig(path string) error { !strings.HasPrefix(viper.GetString("server_url"), "https://") { errorText += "Fatal config error: server_url must start with https:// or http://\n" } + + auth_mode := viper.GetString("tls_client_auth_mode") + if (auth_mode != "disabled" && auth_mode != "enforced"){ + errorText += "Invalid tls_client_auth_mode supplied. Accepted values: disabled, enforced." + } + if errorText != "" { //nolint return errors.New(strings.TrimSuffix(errorText, "\n")) @@ -251,6 +258,7 @@ func getHeadscaleConfig() headscale.Config { TLSCertPath: absPath(viper.GetString("tls_cert_path")), TLSKeyPath: absPath(viper.GetString("tls_key_path")), + TLSClientAuthMode: viper.GetString("tls_client_auth_mode"), DNSConfig: dnsConfig,