mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
Allow the kernel to provide random source ports.
On some operating systems, for example OpenBSD since some decades, the kernel binds to a random source port if asked for any port (port number 0). There is no need to replicate this functionality in userland.
This commit is contained in:
parent
d2a843b422
commit
5aaa5e253d
5 changed files with 56 additions and 2 deletions
|
|
@ -805,6 +805,10 @@
|
|||
/* Define to 1 to use ipset support */
|
||||
#undef USE_IPSET
|
||||
|
||||
/* Define to 1 to disable explict UDP source port randomisation and rely on the
|
||||
kernel to provide random source ports */
|
||||
#undef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
|
||||
/* Define if you want to use internal select based events */
|
||||
#undef USE_MINI_EVENT
|
||||
|
||||
|
|
|
|||
19
configure
vendored
19
configure
vendored
|
|
@ -890,6 +890,7 @@ enable_cachedb
|
|||
enable_ipsecmod
|
||||
enable_ipset
|
||||
with_libmnl
|
||||
enable_explicit_port_randomisation
|
||||
with_libunbound_only
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
|
|
@ -1579,6 +1580,9 @@ Optional Features:
|
|||
--enable-ipsecmod Enable ipsecmod module that facilitates
|
||||
opportunistic IPsec
|
||||
--enable-ipset enable ipset module
|
||||
--disable-explicit-port-randomisation
|
||||
disable explicit source port randomisation and rely
|
||||
on the kernel to provide random source ports
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
|
|
@ -21443,6 +21447,21 @@ $as_echo "found in $dir" >&6; }
|
|||
# nothing
|
||||
;;
|
||||
esac
|
||||
# Check whether --enable-explicit-port-randomisation was given.
|
||||
if test "${enable_explicit_port_randomisation+set}" = set; then :
|
||||
enableval=$enable_explicit_port_randomisation;
|
||||
fi
|
||||
|
||||
case "$enable_explicit_port_randomisation" in
|
||||
no)
|
||||
|
||||
$as_echo "#define DISABLE_EXPLICIT_PORT_RANDOMISATION 1" >>confdefs.h
|
||||
|
||||
;;
|
||||
yes|*)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if ${MAKE:-make} supports $< with implicit rule in scope" >&5
|
||||
$as_echo_n "checking if ${MAKE:-make} supports $< with implicit rule in scope... " >&6; }
|
||||
|
|
|
|||
|
|
@ -1778,6 +1778,15 @@ case "$enable_ipset" in
|
|||
# nothing
|
||||
;;
|
||||
esac
|
||||
AC_ARG_ENABLE(explicit-port-randomisation, AC_HELP_STRING([--disable-explicit-port-randomisation], [disable explicit source port randomisation and rely on the kernel to provide random source ports]))
|
||||
case "$enable_explicit_port_randomisation" in
|
||||
no)
|
||||
AC_DEFINE([DISABLE_EXPLICIT_PORT_RANDOMISATION], [1], [Define this to enable kernel based UDP source port randomization.])
|
||||
;;
|
||||
yes|*)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
|
||||
# on openBSD, the implicit rule make $< work.
|
||||
|
|
|
|||
|
|
@ -514,7 +514,9 @@ portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc)
|
|||
comm_point_close(pc->cp);
|
||||
pif = pc->pif;
|
||||
log_assert(pif->inuse > 0);
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
pif->avail_ports[pif->avail_total - pif->inuse] = pc->number;
|
||||
#endif
|
||||
pif->inuse--;
|
||||
pif->out[pc->index] = pif->out[pif->inuse];
|
||||
pif->out[pc->index]->index = pc->index;
|
||||
|
|
@ -727,10 +729,12 @@ create_pending_tcp(struct outside_network* outnet, size_t bufsize)
|
|||
static int setup_if(struct port_if* pif, const char* addrstr,
|
||||
int* avail, int numavail, size_t numfd)
|
||||
{
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
pif->avail_total = numavail;
|
||||
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
|
||||
if(!pif->avail_ports)
|
||||
return 0;
|
||||
#endif
|
||||
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
|
||||
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
|
||||
&pif->addr, &pif->addrlen, &pif->pfxlen))
|
||||
|
|
@ -957,7 +961,9 @@ outside_network_delete(struct outside_network* outnet)
|
|||
comm_point_delete(pc->cp);
|
||||
free(pc);
|
||||
}
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
free(outnet->ip4_ifs[i].avail_ports);
|
||||
#endif
|
||||
free(outnet->ip4_ifs[i].out);
|
||||
}
|
||||
free(outnet->ip4_ifs);
|
||||
|
|
@ -971,7 +977,9 @@ outside_network_delete(struct outside_network* outnet)
|
|||
comm_point_delete(pc->cp);
|
||||
free(pc);
|
||||
}
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
free(outnet->ip6_ifs[i].avail_ports);
|
||||
#endif
|
||||
free(outnet->ip6_ifs[i].out);
|
||||
}
|
||||
free(outnet->ip6_ifs);
|
||||
|
|
@ -1135,6 +1143,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
|||
while(1) {
|
||||
my_if = ub_random_max(outnet->rnd, num_if);
|
||||
pif = &ifs[my_if];
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
my_port = ub_random_max(outnet->rnd, pif->avail_total);
|
||||
if(my_port < pif->inuse) {
|
||||
/* port already open */
|
||||
|
|
@ -1146,6 +1155,9 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
|||
/* try to open new port, if fails, loop to try again */
|
||||
log_assert(pif->inuse < pif->maxout);
|
||||
portno = pif->avail_ports[my_port - pif->inuse];
|
||||
#else
|
||||
my_port = portno = 0;
|
||||
#endif
|
||||
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
|
||||
portno, &inuse, outnet->rnd);
|
||||
if(fd == -1 && !inuse) {
|
||||
|
|
@ -1169,8 +1181,10 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
|||
|
||||
/* grab port in interface */
|
||||
pif->out[pif->inuse] = pend->pc;
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
pif->avail_ports[my_port - pif->inuse] =
|
||||
pif->avail_ports[pif->avail_total-pif->inuse-1];
|
||||
#endif
|
||||
pif->inuse++;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2227,6 +2241,7 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
|
|||
}
|
||||
addr = &pif->addr;
|
||||
addrlen = pif->addrlen;
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
pnum = ub_random_max(outnet->rnd, pif->avail_total);
|
||||
if(pnum < pif->inuse) {
|
||||
/* port already open */
|
||||
|
|
@ -2235,7 +2250,9 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
|
|||
/* unused ports in start part of array */
|
||||
port = pif->avail_ports[pnum - pif->inuse];
|
||||
}
|
||||
|
||||
#else
|
||||
pnum = port = 0;
|
||||
#endif
|
||||
if(addr_is_ip6(to_addr, to_addrlen)) {
|
||||
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
|
||||
sa.sin6_port = (in_port_t)htons((uint16_t)port);
|
||||
|
|
@ -2459,7 +2476,10 @@ if_get_mem(struct port_if* pif)
|
|||
{
|
||||
size_t s;
|
||||
int i;
|
||||
s = sizeof(*pif) + sizeof(int)*pif->avail_total +
|
||||
s = sizeof(*pif) +
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
sizeof(int)*pif->avail_total +
|
||||
#endif
|
||||
sizeof(struct port_comm*)*pif->maxout;
|
||||
for(i=0; i<pif->inuse; i++)
|
||||
s += sizeof(*pif->out[i]) +
|
||||
|
|
|
|||
|
|
@ -172,11 +172,13 @@ struct port_if {
|
|||
* if 0, no randomisation. */
|
||||
int pfxlen;
|
||||
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
/** the available ports array. These are unused.
|
||||
* Only the first total-inuse part is filled. */
|
||||
int* avail_ports;
|
||||
/** the total number of available ports (size of the array) */
|
||||
int avail_total;
|
||||
#endif
|
||||
|
||||
/** array of the commpoints currently in use.
|
||||
* allocated for max number of fds, first part in use. */
|
||||
|
|
|
|||
Loading…
Reference in a new issue