[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CALx6S34SjAvoidT+vjWA=U3GezP39hT2v3LuaFtLid_sMY7+dA@mail.gmail.com>
Date: Sat, 22 Nov 2025 08:48:09 -0800
From: Tom Herbert <tom@...bertland.com>
To: Justin Iurman <justin.iurman@...ege.be>
Cc: davem@...emloft.net, kuba@...nel.org, netdev@...r.kernel.org
Subject: Re: [RFC net-next 2/3] ipv6: Disable IPv6 Destination Options RX
processing by default
On Sat, Nov 22, 2025 at 1:53 AM Justin Iurman <justin.iurman@...ege.be> wrote:
>
> On 11/21/25 22:23, Tom Herbert wrote:
> > On Thu, Nov 13, 2025 at 5:17 AM Justin Iurman <justin.iurman@...ege.be> wrote:
> >>
> >> On 11/12/25 01:16, Tom Herbert wrote:
> >>> Set IP6_DEFAULT_MAX_HBH_OPTS_CNT to zero. This disables
> >>
> >> s/IP6_DEFAULT_MAX_HBH_OPTS_CNT/IP6_DEFAULT_MAX_DST_OPTS_CNT
> >>
> >>> processing of Destinations Options extension headers by default.
> >>> Processing can be enabled by setting the net.ipv6.max_dst_opts_number
> >>> to a non-zero value.
> >>>
> >>> The rationale for this is that Destination Options pose a serious risk
> >>> of Denial off Service attack. The problem is that even if the
> >>> default limit is set to a small number (previously it was eight) there
> >>> is still the possibility of a DoS attack. All an attacker needs to do
> >>> is create and MTU size packet filled with 8 bytes Destination Options
> >>> Extension Headers. Each Destination EH simply contains a single
> >>> padding option with six bytes of zeroes.
> >>>
> >>> In a 1500 byte MTU size packet, 182 of these dummy Destination
> >>> Options headers can be placed in a packet. Per RFC8200, a host must
> >>> accept and process a packet with any number of Destination Options
> >>> extension headers. So when the stack processes such a packet it is
> >>> a lot of work and CPU cycles that provide zero benefit. The packet
> >>> can be designed such that every byte after the IP header requires
> >>> a conditional check and branch prediction can be rendered useless
> >>> for that. This also may mean over twenty cache misses per packet.
> >>> In other words, these packets filled with dummy Destination Options
> >>> extension headers are the basis for what would be an effective DoS
> >>> attack.
> >>
> >> How about a new document to update RFC8200 Sec. 4.1.? Maybe we can get
> >> 6man consensus to enforce only one occurrence (vs. 2 for the Dest) for
> >> each extension header. Let alone the recommended order (without
> >> normative language), we could...
> >
> > Hi Justin,
>
> Hi Tom,
>
> > It's a nice idea, but given the turnaround times for the IETF process
>
> Indeed, but I think we'll need that at some point. I'll craft something
> and send it to 6man to get feedback.
>
> > it would take years. Also to implement that in the stack isn't
>
> I don't think it would be difficult thanks to struct inet6_skb_parm that
> is stored in the control buffer of skb's. We already have some flags
> that are set, and offsets defined.
Justin,
A patch for that would be good regardless of whether you take it to IETF :-).
>
> > particularly trivial. Avoiding the potential DoS attack is the higher
> > priority problem IMO, and disabling DestOpts by default will have
> > little impact since almost no one is using them..
>
> Agree, but both issues are linked. If we don't explicitly limit (funny,
> in this case, I'd be OK to use that term ;-) the number of Destination
> Options header to 2 (as it should be), then the attack surface increases.
Yes, but it doesn't eliminate the potential for attack.
>
> >>
> >> OLD:
> >> Each extension header should occur at most once, except for the
> >> Destination Options header, which should occur at most twice (once
> >> before a Routing header and once before the upper-layer header).
> >>
> >> NEW:
> >> Each extension header MUST occur at most once, except for the
> >> Destination Options header, which MUST occur at most twice (once
> >> before a Routing header and once before the upper-layer header).
> >>
> >> ...and...
> >>
> >> OLD:
> >> IPv6 nodes must accept and attempt to process extension headers in
> >> any order and occurring any number of times in the same packet,
> >> except for the Hop-by-Hop Options header, which is restricted to
> >> appear immediately after an IPv6 header only. Nonetheless, it is
> >> strongly advised that sources of IPv6 packets adhere to the above
> >> recommended order until and unless subsequent specifications revise
> >> that recommendation.
> >>
> >> NEW:
> >> IPv6 nodes must accept and attempt to process extension headers in
> >> any order in the same packet,
> >> except for the Hop-by-Hop Options header, which is restricted to
> >> appear immediately after an IPv6 header only. Nonetheless, it is
> >> strongly advised that sources of IPv6 packets adhere to the above
> >> recommended order until and unless subsequent specifications revise
> >> that recommendation.
> >>
> >>> Disabling Destination Options is not a major issue for the following
> >>> reasons:
> >>>
> >>> * Linux kernel only supports one Destination Option (Home Address
> >>> Option). There is no evidence this has seen any real world use
> >>
> >> IMO, this is precisely the one designed for such real world end-to-end
> >> use cases (e.g., PDM [RFC8250] and PDMv2 [draft-ietf-ippm-encrypted-pdmv2]).
> >
> > Sure, but where is the Linux implementation? Deployment?
>
> Maybe they'll send it upstream one day, who knows.
>
> >>
> >>> * On the Internet packets with Destination Options are dropped with
> >>> a high enough rate such that use of Destination Options is not
> >>> feasible
> >>
> >> I wouldn't say that a 10-20% drop is *that* bad (i.e., "not feasible")
> >> for sizes < 64 bytes. But anyway...
> >
> > The drop rates for Destination Options vary by size of the extension
> > header. AP NIC data shows that 32 bytes options have about a 30% drop
> > rate, 64 byte options have about a 40% drop rate, but 128 byte options
> > have over 80% drop rate. The drops are coming from routers and not
> > hosts, Linux has no problem with different sizes. As you know from the
> > 6man list discussions, I proposed a minimum level of support that
> > routers must forward packets with up to 64 bytes of extension headers,
> > but that draft was rejected because of concerns that it would ossify
> > an already ossified protocol :-(. Even if a 40% drop rate isn't "that
> > bad" the 80% drop rate of 128 bytes EH would seem to qualify as "bad".
> > In any case, no one in IETF has offered an alternative plan to address
> > the high loss rates and without a solution I believe it's fair to say
> > that use of Destination Options is not feasible.
>
> The difference with APNIC's measurements lies in the fact that they
> reach end-users located behind ISPs, where EHs are heavily filtered. So
> their measurements are worst case scenarios (not saying they are not
> representative, just that it's a different location in networks). This
> becomes "less" problematic (don't get me wrong, there are still EH
> filters) if you remain at the core/edge (e.g., cloud providers, etc).
>
That's exactly the point though. The vast majority of our users, i.e.
billions of laptops and SmartPhones, live behind ISPs and packets sent
to them with EH are commonly being filtered by ISPs. IMO we need to
set the defaults for the benefit of _them_, not for the relative
handful of nodes that remain at the core/edge. For the latter group if
they really want to use extension headers they can easily configure
their devices accordingly. As contrary as it is to the end-to-end
principle, it may actually be a good thing that ISPs have been
filtering all along since that saves hosts from DoS attacks involving
EH, but it's time to close this security hole in Linux itself.
Also we need to be honest here. The whole idea of extension headers
was ill conceived from the get go. Even if we didn't know any better
in the first design of IPv6 thirty years ago, I really wished the
problems would have been addressed when IPv6 was promoted to Standard.
Destination Options are particularly problematic since they have no
security to speak of. If someone wants to send end-to-end information
wouldn't they wrap this in an encrypted transport layer, I mean why
expose end-to-end information in plain text for all the world to see
and muck with?
In the end, the most likely future of extension headers is that they
will be relegated to use in limited domains. And that's fine, in a
limited domain any issues of router compatibility can be managed and
security can be enforced. But on the Internet, I don't believe we'll
ever see EH used. And that's why I think we should disable Destination
Options by default for the greater good of humanity! ;-)
Tom
> >>
> >>> * It is unknown however quite possible that no one anywhere is using
> >>> Destination Options for anything but experiments, class projects,
> >>> or DoS. If someone is using them in their private network thenthatit
> >>> it's easy enough to configure a non-zero limit for their use case
> >>> ---
> >>> include/net/ipv6.h | 7 +++++--
> >>> 1 file changed, 5 insertions(+), 2 deletions(-)
> >>>
> >>> diff --git a/include/net/ipv6.h b/include/net/ipv6.h
> >>> index 74fbf1ad8065..723a254c0b90 100644
> >>> --- a/include/net/ipv6.h
> >>> +++ b/include/net/ipv6.h
> >>> @@ -86,8 +86,11 @@ struct ip_tunnel_info;
> >>> * silently discarded.
> >>> */
> >>>
> >>> -/* Default limits for Hop-by-Hop and Destination options */
> >>> -#define IP6_DEFAULT_MAX_DST_OPTS_CNT 8
> >>> +/* Default limits for Hop-by-Hop and Destination options. By default
> >>> + * packets received with Destination Options headers are dropped to thwart
> >>> + * Denial of Service attacks (see sysctl documention)
> >>> + */
> >>> +#define IP6_DEFAULT_MAX_DST_OPTS_CNT 0
> >>> #define IP6_DEFAULT_MAX_HBH_OPTS_CNT 8
> >>> #define IP6_DEFAULT_MAX_DST_OPTS_LEN INT_MAX /* No limit */
> >>> #define IP6_DEFAULT_MAX_HBH_OPTS_LEN INT_MAX /* No limit */
> >>
> >> I'd rather prefer to update RFC8200 and enforce a maximum of 2
> >> occurrences for the Dest, and keep the default limit of 8 options.
> >>
> >> Also, regardless of what we do here (and this remark also applies to the
> >> Hop-by-Hop), I think it's reasonable for a *host* to drop packets with a
> >> number of Hbh or Dest options that exceeds the configured limit.
> >> However, for a router (i.e., forwarding mode), I'd prefer to skip the EH
> >> chain rather than drop packets (for obvious reasons).
> >
> > I considered that, but there is a problem in that when we process HBH
> > options we don't know if we're a host (i.e. the final destination) or
> > a router (i.e. the packet will be forwarded). I would prefer to keep
>
> Correct. We may consider calling ip6_route_input() earlier (this is what
> IOAM does already), for example before calling ipv6_parse_hopopts() in
> ip6_rcv_core(), instead of doing it in ip6_rcv_finish_core(). Otherwise,
> we'd need to rely on ipv6_chk_addr_ret(). Maybe something like (not tested):
>
> diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
> index a23eb8734e15..0351b7fc58ee 100644
> --- a/net/ipv6/exthdrs.c
> +++ b/net/ipv6/exthdrs.c
> @@ -119,6 +119,7 @@ static bool ip6_parse_tlv(bool hopbyhop,
> const unsigned char *nh = skb_network_header(skb);
> int off = skb_network_header_len(skb);
> bool disallow_unknowns = false;
> + int ipv6_chk_addr_ret = -1;
> int tlv_count = 0;
> int padlen = 0;
>
> @@ -166,8 +167,30 @@ static bool ip6_parse_tlv(bool hopbyhop,
> }
> } else {
> tlv_count++;
> - if (tlv_count > max_count)
> - goto bad;
> + if (tlv_count > max_count) {
> + /* Drop a Destination Options header when its
> + * number of options exceeds the configured
> + * limit.
> + */
> + if (!hopbyhop)
> + goto bad;
> +
> + /* Drop a Hop-by-Hop Options header when its
> + * number of options exceeds the configured
> + * limit IF we're the destination. Otherwise,
> + * just skip it.
> + */
> + if (ipv6_chk_addr_ret == -1)
> + ipv6_chk_addr_ret = ipv6_chk_addr(
> + dev_net(skb->dev),
> + &ipv6_hdr(skb)->daddr,
> + skb->dev, 0);
> +
> + if (ipv6_chk_addr_ret)
> + goto bad;
> +
> + goto skip;
> + }
>
> if (hopbyhop) {
> switch (nh[off]) {
> @@ -210,6 +233,7 @@ static bool ip6_parse_tlv(bool hopbyhop,
> break;
> }
> }
> +skip:
> padlen = 0;
> }
> off += optlen;
>
> > it simple and drop whenever a limit is exceeded. RFC9673 does allow a
> > host to skip over HBH options, but IMO it's too risky to blindly
> > accept a packet without verifying all the headers.
>
> For a host, I agree. But as a router, I really don't think we should
> drop packets if the limit is exceeded. In that case, we just don't care,
> we're routers, it's not our job to decide if we drop a packet because of
> EHs. Otherwise, we'd be doing the same as operators' policies and
> hardware limitation in transit ASs, and we'd be exacerbating the
> ossification.
>
> Justin
>
> > Tom
>
Powered by blists - more mailing lists