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 */
|
/* Define to 1 to use ipset support */
|
||||||
#undef USE_IPSET
|
#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 */
|
/* Define if you want to use internal select based events */
|
||||||
#undef USE_MINI_EVENT
|
#undef USE_MINI_EVENT
|
||||||
|
|
||||||
|
|
|
||||||
19
configure
vendored
19
configure
vendored
|
|
@ -890,6 +890,7 @@ enable_cachedb
|
||||||
enable_ipsecmod
|
enable_ipsecmod
|
||||||
enable_ipset
|
enable_ipset
|
||||||
with_libmnl
|
with_libmnl
|
||||||
|
enable_explicit_port_randomisation
|
||||||
with_libunbound_only
|
with_libunbound_only
|
||||||
'
|
'
|
||||||
ac_precious_vars='build_alias
|
ac_precious_vars='build_alias
|
||||||
|
|
@ -1579,6 +1580,9 @@ Optional Features:
|
||||||
--enable-ipsecmod Enable ipsecmod module that facilitates
|
--enable-ipsecmod Enable ipsecmod module that facilitates
|
||||||
opportunistic IPsec
|
opportunistic IPsec
|
||||||
--enable-ipset enable ipset module
|
--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:
|
Optional Packages:
|
||||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||||
|
|
@ -21443,6 +21447,21 @@ $as_echo "found in $dir" >&6; }
|
||||||
# nothing
|
# nothing
|
||||||
;;
|
;;
|
||||||
esac
|
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 "$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; }
|
$as_echo_n "checking if ${MAKE:-make} supports $< with implicit rule in scope... " >&6; }
|
||||||
|
|
|
||||||
|
|
@ -1778,6 +1778,15 @@ case "$enable_ipset" in
|
||||||
# nothing
|
# nothing
|
||||||
;;
|
;;
|
||||||
esac
|
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])
|
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
|
||||||
# on openBSD, the implicit rule make $< work.
|
# 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);
|
comm_point_close(pc->cp);
|
||||||
pif = pc->pif;
|
pif = pc->pif;
|
||||||
log_assert(pif->inuse > 0);
|
log_assert(pif->inuse > 0);
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
pif->avail_ports[pif->avail_total - pif->inuse] = pc->number;
|
pif->avail_ports[pif->avail_total - pif->inuse] = pc->number;
|
||||||
|
#endif
|
||||||
pif->inuse--;
|
pif->inuse--;
|
||||||
pif->out[pc->index] = pif->out[pif->inuse];
|
pif->out[pc->index] = pif->out[pif->inuse];
|
||||||
pif->out[pc->index]->index = pc->index;
|
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,
|
static int setup_if(struct port_if* pif, const char* addrstr,
|
||||||
int* avail, int numavail, size_t numfd)
|
int* avail, int numavail, size_t numfd)
|
||||||
{
|
{
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
pif->avail_total = numavail;
|
pif->avail_total = numavail;
|
||||||
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
|
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
|
||||||
if(!pif->avail_ports)
|
if(!pif->avail_ports)
|
||||||
return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
|
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
|
||||||
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
|
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
|
||||||
&pif->addr, &pif->addrlen, &pif->pfxlen))
|
&pif->addr, &pif->addrlen, &pif->pfxlen))
|
||||||
|
|
@ -957,7 +961,9 @@ outside_network_delete(struct outside_network* outnet)
|
||||||
comm_point_delete(pc->cp);
|
comm_point_delete(pc->cp);
|
||||||
free(pc);
|
free(pc);
|
||||||
}
|
}
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
free(outnet->ip4_ifs[i].avail_ports);
|
free(outnet->ip4_ifs[i].avail_ports);
|
||||||
|
#endif
|
||||||
free(outnet->ip4_ifs[i].out);
|
free(outnet->ip4_ifs[i].out);
|
||||||
}
|
}
|
||||||
free(outnet->ip4_ifs);
|
free(outnet->ip4_ifs);
|
||||||
|
|
@ -971,7 +977,9 @@ outside_network_delete(struct outside_network* outnet)
|
||||||
comm_point_delete(pc->cp);
|
comm_point_delete(pc->cp);
|
||||||
free(pc);
|
free(pc);
|
||||||
}
|
}
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
free(outnet->ip6_ifs[i].avail_ports);
|
free(outnet->ip6_ifs[i].avail_ports);
|
||||||
|
#endif
|
||||||
free(outnet->ip6_ifs[i].out);
|
free(outnet->ip6_ifs[i].out);
|
||||||
}
|
}
|
||||||
free(outnet->ip6_ifs);
|
free(outnet->ip6_ifs);
|
||||||
|
|
@ -1135,6 +1143,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
||||||
while(1) {
|
while(1) {
|
||||||
my_if = ub_random_max(outnet->rnd, num_if);
|
my_if = ub_random_max(outnet->rnd, num_if);
|
||||||
pif = &ifs[my_if];
|
pif = &ifs[my_if];
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
my_port = ub_random_max(outnet->rnd, pif->avail_total);
|
my_port = ub_random_max(outnet->rnd, pif->avail_total);
|
||||||
if(my_port < pif->inuse) {
|
if(my_port < pif->inuse) {
|
||||||
/* port already open */
|
/* 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 */
|
/* try to open new port, if fails, loop to try again */
|
||||||
log_assert(pif->inuse < pif->maxout);
|
log_assert(pif->inuse < pif->maxout);
|
||||||
portno = pif->avail_ports[my_port - pif->inuse];
|
portno = pif->avail_ports[my_port - pif->inuse];
|
||||||
|
#else
|
||||||
|
my_port = portno = 0;
|
||||||
|
#endif
|
||||||
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
|
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
|
||||||
portno, &inuse, outnet->rnd);
|
portno, &inuse, outnet->rnd);
|
||||||
if(fd == -1 && !inuse) {
|
if(fd == -1 && !inuse) {
|
||||||
|
|
@ -1169,8 +1181,10 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
||||||
|
|
||||||
/* grab port in interface */
|
/* grab port in interface */
|
||||||
pif->out[pif->inuse] = pend->pc;
|
pif->out[pif->inuse] = pend->pc;
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
pif->avail_ports[my_port - pif->inuse] =
|
pif->avail_ports[my_port - pif->inuse] =
|
||||||
pif->avail_ports[pif->avail_total-pif->inuse-1];
|
pif->avail_ports[pif->avail_total-pif->inuse-1];
|
||||||
|
#endif
|
||||||
pif->inuse++;
|
pif->inuse++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2227,6 +2241,7 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
|
||||||
}
|
}
|
||||||
addr = &pif->addr;
|
addr = &pif->addr;
|
||||||
addrlen = pif->addrlen;
|
addrlen = pif->addrlen;
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
pnum = ub_random_max(outnet->rnd, pif->avail_total);
|
pnum = ub_random_max(outnet->rnd, pif->avail_total);
|
||||||
if(pnum < pif->inuse) {
|
if(pnum < pif->inuse) {
|
||||||
/* port already open */
|
/* 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 */
|
/* unused ports in start part of array */
|
||||||
port = pif->avail_ports[pnum - pif->inuse];
|
port = pif->avail_ports[pnum - pif->inuse];
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
pnum = port = 0;
|
||||||
|
#endif
|
||||||
if(addr_is_ip6(to_addr, to_addrlen)) {
|
if(addr_is_ip6(to_addr, to_addrlen)) {
|
||||||
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
|
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
|
||||||
sa.sin6_port = (in_port_t)htons((uint16_t)port);
|
sa.sin6_port = (in_port_t)htons((uint16_t)port);
|
||||||
|
|
@ -2459,7 +2476,10 @@ if_get_mem(struct port_if* pif)
|
||||||
{
|
{
|
||||||
size_t s;
|
size_t s;
|
||||||
int i;
|
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;
|
sizeof(struct port_comm*)*pif->maxout;
|
||||||
for(i=0; i<pif->inuse; i++)
|
for(i=0; i<pif->inuse; i++)
|
||||||
s += sizeof(*pif->out[i]) +
|
s += sizeof(*pif->out[i]) +
|
||||||
|
|
|
||||||
|
|
@ -172,11 +172,13 @@ struct port_if {
|
||||||
* if 0, no randomisation. */
|
* if 0, no randomisation. */
|
||||||
int pfxlen;
|
int pfxlen;
|
||||||
|
|
||||||
|
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||||
/** the available ports array. These are unused.
|
/** the available ports array. These are unused.
|
||||||
* Only the first total-inuse part is filled. */
|
* Only the first total-inuse part is filled. */
|
||||||
int* avail_ports;
|
int* avail_ports;
|
||||||
/** the total number of available ports (size of the array) */
|
/** the total number of available ports (size of the array) */
|
||||||
int avail_total;
|
int avail_total;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** array of the commpoints currently in use.
|
/** array of the commpoints currently in use.
|
||||||
* allocated for max number of fds, first part in use. */
|
* allocated for max number of fds, first part in use. */
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue