From aaa36f1dd1719119fcf54bfc9e44d929ad760a6f Mon Sep 17 00:00:00 2001 From: Vladimir Dubrovin <3proxy@3proxy.ru> Date: Sun, 25 Oct 2026 16:33:39 +0300 Subject: [PATCH] Outgoing connections bound with IP_BIND_ADDRESS_NO_PORT The socket of a connection to the destination is bound to the external address before connect(), with port 0 unless a range is given. bind() then takes an ephemeral port for the socket alone: not one in use towards another destination, nor one of a connection still closing in TIME_WAIT, which connect() would reuse. With many connections the range runs out and bind() fails, result 12, or searches long for a port: 7 ms a call was seen. The more connections are open at once, the sooner: with event loops, serving more of them at once, the client of every tenth connection or so of a saturated relay got its end at once. Where the system has IP_BIND_ADDRESS_NO_PORT (Linux 4.2), the port is left to connect() for a socket that is going to connect: chosen for the pair with the destination, together with IP_LOCAL_PORT_RANGE when a range is given. Co-Authored-By: Claude Opus 5.5 --- src/common.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/common.c b/src/common.c index ee2cece..e19fbb3 100644 --- a/src/common.c +++ b/src/common.c @@ -780,6 +780,22 @@ int doconnect(struct clientparam * param){ param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg)); #endif if(extbindtodevice(param, param->remsock)) return 12; +#ifdef IP_BIND_ADDRESS_NO_PORT + /* A port the kernel chooses is chosen by connect(), for the pair with + the destination: one in use towards another destination, or closing + from an earlier connection, does as well. bind() would take one of + its own, and with many connections find none left, or search long + for it. */ + if((param->operation >= 256 || (param->operation & CONNECT) || param->redirected) +# ifdef WITH_UN + && *SAFAMILY(¶m->sinsl) != AF_UNIX +# endif + ){ + int one = 1; + + param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, (char *)&one, sizeof(one)); + } +#endif #ifdef WITH_UN if(*SAFAMILY(¶m->sinsl) != AF_UNIX) #endif