From 6a4ea692d4357487b92e6c12e722a42b3430050b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cristian=20Rodr=C3=ADguez?= Date: Sat, 23 Apr 2022 23:08:45 +0000 Subject: [PATCH 1/2] Set IP_BIND_ADDRESS_NO_PORT on outbound tcp sockets When bound to a local address the kernel does not know if the socket will listen() or connect() and must reserve a port inmediately after bind() effectively limiting the random port range to ~32k. when IP_BIND_ADDRESS_NO_PORT is set, the kernel delays source port allocation until the time the complete 4-tuple is known allowing a much larger number of combinations --- services/outside_network.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/services/outside_network.c b/services/outside_network.c index 4578bf8fc..2a081ad71 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -247,6 +247,9 @@ pick_outgoing_tcp(struct pending_tcp* pend, struct waiting_tcp* w, int s) if(addr_is_ip6(&pi->addr, pi->addrlen)) ((struct sockaddr_in6*)&pi->addr)->sin6_port = 0; else ((struct sockaddr_in*)&pi->addr)->sin_port = 0; +#ifdef IP_BIND_ADDRESS_NO_PORT + setsockopt(s, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &(int) {1}, sizeof(int)); +#endif if(bind(s, (struct sockaddr*)&pi->addr, pi->addrlen) != 0) { #ifndef USE_WINSOCK #ifdef EADDRNOTAVAIL From e5f66b4902d80cbcb58a8623e1da41f7476dcfb9 Mon Sep 17 00:00:00 2001 From: George Thessalonikefs Date: Mon, 4 Jul 2022 12:46:17 +0200 Subject: [PATCH 2/2] - For #668: relocate and make code more portable. --- services/outside_network.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index e1ed1c451..3f479a3a3 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -247,9 +247,6 @@ pick_outgoing_tcp(struct pending_tcp* pend, struct waiting_tcp* w, int s) if(addr_is_ip6(&pi->addr, pi->addrlen)) ((struct sockaddr_in6*)&pi->addr)->sin6_port = 0; else ((struct sockaddr_in*)&pi->addr)->sin_port = 0; -#ifdef IP_BIND_ADDRESS_NO_PORT - setsockopt(s, SOL_IP, IP_BIND_ADDRESS_NO_PORT, &(int) {1}, sizeof(int)); -#endif if(bind(s, (struct sockaddr*)&pi->addr, pi->addrlen) != 0) { #ifndef USE_WINSOCK #ifdef EADDRNOTAVAIL @@ -274,7 +271,7 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int s; int af; char* err; -#ifdef SO_REUSEADDR +#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT) int on = 1; #endif #ifdef INET6 @@ -320,7 +317,13 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, " setsockopt(TCP_MAXSEG) unsupported"); #endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */ } - +#ifdef IP_BIND_ADDRESS_NO_PORT + if(setsockopt(s, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, (void*)&on, + (socklen_t)sizeof(on)) < 0) { + verbose(VERB_ALGO, "outgoing tcp:" + " setsockopt(.. IP_BIND_ADDRESS_NO_PORT ..) failed"); + } +#endif /* IP_BIND_ADDRESS_NO_PORT */ return s; }