Use IP_BIND_ADDRESS_NO_PORT when dialing the ORPort on Linux
All the programs in the snowflake server chain
(snowflake-server, haproxy, extor-static-cookie)
bind to an explicit source IP address
before connecting to the next link in the chain,
in order free up more 4-tuples: because if everything were on 127.0.0.1
there would not be enough ephemeral port numbers for as many connections as we have.
tor itself also binds to a source address before connecting to middle relays
when the OutboundBindAddress
option is set,
as it is on the snowflake-01 bridge.
There is a socket option IP_BIND_ADDRESS_NO_PORT
you can set
when doing this bind-before-connect pattern that enables better port number reuse
and helps conserve ephemeral ports further.
But there is a problem when some programs use IP_BIND_ADDRESS_NO_PORT
and some do not:
the ones that do will be starved of ephemeral ports.
See extensive past analysis:
- #40198 (closed)
- #40201 (closed)
- https://forum.torproject.net/t/tor-relays-inet-csk-bind-conflict/5757/10
- https://blog.cloudflare.com/the-quantum-state-of-a-tcp-port/
Because formerly tor did not use IP_BIND_ADDRESS_NO_PORT
,
we had fallen into an equilibrium of all the snowflake programs
similarly not using the socket option.
But now that tor 0.4.7.13
always uses IP_BIND_ADDRESS_NO_PORT
when OutboundBindAddress
is set,
we need to flip the other way, and make all the snowflake programs set IP_BIND_ADDRESS_NO_PORT
.
See #40270 (closed).
The necessary change has already been made in extor-static-cookie.
In haproxy, it only requires a configuration change to start using
IP_BIND_ADDRESS_NO_PORT
.
This merge request is to make the necessary change in snowflake-server.
IP_BIND_ADDRESS_NO_PORT
is a Linux-only option.
The patch defines a dialerControl
function that sets
IP_BIND_ADDRESS_NO_PORT
on Linux and is a no-op on other platforms.