From db63b4b63158d95399fa9109b9802b195df515f8 Mon Sep 17 00:00:00 2001 From: Otto Date: Tue, 6 Apr 2021 10:41:39 +0200 Subject: [PATCH] Also disable PMTU for v6 --- pdns/dnsdist.cc | 4 ++-- pdns/iputils.cc | 41 ++++++++++++++++++++++++++++++++--------- pdns/iputils.hh | 2 +- pdns/nameserver.cc | 12 +++++------- pdns/pdns_recursor.cc | 12 +++++------- 5 files changed, 45 insertions(+), 26 deletions(-) diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index 5eee451c37..f474c79c91 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -1903,9 +1903,9 @@ static void setUpLocalBind(std::unique_ptr& cs) /* Only set this on IPv4 UDP sockets. Don't set it for DNSCrypt binds. DNSCrypt pads queries for privacy purposes, so we do receive large, sometimes fragmented datagrams. */ - if (!cs->tcp && cs->local.isIPv4() && !cs->dnscryptCtx) { + if (!cs->tcp && !cs->dnscryptCtx) { try { - setSocketIgnorePMTU(cs->udpFD); + setSocketIgnorePMTU(cs->udpFD, cs->local.sin4.sin_family); } 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()); diff --git a/pdns/iputils.cc b/pdns/iputils.cc index 019eff2dd2..216945b7cc 100644 --- a/pdns/iputils.cc +++ b/pdns/iputils.cc @@ -136,28 +136,51 @@ int SSetsockopt(int sockfd, int level, int opname, int value) return ret; } -void setSocketIgnorePMTU(int sockfd) +void setSocketIgnorePMTU(int sockfd, int family) { + if (family == AF_INET) { #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) #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 */ - } + 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); + SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DONT); #endif /* defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) */ + } + else { + #if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT) +#ifdef IPV6_PMTUDISC_OMIT + /* Linux 3.15+ has IPV6_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_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_OMIT); + return; + } + catch(const std::exception& e) { + /* failed, let's try IP_PMTUDISC_DONT instead */ + } +#endif /* IPV6_PMTUDISC_OMIT */ + + /* IPV6_PMTUDISC_DONT disables Path MTU discovery */ + SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_DONT); +#endif /* defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT) */ + } } + bool setReusePort(int sockfd) { #if defined(SO_REUSEPORT_LB) diff --git a/pdns/iputils.hh b/pdns/iputils.hh index b0999f01ff..92055f8c2c 100644 --- a/pdns/iputils.hh +++ b/pdns/iputils.hh @@ -1433,7 +1433,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); +void setSocketIgnorePMTU(int sockfd, int family); bool setReusePort(int sockfd); #if defined(IP_PKTINFO) diff --git a/pdns/nameserver.cc b/pdns/nameserver.cc index a09953e635..3f03eb3ff5 100644 --- a/pdns/nameserver.cc +++ b/pdns/nameserver.cc @@ -128,13 +128,11 @@ void UDPNameserver::bindAddresses() if (!setSocketTimestamps(s)) g_log<