From: Vladimír Čunát Date: Tue, 15 Sep 2020 08:57:37 +0000 (+0200) Subject: daemon/io: avoid PMTU discovery for IPv4 server side X-Git-Tag: v5.2.0~22^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b09e8296581878ba2410ea48acf8a045dc4a5c22;p=thirdparty%2Fknot-resolver.git daemon/io: avoid PMTU discovery for IPv4 server side This seems generally considered to be a good thing (for DNS servers). We don't do it on client side; I can't see an easy way there. --- diff --git a/NEWS b/NEWS index 52c0bdb61..02680d599 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ Improvements ------------ - net: split the EDNS buffer size into upstream and downstream (!1026) - lua-http doh: answer to /dns-query endpoint as well as /doh (!1069) +- improve resiliency against UDP fragmentation attacks (disable PMTUD) (!1061) Bugfixes -------- diff --git a/daemon/io.c b/daemon/io.c index 8c929ecf2..7b5f910cb 100644 --- a/daemon/io.c +++ b/daemon/io.c @@ -144,6 +144,23 @@ int io_bind(const struct sockaddr *addr, int type, const endpoint_flags_t *flags if (setsockopt(fd, optlevel, optname, &yes, sizeof(yes))) return kr_error(errno); } + + /* Linux 3.15 has IP_PMTUDISC_OMIT which makes sockets + * ignore PMTU information and send packets with DF=0. + * This mitigates DNS fragmentation attacks by preventing + * forged PMTU information. FreeBSD already has same semantics + * without setting the option. + https://gitlab.nic.cz/knot/knot-dns/-/issues/640 + */ +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT) + int omit = IP_PMTUDISC_OMIT; + if (type == SOCK_DGRAM && addr->sa_family == AF_INET + && setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &omit, sizeof(omit))) { + kr_log_error( + "[ io ] failed to disable Path MTU discovery for %s UDP: %s\n", + kr_straddr(addr), strerror(errno)); + } +#endif } if (bind(fd, addr, kr_sockaddr_len(addr)))