From 051b6ef141eace6b6ba067ac08d6064831312f35 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 2 Mar 2020 08:55:44 -0800 Subject: [PATCH] cmd/derper: accept more LetsEncrypt hostnames without explicit config --- cmd/derper/derper.go | 15 +++++++++++++++ cmd/derper/derper_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 cmd/derper/derper_test.go diff --git a/cmd/derper/derper.go b/cmd/derper/derper.go index 6a1979611..e3fe069a9 100644 --- a/cmd/derper/derper.go +++ b/cmd/derper/derper.go @@ -6,7 +6,9 @@ package main // import "tailscale.com/cmd/derper" import ( + "context" "encoding/json" + "errors" "expvar" "flag" "fmt" @@ -17,6 +19,7 @@ import ( "net/http" "os" "path/filepath" + "regexp" "time" "github.com/tailscale/wireguard-go/wgcfg" @@ -159,6 +162,9 @@ func main() { HostPolicy: autocert.HostWhitelist(*hostname), Cache: autocert.DirCache(*certDir), } + if *hostname == "derp.tailscale.com" { + certManager.HostPolicy = prodAutocertHostPolicy + } httpsrv.TLSConfig = certManager.TLSConfig() go func() { err := http.ListenAndServe(":80", certManager.HTTPHandler(tsweb.Port80Handler{mux})) @@ -253,3 +259,12 @@ func serveSTUN() { } } } + +var validProdHostname = regexp.MustCompile(`^derp(\d+|\-\w+)?\.tailscale\.com\.?$`) + +func prodAutocertHostPolicy(_ context.Context, host string) error { + if validProdHostname.MatchString(host) { + return nil + } + return errors.New("invalid hostname") +} diff --git a/cmd/derper/derper_test.go b/cmd/derper/derper_test.go new file mode 100644 index 000000000..33500d884 --- /dev/null +++ b/cmd/derper/derper_test.go @@ -0,0 +1,31 @@ +// 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 main + +import "testing" + +func TestProdAutocertHostPolicy(t *testing.T) { + tests := []struct { + in string + wantOK bool + }{ + {"derp.tailscale.com", true}, + {"derp.tailscale.com.", true}, + {"derp1.tailscale.com", true}, + {"derp2.tailscale.com", true}, + {"derp02.tailscale.com", true}, + {"derp-nyc.tailscale.com", true}, + {"derpfoo.tailscale.com", false}, + {"derp02.bar.tailscale.com", false}, + {"example.net", false}, + } + for _, tt := range tests { + got := prodAutocertHostPolicy(nil, tt.in) == nil + if got != tt.wantOK { + t.Errorf("f(%q) = %v; want %v", tt.in, got, tt.wantOK) + } + } + +}