By forwarding the method to the inner smux.Stream. This is to prevent
io.Copy in the top-level proxy function from allocating a buffer per
client.
The smux.Stream WriteTo method returns io.EOF on success, contrary to
the contract of io.Copy that says it should return nil. Ignore io.EOF in
the proxy loop to avoid a log message.
/anti-censorship/pluggable-transports/snowflake/-/issues/40177
Due to a bug (#40098), legacy oneshot connections have not worked for
awhile. Connections without the turbotunnel token would cause the server
to crash. This fixes that bug by removing support altogether and simply
closes the connection.
This should increase the maximum amount of inflight data and hopefully
the performance of Snowflake, especially for clients geographically
distant from proxies and the server.
This fixes a stats collection bug where we were converting client
addresses between a string and net.Addr using the clientAddr function
multiple times, resulting in an empty string for all addresses.
Introduce a waitgroup and done channel to ensure that both the read and
write gorouting for turbotunnel connections terminate when the
connection is closed.
Snowflake copies data between the OR connection and the KCP stream,
meaning that in most cases the copy loops will only terminate once the
OR connection times out. In this case the OR connection is already
closed and so calls to CloseRead and CloseWrite will generate errors.
The difficulty here is that the whole point of turbotunnel sessions is
that they are not necessarily tied to a single WebSocket connection, nor
even a single client IP address. We use a heuristic: whenever a
WebSocket connection starts that has a new ClientID, we store a mapping
from that ClientID to the IP address attached to the WebSocket
connection in a lookup table. Later, when enough packets have arrived to
establish a turbotunnel session, we recover the ClientID associated with
the session (which kcp-go has stored in the RemoteAddr field), and look
it up in the table to get an IP address. We introduce a new data type,
clientIDMap, to store the clientID-to-IP mapping during the short time
between when a WebSocket connection starts and handleSession receives a
fully fledged KCP session.
The client opts into turbotunnel mode by sending a magic token at the
beginning of each WebSocket connection (before sending even the
ClientID). The token is just a random byte string I generated. The
server peeks at the token and, if it matches, uses turbotunnel mode.
Otherwise, it unreads the token and continues in the old
one-session-per-WebSocket mode.
Some proxies currently send ?client_ip=0.0.0.0 because of an error in
how they attempt to grep the address from the client's SDP. That's
inflating our "%d/%d connections had client_ip" logs. Instead, treat
these cases as if the IP address were absent.
https://bugs.torproject.org/33157https://bugs.torproject.org/33385
Rename websocketconn.WebSocketConn to websocketconn.Conn, and
websocketconn.NewWebSocketConn to websocketconn.New
Following the guidelines at
https://blog.golang.org/package-names#TOC_3%2e
These functions are called for their side effect of sending a PT error
message on stdout; they also return a representation of the error
message as an error object for the caller to use if it wishes. These
functions *always* return a non-nil error object; it is not something to
be logged, any more than the return value of errors.New is.
The mistaken logging was added in
https://bugs.torproject.org/31794b26c7a7a733ec9dd19faed3d42e1ec
- Error strings are no longer capitalized nor end with punctuation
- Alias import
- Remove extraneous initilisation code (No need to provide zero value
for variables, because the compiler does that anyway)