[PATCH net-next v10 00/10] ipv6: Address ext hdr DoS vulnerabilities

Tom Herbert
2026-05-04T18:52:13Z

IPv6 extension headers are defined to be quite open ended with few
limits. For instance, RFC8200 requires a receiver to process any
number of extension headers in a packet in any order. This flexibility
comes at the cost of a potential Denial of Service attack. The only
thing that might mitigate the DoS attacks is the fact that packets
with extension headers experience high drop rates on the Internet so
that a DoS attack based on extension wouldn't be very effective at
Internet scale.

This patch set addresses some of the more egregious vulnerabilities
of extension headers to DoS attack.

- If sysctl.max_dst_opts_cnt or hbh_opts_cnt are set to 0 then that
disallows packets with Destination Options or Hop-by-Hop Options even
if the packet contain zero non-padding options

- Add a case for IPV6_TLV_TNL_ENCAP_LIMIT in the switch on TLV type
in ip6_parse_tlv function. This TLV is handled in tunnel processing,
however it needs to be detected in ip6_parse_tlv to properly account
for it as recognized non-padding option

- Move IPV6_TLV_TNL_ENCAP_LIMIT to uapi/linux/in6.h so that all the
TLV definitions are in one place

- Set the default limits of non-padding Hop-by-Hop and Destination
options to 2. This means that if a packet contains more then two
non-padding options then it will be dropped. The previous limit
was 8, but that was too liberal considering that the stack only
support two Destination Options and the most Hop-by-Hop options
likely to ever be in the same packet are IOAM and JUMBO. The limit
can be increased via sysctl for private use and experimentation

- Enforce RFC8200 recommended ordering of Extension Headers. This
also enforces that any Extension Header occurs at most once
in a packet except for Destination Options that may appear
twice. The enforce_ext_hdr_order sysctl controls enforcement. If
it's set to true then order is enforced, if it's set to false then
neither order nor number of occurrences are enforced.

The enforced ordering is:

IPv6 header
Hop-by-Hop Options header
Destination Options before the Routing header
Routing header
Fragment header
Authentication header
Encapsulating Security Payload header
Destination Options header
Upper-Layer header

--- Background

We selected the default value of eight in RFC8504 based on an
expectation that there might be new options defined and that the
Internet would be fixed to reliably support extension headers
including those with options. I do not believe either of those are
going to happen.

