Subject: Re: [DNSOP] draft-fujiwara-dnsop-fragment-attack-01.txt

From: Florian Weimer <[email-masked]>
Date: Fri, 24 May 2019 14:21:02 +0200

* Daisuke HIGASHI:

> draft-fujiwara-dnsop-fragment-attack-01:
>
>> 3.  Current status
>>
>>   [Brandt2018] showed that Linux version 3.13 and older versions are
>>   vulnerable to crafted ICMP fragmentation needed and DF set packet and
>>   off-path attackers can set some of authoritative servers' path MTU
>>   size to 296.
>>
>>   The author tested Linux version 2.6.32, 4.18.20 and FreeBSD 12.0.
>>   Linux 2.6.32 accepts crafted "ICMP Need Fragmentation and DF set"
>>   packet and path MTU decreased to 552.  Linux 2.6.32, Linux 4.18.20
>>   and FreeBSD 12.0 accept crafted "ICMPv6 Packet Too Big" packet and
>>   path MTU decreased to 1280.
>>
>>  Linux version 4.18.20 may ignore crafted ICMP packet.
>
>    I confirmed that Linux 4.18 (Ubuntu 18.10) accepts crafted ICMP
> on "plain" UDP socket. And if sockopt IP_PMTUDISC_DONT is set to sockets
> (many DNS implements do this) sender host generates fragmented packets
> caused by crafted ICMP.
>
>    Determining whether a DNS implementation on Linux accepts
> crafted ICMPv4 or not is somewhat confusing and need to investigate
> with caution:
>
>  - Latest Linux seems to still accept crafted ICMPv4 by default.
>    Linux 3.15 introduced a new socket option IP_PMTUDISC_OMIT
>    which makes sockets ignore PMTU information and send packet with DF=0.
>    With this option sending socket never honor PMTU information and
> fragmentation
>    is done if and only if the packet size exceeds outgoing interface MTU.
>
> - Some DNS implementation (BIND 9.9.10 / Unbound 1.5.0 and later) utilize
>   IP_PMTUDISC_OMIT option if available. So these DNS implementation on
> Linux 3.15 (or later)
>   won't accept crafted ICMP.
>   (I submitted a patch to NSD for enabling this feature.
>     https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=4235 )

Correct, this was the intent.

There is another essential Linux kernel change: not using the path MTU
when forwarding packets.  Otherwise, a Linux hypervisor (or router),
after receiving an ICMP packet directed to itself, would reassemble the
packet and re-fragment it to the cached (spoofed) path MTU.

I believe it's this commit:

commit 69647ce46a236a355a7a3096d793819a9bd7c1d3
Author: Hannes Frederic Sowa <[email-masked]>
Date:   Wed Feb 26 01:20:41 2014 +0100

    ipv4: use ip_skb_dst_mtu to determine mtu in ip_fragment
    
    ip_skb_dst_mtu mostly falls back to ip_dst_mtu_maybe_forward if no socket
    is attached to the skb (in case of forwarding) or determines the mtu like
    we do in ip_finish_output, which actually checks if we should branch to
    ip_fragment. Thus use the same function to determine the mtu here, too.
    
    This is important for the introduction of IP_PMTUDISC_OMIT, where we
    want the packets getting cut in pieces of the size of the outgoing
    interface mtu. IPv6 already does this correctly.

> - Some Linux distribution is based on older version (like Linux 3.10)
>   but has IP_PMTUDISC_OMIT feature by backporting.
>
>   I found that IP_PMTUDISC_OMIT feature is backported to Red Hat
> Enterprise Linux 7
>   (it's Linux 3.10 based) but they didn't backport corresponding macro
> definition to glibc header.
>   So BIND9's / Unbound's IP_PMTUDISC_OMIT feature on current RHEL7
> won't be enabled
>   regardless of kernel feature.
>   (Bug report:  https://bugzilla.redhat.com/show_bug.cgi?id=1684874 )

Yes, this is about to be fixed.  But applications can use the constant
directly if necessary (it's not architecture-specific and will never
change).

All in all, I do not think it is necessary or desirable to send DF=1
responses.  The backwards compatibility impact would be too large.

Thanks,
Florian