From: Remi Gacogne Date: Mon, 8 Jan 2024 11:51:07 +0000 (+0100) Subject: dnsdist: Enable PMTU discovery and disable fragmentation on QUIC binds X-Git-Tag: auth-4.9.0-alpha1~11^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F13676%2Fhead;p=thirdparty%2Fpdns.git dnsdist: Enable PMTU discovery and disable fragmentation on QUIC binds --- diff --git a/pdns/dnsdist.cc b/pdns/dnsdist.cc index e4283a84cd..378cd751c3 100644 --- a/pdns/dnsdist.cc +++ b/pdns/dnsdist.cc @@ -2360,10 +2360,20 @@ static void setupLocalSocket(ClientState& clientState, const ComboAddress& addr, } } - /* 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 (!tcp && !clientState.dnscryptCtx) { + const bool isQUIC = clientState.doqFrontend != nullptr || clientState.doh3Frontend != nullptr; + if (isQUIC) { + /* disable fragmentation and force PMTU discovery for QUIC-enabled sockets */ + try { + setSocketForcePMTU(socket, addr.sin4.sin_family); + } + catch (const std::exception& e) { + warnlog("Failed to set IP_MTU_DISCOVER on QUIC server socket for local address '%s': %s", addr.toStringWithPort(), e.what()); + } + } + else if (!tcp && !clientState.dnscryptCtx) { + /* 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. */ try { setSocketIgnorePMTU(socket, addr.sin4.sin_family); } diff --git a/pdns/iputils.cc b/pdns/iputils.cc index 2f629cbfa1..55d8daad5a 100644 --- a/pdns/iputils.cc +++ b/pdns/iputils.cc @@ -192,6 +192,27 @@ void setSocketIgnorePMTU([[maybe_unused]] int sockfd, [[maybe_unused]] int famil } } +void setSocketForcePMTU([[maybe_unused]] int sockfd, [[maybe_unused]] int family) +{ + if (family == AF_INET) { +#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) + /* IP_PMTUDISC_DO enables Path MTU discovery and prevents fragmentation */ + SSetsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, IP_PMTUDISC_DO); +#elif defined(IP_DONTFRAG) + /* at least this prevents fragmentation */ + SSetsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, 1); +#endif /* defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DO) */ + } + else { +#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) + /* IPV6_PMTUDISC_DO enables Path MTU discovery and prevents fragmentation */ + SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IPV6_PMTUDISC_DO); +#elif defined(IPV6_DONTFRAG) + /* at least this prevents fragmentation */ + SSetsockopt(sockfd, IPPROTO_IPV6, IPV6_DONTFRAG, 1); +#endif /* defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DO) */ + } +} bool setReusePort(int sockfd) { diff --git a/pdns/iputils.hh b/pdns/iputils.hh index 2a5b21544e..ade4c82a30 100644 --- a/pdns/iputils.hh +++ b/pdns/iputils.hh @@ -1699,6 +1699,7 @@ 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, int family); +void setSocketForcePMTU(int sockfd, int family); bool setReusePort(int sockfd); #if defined(IP_PKTINFO)