Hop-by-Hop Options are ostensibly the right way to do network to host
and host to network signaling.The only HBH options that might get any
substantial deployment are Router Alert option and IOAM. The Router
Alert option is being deprecated and IOAM is at best a "nice to
have". The best use case of Hop-by-Hop options is congestion
signaling, unfortunately the die was cast when CSIG authors decided to
place the information in VLANs at L2 and cajole the information to be
routable through a switch. IMO, the miss on CSIG pretty much is the
nail in the coffin for Hop-by-Hop options to ever be widely deployed
(https://www.ietf.org/archive/id/draft-ravi-ippm-csig-01.txt).

Destination Options have proven even less useful than Hop-by-Hop
Options. The only Destination Options supported by the stack is the
Tunnel Encap Limit option and Home Address Options. The Tunnel Encap
Option was buried in the v6 tunnel code which is why it wasn't obvious
it was supported in the first version of the patch set. I'll assume
that might be useful, so this patch set cleans up the code for it. I
don't believe there's any use of Home Address Option.

A major problem with DestOpts, HBH, Routing Header, and Fragment
header is that they have no inherent security. Their use presents a
security risk especially when sent over untrusted networks including
the Internet. Given that and that the high drop rates of extension
headers on the Internet, I am proposing that Extension header except
for ESP being deprecated on the Internet
(https://www.ietf.org/archive/id/draft-herbert-deprecate-eh-01.txt).

An update to RFC8200 is being proposed in IETF to allow enforcement of
extension header ordering and number of occurences. An I-D is in
https://www.ietf.org/archive/id/draft-iurman-6man-eh-occurrences-00.txt

--- Testing

Add selftest eh_limits.sh. Tested by running:

$ sudo ./eh_limits.sh
TEST: EH-limits - default sysctls [ OK ]
TEST: EH-limits - modified sysctls [ OK ]

Tests passed: 2
Tests failed: 0

$ sudo ./eh_limits.sh -v
>>>>> Default
TEST: Two non-padding options in HBH and DestOpts: Received as expected
TEST: Big destination option: Received as expected
TEST: Almost Big HBH option: Received as expected
TEST: Big HBH option: Received as expected
TEST: Too much HBH padding: Didn't receive as expected
TEST: Too much DestOpt padding: Didn't receive as expected
TEST: Too much DestOpt padding #2: Didn't receive as expected
TEST: Too much DestOpt padding #3: Didn't receive as expected
TEST: Almost too much DestOpt padding #2: Received as expected
TEST: Two Dest Ops: Didn't receive as expected
TEST: OOO Routing header: Didn't receive as expected
TEST: Two Routing headers: Didn't receive as expected
TEST: Two Destination options okay: Received as expected
TEST: Two Destination options: Didn't receive as expected
TEST: Two Destination options after RH: Didn't receive as expected
TEST: Many EH OOO: Didn't receive as expected
TEST: Two fragment Headers: Didn't receive as expected

TEST: EH-limits - default sysctls [ OK ]
>>>>> No order enforce, 8 options, 66 length limit
TEST: Two non-padding options in HBH and DestOpts: Received as expected
TEST: Big destination option: Didn't receive as expected
TEST: Almost Big HBH option: Received as expected
TEST: Big HBH option: Didn't receive as expected
TEST: Too much HBH padding: Didn't receive as expected
TEST: Too much DestOpt padding: Didn't receive as expected
TEST: Too much DestOpt padding #2: Didn't receive as expected
TEST: Too much DestOpt padding #3: Didn't receive as expected
TEST: Almost too much DestOpt padding #2: Received as expected
TEST: Two Dest Ops: Received as expected
TEST: OOO Routing header: Received as expected
TEST: Two Routing headers: Received as expected
TEST: Two Destination options okay: Received as expected
TEST: Two Destination options: Received as expected
TEST: Two Destination options after RH: Received as expected
TEST: Many EH OOO: Received as expected
TEST: Two fragment Headers: Didn't receive as expected

TEST: EH-limits - modified sysctls [ OK ]

Tests passed: 2
Tests failed: 0

V4: Switch order of patches to avoid transient build failure
V5: Allow Destination Options before the Routing header, fixes
suggested by Justin Iurman
v6: Fix a bug and create a test for extension header limits
v7: Run pylint on new Python file, run shellcheck on new bash file,
Make fixes as needed
v8: Repost
v9: Fix subject prefix
v10: Lint fixes in selftest scripts suggested by Simon Horman

Tom Herbert (10):
ipv6: Check of max HBH or DestOp sysctl is zero and drop if it is
ipv6: Cleanup IPv6 TLV definitions
ipv6: Add case for IPV6_TLV_TNL_ENCAP_LIMIT in EH TLV switch
ipv6: Set HBH and DestOpt limits to 2
ipv6: Document defaults for max_{dst|hbh}_opts_number sysctls
ipv6: Enforce Extension Header ordering
ipv6: Document enforce_ext_hdr_order sysctl
test: Add proto_nums.py in networking selftests
test: Add ext_hdr.py in networking selftests
test: Add networking selftest for eh limits

Documentation/networking/ip-sysctl.rst | 52 ++-
include/net/ipv6.h | 9 +-
include/net/netns/ipv6.h | 1 +
include/net/protocol.h | 14 +
include/uapi/linux/in6.h | 21 +-
include/uapi/linux/ip6_tunnel.h | 1 -
net/ipv6/af_inet6.c | 1 +
net/ipv6/exthdrs.c | 32 +-
net/ipv6/ip6_input.c | 42 +++
net/ipv6/reassembly.c | 1 +
net/ipv6/sysctl_net_ipv6.c | 7 +
net/ipv6/xfrm6_protocol.c | 2 +
tools/testing/selftests/net/Makefile | 4 +
tools/testing/selftests/net/eh_limits.py | 349 ++++++++++++++++++++
tools/testing/selftests/net/eh_limits.sh | 210 ++++++++++++
tools/testing/selftests/net/ext_hdr.py | 385 ++++++++++++++++++++++
tools/testing/selftests/net/proto_nums.py | 231 +++++++++++++
17 files changed, 1334 insertions(+), 28 deletions(-)
create mode 100755 tools/testing/selftests/net/eh_limits.py
create mode 100755 tools/testing/selftests/net/eh_limits.sh
create mode 100755 tools/testing/selftests/net/ext_hdr.py
create mode 100644 tools/testing/selftests/net/proto_nums.py

--
2.43.0