This is a port of commit e3f3054f8b74caa639a6d9be09702693af9a70e7 from meek. In the previous commit, we changed from separate Listen and Serve steps to always calling ListenAndServe. However, we would really like to immediately get feedback if any errors happen in the Listen step inside the call, because it's much better for debugging if those errors get reported to tor through SMETHOD-ERROR--rather than reporting success to tor and actually logging an error only in the snowflake log. So we wait 100 ms for an error to occur before deciding that the Listen succeeded. We don't need to apply this hack to the ACME HTTP-01 listener, because it's a plaintext listener. Unlike in the TLS case, there isn't any internal magic that the net library does that we have to rely on. We just call net.ListenTCP and check for an error. |
||
---|---|---|
.. | ||
README.md | ||
server.go | ||
server_test.go | ||
stats.go | ||
torrc |
This is the server transport plugin for Snowflake. The actual transport protocol it uses is WebSocket. In Snowflake, the client connects to the proxy using WebRTC, and the proxy connects to the server (this program) using WebSocket.
Setup
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 80 without running as root:
setcap 'cap_net_bind_service=+ep' /usr/local/bin/snowflake-server
Here is a short example of configuring your torrc file to run the Snowflake server under Tor:
SocksPort 0
ORPort 9001
ExtORPort auto
BridgeRelay 1
ServerTransportListenAddr snowflake 0.0.0.0:443
ServerTransportPlugin snowflake exec ./server --acme-hostnames snowflake.example --acme-email admin@snowflake.example --log /var/log/tor/snowflake-server.log
The domain names given to the --acme-hostnames
option
should resolve to the IP address of the server.
You can give more than one, separated by commas.
TLS
The server uses TLS WebSockets by default: wss:// not ws://.
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 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.
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 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.
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:
setcap 'cap_net_bind_service=+ep' /usr/local/bin/snowflake-server