Use tcp/80 for TS2021 when Let's Encrypt HTTP-01 is enabled

TS2021 prefers running over plain HTTP (tcp/80), to avoid double encryption. When using
Lets Encrypt with the HTTP-01 challengue, we are sure tcp/80 is available, so we can
extend the redirect we already had there to also listen for /ts2021 upgrades.
This commit is contained in:
Juan Font Alonso 2022-04-30 23:35:13 +02:00
parent 30d0d20029
commit 33d0d2d900

16
app.go
View file

@ -273,9 +273,10 @@ func NewHeadscale(cfg Config) (*Headscale, error) {
} }
// Redirect to our TLS url. // Redirect to our TLS url.
func (h *Headscale) redirect(w http.ResponseWriter, req *http.Request) { func (h *Headscale) redirect(ctx *gin.Context) {
target := h.cfg.ServerURL + req.URL.RequestURI() log.Trace().Msgf("Redirecting to TLS, path %s", ctx.Request.RequestURI)
http.Redirect(w, req, target, http.StatusFound) target := h.cfg.ServerURL + ctx.Request.RequestURI
http.Redirect(ctx.Writer, ctx.Request, target, http.StatusFound)
} }
// expireEphemeralNodes deletes ephemeral machine records that have not been // expireEphemeralNodes deletes ephemeral machine records that have not been
@ -479,7 +480,7 @@ func (h *Headscale) createRouter(grpcMux *runtime.ServeMux) *gin.Engine {
func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"healthy": "ok"}) }, func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"healthy": "ok"}) },
) )
router.POST("/ts2021", h.NoiseUpgradeHandler) router.POST(ts2021UpgradePath, h.NoiseUpgradeHandler)
router.GET("/key", h.KeyHandler) router.GET("/key", h.KeyHandler)
router.GET("/register", h.RegisterWebAPI) router.GET("/register", h.RegisterWebAPI)
router.POST("/machine/:id/map", h.PollNetMapHandler) router.POST("/machine/:id/map", h.PollNetMapHandler)
@ -772,10 +773,14 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
// Configuration via autocert with HTTP-01. This requires listening on // Configuration via autocert with HTTP-01. This requires listening on
// port 80 for the certificate validation in addition to the headscale // port 80 for the certificate validation in addition to the headscale
// service, which can be configured to run on any other port. // service, which can be configured to run on any other port.
httpRouter := gin.Default()
httpRouter.POST(ts2021UpgradePath, h.NoiseUpgradeHandler)
httpRouter.NoRoute(h.redirect)
go func() { go func() {
log.Fatal(). log.Fatal().
Caller(). Caller().
Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, certManager.HTTPHandler(http.HandlerFunc(h.redirect)))). Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, certManager.HTTPHandler(httpRouter))).
Msg("failed to set up a HTTP server") Msg("failed to set up a HTTP server")
}() }()
@ -813,6 +818,7 @@ func (h *Headscale) getTLSSettings() (*tls.Config, error) {
} }
func (h *Headscale) setLastStateChangeToNow(namespace string) { func (h *Headscale) setLastStateChangeToNow(namespace string) {
log.Trace().Msgf("setting last state change to now for namespace %s", namespace)
now := time.Now().UTC() now := time.Now().UTC()
lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix())) lastStateUpdate.WithLabelValues("", "headscale").Set(float64(now.Unix()))
h.lastStateChange.Store(namespace, now) h.lastStateChange.Store(namespace, now)