diff --git a/app.go b/app.go index 1809f95c..b87fb33c 100644 --- a/app.go +++ b/app.go @@ -47,6 +47,14 @@ import ( "tailscale.com/types/key" ) +const ( + errSTUNAddressNotSet = Error("STUN address not set") + errUnsupportedDatabase = Error("unsupported DB") + errUnsupportedLetsEncryptChallengeType = Error( + "unknown value for Lets Encrypt challenge type", + ) +) + const ( AuthPrefix = "Bearer " Postgres = "postgres" @@ -58,11 +66,6 @@ const ( registerCacheExpiration = time.Minute * 15 registerCacheCleanup = time.Minute * 20 - errUnsupportedDatabase = Error("unsupported DB") - errUnsupportedLetsEncryptChallengeType = Error( - "unknown value for Lets Encrypt challenge type", - ) - DisabledClientAuth = "disabled" RelaxedClientAuth = "relaxed" EnforcedClientAuth = "enforced" @@ -124,7 +127,6 @@ type DERPConfig struct { ServerRegionID int ServerRegionCode string ServerRegionName string - STUNEnabled bool STUNAddr string URLs []url.URL Paths []string @@ -500,10 +502,13 @@ func (h *Headscale) Serve() error { h.DERPMap = GetDERPMap(h.cfg.DERP) if h.cfg.DERP.ServerEnabled { - h.DERPMap.Regions[h.DERPServer.region.RegionID] = &h.DERPServer.region - if h.cfg.DERP.STUNEnabled { - go h.ServeSTUN() + // When embedded DERP is enabled we always need a STUN server + if h.cfg.DERP.STUNAddr == "" { + return errSTUNAddressNotSet } + + h.DERPMap.Regions[h.DERPServer.region.RegionID] = &h.DERPServer.region + go h.ServeSTUN() } if h.cfg.DERP.AutoUpdate { diff --git a/cmd/headscale/cli/utils.go b/cmd/headscale/cli/utils.go index dc7a4e9f..768a9713 100644 --- a/cmd/headscale/cli/utils.go +++ b/cmd/headscale/cli/utils.go @@ -55,6 +55,9 @@ func LoadConfig(path string) error { viper.SetDefault("dns_config", nil) + viper.SetDefault("derp.server.enabled", false) + viper.SetDefault("derp.server.stun.enabled", true) + viper.SetDefault("unix_socket", "/var/run/headscale.sock") viper.SetDefault("unix_socket_permission", "0o770") @@ -121,8 +124,11 @@ func GetDERPConfig() headscale.DERPConfig { serverRegionID := viper.GetInt("derp.server.region_id") serverRegionCode := viper.GetString("derp.server.region_code") serverRegionName := viper.GetString("derp.server.region_name") - stunEnabled := viper.GetBool("derp.server.stun.enabled") - stunAddr := viper.GetString("derp.server.stun.listen_addr") + stunAddr := viper.GetString("derp.server.stun_listen_addr") + + if serverEnabled && stunAddr == "" { + log.Fatal().Msg("derp.server.stun_listen_addr must be set if derp.server.enabled is true") + } urlStrs := viper.GetStringSlice("derp.urls") @@ -149,7 +155,6 @@ func GetDERPConfig() headscale.DERPConfig { ServerRegionID: serverRegionID, ServerRegionCode: serverRegionCode, ServerRegionName: serverRegionName, - STUNEnabled: stunEnabled, STUNAddr: stunAddr, URLs: urls, Paths: paths, diff --git a/config-example.yaml b/config-example.yaml index 2075e69a..dee25cb3 100644 --- a/config-example.yaml +++ b/config-example.yaml @@ -69,11 +69,11 @@ derp: region_code: "headscale" region_name: "Headscale Embedded DERP" - # If enabled, also listens in UDP at the configured address for STUN connections to help on NAT traversal + # Listens in UDP at the configured address for STUN connections to help on NAT traversal. + # When the embedded DERP server is enabled stun_listen_addr MUST be defined. + # # For more details on how this works, check this great article: https://tailscale.com/blog/how-tailscale-works/ - stun: - enabled: false - listen_addr: "0.0.0.0:3478" + stun_listen_addr: "0.0.0.0:3478" # List of externally available DERP maps encoded in JSON urls: diff --git a/derp_server.go b/derp_server.go index 11e3eb14..6580419e 100644 --- a/derp_server.go +++ b/derp_server.go @@ -77,17 +77,15 @@ func (h *Headscale) generateRegionLocalDERP() (tailcfg.DERPRegion, error) { }, } - if h.cfg.DERP.STUNEnabled { - _, portStr, err := net.SplitHostPort(h.cfg.DERP.STUNAddr) - if err != nil { - return tailcfg.DERPRegion{}, err - } - port, err := strconv.Atoi(portStr) - if err != nil { - return tailcfg.DERPRegion{}, err - } - localDERPregion.Nodes[0].STUNPort = port + _, portSTUNStr, err := net.SplitHostPort(h.cfg.DERP.STUNAddr) + if err != nil { + return tailcfg.DERPRegion{}, err } + portSTUN, err := strconv.Atoi(portSTUNStr) + if err != nil { + return tailcfg.DERPRegion{}, err + } + localDERPregion.Nodes[0].STUNPort = portSTUN return localDERPregion, nil } diff --git a/integration_test/etc_embedded_derp/config.yaml b/integration_test/etc_embedded_derp/config.yaml index 1531d347..a8b57af5 100644 --- a/integration_test/etc_embedded_derp/config.yaml +++ b/integration_test/etc_embedded_derp/config.yaml @@ -24,6 +24,5 @@ derp: region_id: 999 region_code: "headscale" region_name: "Headscale Embedded DERP" - stun: - enabled: true - listen_addr: "0.0.0.0:3478" + + stun_listen_addr: "0.0.0.0:3478"