From 90f9fbc0dd64c9913f1ee40a435c2316fdb1cb4f Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Mon, 21 Jan 2019 15:40:38 +0100 Subject: [PATCH] Ignore Path MTU Discovery on UDP server socket It might help prevent Path MTU poisoning attacks. --- pdns/dnsdist.cc | 11 +++++++++++ pdns/iputils.cc | 19 +++++++++++++++++++ pdns/iputils.hh | 1 + pdns/nameserver.cc | 9 +++++++++ pdns/pdns_recursor.cc | 12 +++++++++++- 5 files changed, 51 insertions(+), 1 deletion(-) diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index f7bfc1dee..64196d6fc 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -2218,6 +2218,17 @@ static void setUpLocalBind(std::unique_ptr& cs) #endif } + if (!cs->tcp) { + if (cs->local.isIPv4()) { + try { + setSocketIgnorePMTU(cs->udpFD); + } + catch(const std::exception& e) { + warnlog("Failed to set IP_MTU_DISCOVER on UDP server socket for local address '%s': %s", cs->local.toStringWithPort(), e.what()); + } + } + } + const std::string& itf = cs->interface; if (!itf.empty()) { #ifdef SO_BINDTODEVICE diff --git a/pdns/iputils.cc b/pdns/iputils.cc index 84425e66c..de94bb2e5 100644 --- a/pdns/iputils.cc +++ b/pdns/iputils.cc @@ -136,6 +136,25 @@ int SSetsockopt(int sockfd, int level, int opname, int value) return ret; } +void setSocketIgnorePMTU(int sockfd) +{ +#ifdef IP_PMTUDISC_OMIT + /* Linux 3.15+ has IP_PMTUDISC_OMIT, which discards PMTU information to prevent + poisoning, but still allows fragmentation if the packet size exceeds the + outgoing interface MTU, which is good. + */ + try { + SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_OMIT); + return; + } + catch(const std::exception& e) { + /* failed, let's try IP_PMTUDISC_DONT instead */ + } +#endif /* IP_PMTUDISC_OMIT */ + + /* IP_PMTUDISC_DONT disables Path MTU discovery */ + SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT); +} bool HarvestTimestamp(struct msghdr* msgh, struct timeval* tv) { diff --git a/pdns/iputils.hh b/pdns/iputils.hh index 694c64740..457b2b597 100644 --- a/pdns/iputils.hh +++ b/pdns/iputils.hh @@ -1046,6 +1046,7 @@ int SBind(int sockfd, const ComboAddress& local); int SAccept(int sockfd, ComboAddress& remote); int SListen(int sockfd, int limit); int SSetsockopt(int sockfd, int level, int opname, int value); +void setSocketIgnorePMTU(int sockfd); #if defined(IP_PKTINFO) #define GEN_IP_PKTINFO IP_PKTINFO diff --git a/pdns/nameserver.cc b/pdns/nameserver.cc index 995420144..558123917 100644 --- a/pdns/nameserver.cc +++ b/pdns/nameserver.cc @@ -123,6 +123,15 @@ void UDPNameserver::bindIPv4() if (!setSocketTimestamps(s)) g_log<