commit 2d89aa0b7bf10c571f934b846c363cf4a2b9b761
Author: David Fifield <[email protected]>
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)
+       }
 }



_______________________________________________
tor-commits mailing list
[email protected]
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits

Reply via email to