From b09e8296581878ba2410ea48acf8a045dc4a5c22 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Vladim=C3=ADr=20=C4=8Cun=C3=A1t?= Date: Tue, 15 Sep 2020 10:57:37 +0200 Subject: [PATCH] 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. --- NEWS | 1 + daemon/io.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) 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))) -- 2.47.2