commit d0686b1c8df037413f32bef891ef90638b75a080 Author: David Fifield david@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-... - 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#htt... + 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
tor-commits@lists.torproject.org