]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Disable the Path MTU Discover on UDP Sockets
authorOndřej Surý <ondrej@sury.org>
Wed, 28 Jul 2021 13:55:46 +0000 (15:55 +0200)
committerMichał Kępień <michal@isc.org>
Tue, 10 Aug 2021 10:46:54 +0000 (12:46 +0200)
Instead of disabling the fragmentation on the UDP sockets, we now
disable the Path MTU Discovery by setting IP(V6)_MTU_DISCOVER socket
option to IP_PMTUDISC_OMIT on Linux and disabling IP(V6)_DONTFRAG socket
option on FreeBSD.  This option sets DF=0 in the IP header and also
ignores the Path MTU Discovery.

As additional mitigation on Linux, we recommend setting
net.ipv4.ip_no_pmtu_disc to Mode 3:

    Mode 3 is a hardend pmtu discover mode. The kernel will only accept
    fragmentation-needed errors if the underlying protocol can verify
    them besides a plain socket lookup. Current protocols for which pmtu
    events will be honored are TCP, SCTP and DCCP as they verify
    e.g. the sequence number or the association. This mode should not be
    enabled globally but is only intended to secure e.g. name servers in
    namespaces where TCP path mtu must still work but path MTU
    information of other protocols should be discarded. If enabled
    globally this mode could break other protocols.

lib/isc/netmgr/netmgr-int.h
lib/isc/netmgr/netmgr.c
lib/isc/netmgr/udp.c
lib/isc/unix/socket.c

index 765ac925b7d04a46ad16939ba58ac6b3b4a2495e..7a31b74e977b1237db52647a1f44657aa2eced9e 100644 (file)
@@ -1403,9 +1403,10 @@ isc__nm_socket_incoming_cpu(uv_os_sock_t fd);
  */
 
 isc_result_t
-isc__nm_socket_dontfrag(uv_os_sock_t fd, sa_family_t sa_family);
+isc__nm_socket_disable_pmtud(uv_os_sock_t fd, sa_family_t sa_family);
 /*%<
- * Set the SO_IP_DONTFRAG (or equivalent) socket option of the fd if available
+ * Disable the Path MTU Discovery, either by disabling IP(V6)_DONTFRAG socket
+ * option, or setting the IP(V6)_MTU_DISCOVER socket option to IP_PMTUDISC_OMIT
  */
 
 isc_result_t
index 16310318e67ada54c3042a53f5495086e4dcf0b5..04f72935d397f17c364cef4660abfcfca2e92d00 100644 (file)
@@ -2937,20 +2937,20 @@ isc__nm_socket_incoming_cpu(uv_os_sock_t fd) {
 }
 
 isc_result_t
-isc__nm_socket_dontfrag(uv_os_sock_t fd, sa_family_t sa_family) {
+isc__nm_socket_disable_pmtud(uv_os_sock_t fd, sa_family_t sa_family) {
        /*
-        * Set the Don't Fragment flag on IP packets
+        * Disable the Path MTU Discovery on IP packets
         */
        if (sa_family == AF_INET6) {
 #if defined(IPV6_DONTFRAG)
-               if (setsockopt_on(fd, IPPROTO_IPV6, IPV6_DONTFRAG) == -1) {
+               if (setsockopt_off(fd, IPPROTO_IPV6, IPV6_DONTFRAG) == -1) {
                        return (ISC_R_FAILURE);
                } else {
                        return (ISC_R_SUCCESS);
                }
-#elif defined(IPV6_MTU_DISCOVER)
+#elif defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
                if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
-                              &(int){ IP_PMTUDISC_DO }, sizeof(int)) == -1)
+                              &(int){ IP_PMTUDISC_OMIT }, sizeof(int)) == -1)
                {
                        return (ISC_R_FAILURE);
                } else {
@@ -2961,14 +2961,14 @@ isc__nm_socket_dontfrag(uv_os_sock_t fd, sa_family_t sa_family) {
 #endif
        } else if (sa_family == AF_INET) {
 #if defined(IP_DONTFRAG)
-               if (setsockopt_on(fd, IPPROTO_IP, IP_DONTFRAG) == -1) {
+               if (setsockopt_off(fd, IPPROTO_IP, IP_DONTFRAG) == -1) {
                        return (ISC_R_FAILURE);
                } else {
                        return (ISC_R_SUCCESS);
                }
-#elif defined(IP_MTU_DISCOVER)
+#elif defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
                if (setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER,
-                              &(int){ IP_PMTUDISC_DO }, sizeof(int)) == -1)
+                              &(int){ IP_PMTUDISC_OMIT }, sizeof(int)) == -1)
                {
                        return (ISC_R_FAILURE);
                } else {
index c47cb86257b890e871c2d05463897d96855bd53b..a91c425a8e38a226a3b1705579aacf0579e3ca47 100644 (file)
@@ -65,7 +65,7 @@ isc__nm_udp_lb_socket(sa_family_t sa_family) {
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
 
        (void)isc__nm_socket_incoming_cpu(sock);
-       (void)isc__nm_socket_dontfrag(sock, sa_family);
+       (void)isc__nm_socket_disable_pmtud(sock, sa_family);
 
        result = isc__nm_socket_reuse(sock);
        RUNTIME_CHECK(result == ISC_R_SUCCESS);
@@ -783,7 +783,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
 
        (void)isc__nm_socket_incoming_cpu(sock->fd);
 
-       (void)isc__nm_socket_dontfrag(sock->fd, sa_family);
+       (void)isc__nm_socket_disable_pmtud(sock->fd, sa_family);
 
        event = isc__nm_get_netievent_udpconnect(mgr, sock, req);
 
index d8097292294629a4a60d762cff00e18c4f093ae5..c23f6c64bdf003cb03bdef8648c72fe44547e5cd 100644 (file)
@@ -2100,27 +2100,27 @@ set_tcp_maxseg(isc_socket_t *sock, int size) {
 }
 
 static void
-set_ip_dontfrag(isc_socket_t *sock) {
+set_ip_disable_pmtud(isc_socket_t *sock) {
        /*
-        * Set the Don't Fragment flag on IP packets
+        * Disable Path MTU Discover on IP packets
         */
        if (sock->pf == AF_INET6) {
 #if defined(IPV6_DONTFRAG)
                (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_DONTFRAG,
-                                &(int){ 1 }, sizeof(int));
+                                &(int){ 0 }, sizeof(int));
 #endif
-#if defined(IPV6_MTU_DISCOVER)
+#if defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
                (void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
-                                &(int){ IP_PMTUDISC_DO }, sizeof(int));
+                                &(int){ IP_PMTUDISC_OMIT }, sizeof(int));
 #endif
        } else if (sock->pf == AF_INET) {
 #if defined(IP_DONTFRAG)
-               (void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG, &(int){ 1 },
+               (void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG, &(int){ 0 },
                                 sizeof(int));
 #endif
-#if defined(IP_MTU_DISCOVER)
+#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_OMIT)
                (void)setsockopt(sock->fd, IPPROTO_IP, IP_MTU_DISCOVER,
-                                &(int){ IP_PMTUDISC_DO }, sizeof(int));
+                                &(int){ IP_PMTUDISC_OMIT }, sizeof(int));
 #endif
        }
 }
@@ -2411,7 +2411,7 @@ again:
 #endif /* ifdef IP_RECVTOS */
 #endif /* defined(USE_CMSG) || defined(SET_RCVBUF) || defined(SET_SNDBUF) */
 
-       set_ip_dontfrag(sock);
+       set_ip_disable_pmtud(sock);
 
 setup_done:
        inc_stats(manager->stats, sock->statsindex[STATID_OPEN]);