]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Allow the kernel to provide random source ports. 134/head
authorFlorian Obser <florian@narrans.de>
Fri, 10 Jan 2020 12:55:55 +0000 (13:55 +0100)
committerFlorian Obser <florian@narrans.de>
Thu, 20 Feb 2020 13:54:06 +0000 (14:54 +0100)
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.

config.h.in
configure
configure.ac
services/outside_network.c
services/outside_network.h

index 78d47fedc1397e59f47d17aae37c0a5165479e3b..4f419604c525fcdb5143b2c095a7e61835b8d096 100644 (file)
 /* 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
 
index bdec1f0024c714c21d4cf24e7ab1adc6815201d0..744defe211f91bef8a700fbb003f579ebe486465 100755 (executable)
--- a/configure
+++ b/configure
@@ -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; }
index 3e00c999c8039e6798139bcb42e5963371d42e6b..d58c825d0372ad088a9f2f23a5aaf242763b85f2 100644 (file)
@@ -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.
index d3ebe04f6602564e99e8e2c20690c06b813d27b3..1e83bf3a1cc36c90436887c65b38f7ff48782669 100644 (file)
@@ -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]) + 
index 3456a3da38b0b67941d70da8d05551680fff7006..f12b2e5bee56288ab30bf215e1f209bc6db24981 100644 (file)
@@ -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. */