[tor-commits] [snowflake/master] autocert (Let's Encrypt) for broker.
dcf at torproject.org
dcf at torproject.org
Thu Aug 3 02:35:44 UTC 2017
commit 2d89aa0b7bf10c571f934b846c363cf4a2b9b761
Author: David Fifield <david at bamsoftware.com>
Date: Fri Jul 14 20:25:46 2017 -0700
autocert (Let's Encrypt) for broker.
Replaces --cert and --key with --acme-hostnames and --acme-email.
---
broker/README.md | 26 +++++++++++++++++++---
broker/broker.go | 68 +++++++++++++++++++++++++++-----------------------------
2 files changed, 56 insertions(+), 38 deletions(-)
diff --git a/broker/README.md b/broker/README.md
index 1efe9fc..8d8c968 100644
--- a/broker/README.md
+++ b/broker/README.md
@@ -22,9 +22,29 @@ The Broker expects:
### Running your own
-You can run your own Broker on localhost, you'll need to pass a TLS
-certificate file using `--cert` option and the corresponding private key
-file using `--key` option.
+The server uses TLS by default.
+There is a `--disable-tls` option for testing purposes,
+but you should use TLS in production.
+
+The server automatically fetches certificates
+from [Let's Encrypt](https://en.wikipedia.org/wiki/Let's_Encrypt) as needed.
+Use the `--acme-hostnames` option to tell the server
+what hostnames it may request certificates for.
+You can optionally provide a contact email address,
+using the `--acme-email` option,
+so that Let's Encrypt can inform you of any problems.
+
+In order to fetch certificates automatically,
+the server needs to be listening on port 443 (the default).
+On Linux, you can use the `setcap` program,
+part of libcap2, to enable the broker to bind to low-numbered ports
+without having to run as root:
+```
+setcap 'cap_net_bind_service=+ep' /usr/local/bin/broker
+```
+You can control the listening port with the --tlsPort
+or --webPort options (--webPort is honored only when
+also using --disable-tls).
You'll need to provide the URL of the custom broker
to the client plugin using the `--url $URL` flag.
diff --git a/broker/broker.go b/broker/broker.go
index f56f31b..9892fc3 100644
--- a/broker/broker.go
+++ b/broker/broker.go
@@ -7,15 +7,17 @@ package main
import (
"container/heap"
+ "crypto/tls"
"flag"
"fmt"
"io/ioutil"
"log"
"net"
"net/http"
- "os"
- "sync"
+ "strings"
"time"
+
+ "golang.org/x/crypto/acme/autocert"
)
const (
@@ -230,26 +232,18 @@ func ipHandler(w http.ResponseWriter, r *http.Request) {
}
func main() {
- var cert, cert_key, http_port, https_port string
-
- flag.StringVar(&cert, "cert", "", "TLS certificate file")
- flag.StringVar(&cert_key, "key", "", "TLS key file")
+ var acmeEmail string
+ var acmeHostnamesCommas string
+ var disableTLS bool
+ var http_port, https_port string
+ flag.StringVar(&acmeEmail, "acme-email", "", "optional contact email for Let's Encrypt notifications")
+ flag.StringVar(&acmeHostnamesCommas, "acme-hostnames", "", "comma-separated hostnames for TLS certificate")
+ flag.BoolVar(&disableTLS, "disable-tls", false, "don't use HTTPS")
flag.StringVar(&http_port, "webPort", "80", "HTTP port number")
flag.StringVar(&https_port, "tlsPort", "443", "HTTPS port number")
-
flag.Parse()
- if cert == "" || cert_key == "" {
- log.Println("Missing options, exiting.")
- fmt.Println("Usage:")
- flag.PrintDefaults()
- os.Exit(1)
- }
-
- log.Println("Using cert file:", cert)
- log.Println("Using cert key file: ", cert_key)
-
ctx := NewBrokerContext()
go ctx.Broker()
@@ -262,26 +256,30 @@ func main() {
http.Handle("/answer", SnowflakeHandler{ctx, proxyAnswers})
http.Handle("/debug", SnowflakeHandler{ctx, debugHandler})
- var wg sync.WaitGroup
- wg.Add(2)
+ var err error
+ var server http.Server
- //Run HTTP server
- go func() {
- defer wg.Done()
- err := http.ListenAndServe(":"+http_port, nil)
- if err != nil {
- log.Println("ListenAndServe: ", err)
- }
- }()
+ if acmeHostnamesCommas != "" {
+ acmeHostnames := strings.Split(acmeHostnamesCommas, ",")
+ log.Printf("ACME hostnames: %q", acmeHostnames)
- //Run HTTPS server
- go func() {
- defer wg.Done()
- err := http.ListenAndServeTLS(":"+https_port, cert, cert_key, nil)
- if err != nil {
- log.Println("ListenAndServeTLS: ", err)
+ certManager := autocert.Manager{
+ Prompt: autocert.AcceptTOS,
+ HostPolicy: autocert.HostWhitelist(acmeHostnames...),
+ Email: acmeEmail,
}
- }()
- wg.Wait()
+ server.Addr = net.JoinHostPort("", https_port)
+ server.TLSConfig = &tls.Config{GetCertificate: certManager.GetCertificate}
+ err = server.ListenAndServeTLS("", "")
+ } else if disableTLS {
+ server.Addr = net.JoinHostPort("", http_port)
+ err = server.ListenAndServe()
+ } else {
+ log.Fatal("the --acme-hostnames or --disable-tls option is required")
+ }
+
+ if err != nil {
+ log.Fatal(err)
+ }
}
More information about the tor-commits
mailing list