[tor-commits] [snowflake/master] Use Manager.HTTPHandler for automatic TLS support in the server.

dcf at torproject.org dcf at torproject.org
Tue Mar 6 05:17:43 UTC 2018


commit d0686b1c8df037413f32bef891ef90638b75a080
Author: David Fifield <david at bamsoftware.com>
Date:   Mon Mar 5 15:25:48 2018 -0800

    Use Manager.HTTPHandler for automatic TLS support in the server.
    
    As with commit fcc274ac68dcb9063ca631fac9e8905e90088660 for the broker,
    we need to start using the HTTP-01 challenge type in the Snowflake
    websocket server transport plugin.
    https://bugs.torproject.org/25346
---
 server/README.md | 13 ++++++-------
 server/server.go | 41 ++++++++++++++++++-----------------------
 2 files changed, 24 insertions(+), 30 deletions(-)

diff --git a/server/README.md b/server/README.md
index d0fd91d..312a506 100644
--- a/server/README.md
+++ b/server/README.md
@@ -7,10 +7,10 @@ and the proxy connects to the server (this program) using WebSocket.
 
 # Setup
 
-The server needs to be able to listen on port 443
+The server needs to be able to listen on port 80
 in order to generate its TLS certificates.
 On Linux, use the `setcap` program to enable
-the server to listen on port 443 without running as root:
+the server to listen on port 80 without running as root:
 ```
 setcap 'cap_net_bind_service=+ep' /usr/local/bin/snowflake-server
 ```
@@ -48,12 +48,11 @@ The server will cache TLS certificate data in the directory
 `pt_state/snowflake-certificate-cache` inside the tor state directory.
 
 In order to fetch certificates automatically,
-the server needs to listen on port 443.
+the server needs to listen on port 80,
+in addition to whatever ports it is listening on
+for WebSocket connections.
 This is a requirement of the ACME protocol used by Let's Encrypt.
-If your `ServerTransportListenAddr` is not on port 443,
-the server will open an listener on port 443 in addition
-to the port you requested.
-The program will exit if it can't bind to port 443.
+The program will exit if it can't bind to port 80.
 On Linux, you can use the `setcap` program,
 part of libcap2, to enable the server to bind to low-numbered ports
 without having to run as root:
diff --git a/server/server.go b/server/server.go
index a0ddb3e..5ec3ff9 100644
--- a/server/server.go
+++ b/server/server.go
@@ -41,8 +41,8 @@ func usage() {
 WebSocket server pluggable transport for Snowflake. Works only as a managed
 proxy. Uses TLS with ACME (Let's Encrypt) by default. Set the certificate
 hostnames with the --acme-hostnames option. Use ServerTransportListenAddr in
-torrc to choose the listening port. When using TLS, if the port is not 443, this
-program will open an additional listening port on 443 to work with ACME.
+torrc to choose the listening port. When using TLS, this program will open an
+additional HTTP listener on port 80 to work with ACME.
 
 `, os.Args[0])
 	flag.PrintDefaults()
@@ -297,19 +297,11 @@ func main() {
 		}
 	}
 
-	// The ACME responder only works when it is running on port 443. In case
-	// there is not already going to be a TLS listener on port 443, we need
-	// to open an additional one. The port is actually opened in the loop
-	// below, so that any errors can be reported in the SMETHOD-ERROR of
-	// another bindaddr.
-	// https://letsencrypt.github.io/acme-spec/#domain-validation-with-server-name-indication-dvsni
-	need443Listener := !disableTLS
-	for _, bindaddr := range ptInfo.Bindaddrs {
-		if !disableTLS && bindaddr.Addr.Port == 443 {
-			need443Listener = false
-			break
-		}
-	}
+	// The ACME HTTP-01 responder only works when it is running on port 80.
+	// We actually open the port in the loop below, so that any errors can
+	// be reported in the SMETHOD-ERROR of some bindaddr.
+	// https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#http-challenge
+	needHTTP01Listener := !disableTLS
 
 	listeners := make([]net.Listener, 0)
 	for _, bindaddr := range ptInfo.Bindaddrs {
@@ -318,18 +310,21 @@ func main() {
 			continue
 		}
 
-		if need443Listener {
+		if needHTTP01Listener {
 			addr := *bindaddr.Addr
-			addr.Port = 443
-			log.Printf("opening additional ACME listener on %s", addr.String())
-			ln443, err := startListenerTLS("tcp", &addr, certManager)
+			addr.Port = 80
+			log.Printf("Starting HTTP-01 ACME listener")
+			lnHTTP01, err := net.ListenTCP("tcp", &addr)
 			if err != nil {
-				log.Printf("error opening ACME listener: %s", err)
-				pt.SmethodError(bindaddr.MethodName, "ACME listener: "+err.Error())
+				log.Printf("error opening HTTP-01 ACME listener: %s", err)
+				pt.SmethodError(bindaddr.MethodName, "HTTP-01 ACME listener: "+err.Error())
 				continue
 			}
-			listeners = append(listeners, ln443)
-			need443Listener = false
+			go func() {
+				log.Fatal(http.Serve(lnHTTP01, certManager.HTTPHandler(nil)))
+			}()
+			listeners = append(listeners, lnHTTP01)
+			needHTTP01Listener = false
 		}
 
 		var ln net.Listener



More information about the tor-commits mailing list