Enable IP_BIND_ADDRESS_NO_PORT if supported

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
Alex Xu (Hello71) 2022-05-21 15:21:25 -04:00 committed by David Goulet
parent da48104c99
commit 1d9166c8c9
3 changed files with 37 additions and 0 deletions

View File

@ -0,0 +1,5 @@
o Minor features (relays):
- Set the Linux-specific IP_BIND_ADDRESS_NO_PORT option on outgoing
sockets, allowing relays using OutboundBindAddress to make more outgoing
connections than ephemeral ports, as long as they are to separate
destinations. Related to issue 40597; patch by Alex Xu (Hello71).

View File

@ -2229,6 +2229,30 @@ connection_connect_sockaddr,(connection_t *conn,
*/
connection_check_oos(get_n_open_sockets(), 0);
/* From ip(7): Inform the kernel to not reserve an ephemeral port when using
* bind(2) with a port number of 0. The port will later be automatically
* chosen at connect(2) time, in a way that allows sharing a source port as
* long as the 4-tuple is unique.
*
* This is needed for relays using OutboundBindAddresses because the port
* value in the bind address is set to 0. */
#ifdef IP_BIND_ADDRESS_NO_PORT
static int try_ip_bind_address_no_port = 1;
if (bindaddr && try_ip_bind_address_no_port &&
setsockopt(s, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &(int){1}, sizeof(int))) {
if (errno == EINVAL) {
log_notice(LD_NET, "Tor was built with support for "
"IP_BIND_ADDRESS_NO_PORT, but the current kernel "
"doesn't support it. This might cause Tor to run out "
"of ephemeral ports more quickly.");
try_ip_bind_address_no_port = 0;
} else {
log_warn(LD_NET, "Error setting IP_BIND_ADDRESS_NO_PORT on new "
"connection: %s", tor_socket_strerror(errno));
}
}
#endif
if (bindaddr && bind(s, bindaddr, bindaddr_len) < 0) {
*socket_error = tor_socket_errno(s);
log_warn(LD_NET,"Error binding network socket: %s",

View File

@ -954,6 +954,14 @@ sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
return rc;
#endif /* defined(IPV6_V6ONLY) */
#ifdef IP_BIND_ADDRESS_NO_PORT
rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
SCMP_CMP(2, SCMP_CMP_EQ, IP_BIND_ADDRESS_NO_PORT));
if (rc)
return rc;
#endif
return 0;
}