Bug 170604 - [ipfw] ipv6 reass broken
Summary: [ipfw] ipv6 reass broken
Status: In Progress
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: Normal Affects Only Me
Assignee: Andrey V. Elsukov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-08-13 13:50 UTC by public
Modified: 2024-03-25 22:47 UTC (History)
15 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description public 2012-08-13 13:50:01 UTC
Summary:
Packet reassembly is only implemented for IPv4, not for IPv6. This is a request to:
* Support IPv6 packet reassembly with the "reass" command in ipfw.
* Update the documentation and/or ignore the ip6 reass command (to avoid someone bricking a device) in the mean time

Notes: I presume this is the same problem as reported earlier by someone else on the freebsd-ipfw list:
http://lists.freebsd.org/pipermail/freebsd-ipfw/2011-October/004918.html

The bug report/feature request is meant to keep track of that issue.

How-To-Repeat: Steps to reproduce:
1. Add the following rules to ipfw:
# sysctl net.inet.ip.fw.one_pass=0
# ipfw add 100 reass ipv6 from any to any in
2. Try to connect to the device (with any means, e.g. ssh over either IPv4 or IPv6)

Expected result:
I expect the device to be reachable

Actual result:
I bricked my device
Comment 1 Eugene Grosbein 2013-03-20 05:51:03 UTC
Hi!

The problem is here in 8.3-STABLE too, the following rule drops all incoming IPv6 packets
(but reassembles and passes IPv4):

ipfw add reass ip from any to any in recv em0

Eugene Grosbein
Comment 2 Eugene Grosbein 2013-03-20 06:45:15 UTC
20.03.2013 12:51, Eugene Grosbein ÐÉÛÅÔ:
> Hi!
> 
> The problem is here in 8.3-STABLE too, the following rule drops all incoming IPv6 packets
> (but reassembles and passes IPv4):
> 
> ipfw add reass ip from any to any in recv em0

Btw, obvious workaround is to replace 'ip' with 'ip4', so that the rule
does not match IPv6 packets and does not block them.
Comment 3 Mark Linimon freebsd_committer freebsd_triage 2014-04-16 02:13:21 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-ipfw

reassign.
Comment 4 hirner 2015-07-08 12:32:28 UTC
Still a problem with 10.1-RELEASE-p10.

Is there anything how I can help?
Comment 5 Andrey V. Elsukov freebsd_committer freebsd_triage 2015-07-08 15:42:13 UTC
(In reply to hirner from comment #4)
> Still a problem with 10.1-RELEASE-p10.
> 
> Is there anything how I can help?

Only if you can submit some patch :)
There is the big difference between IPv4 and IPv6 in packet fragmentation. IPv6 routers don't do IPv6 fragmentation. So in case when you are trying reassemble fragments on the router, the result of this reassembling will be dropped because it will be too big to go into the wire. I don't like how PF resolves this problem, it does reassembling by self and doing this in the ipfw will introduce third piece of code with the same functionality. I think it will be better slightly redesign KPI in frag6.c, then use it from where we need. But currently I'm lacking of the time.
Comment 6 g_amanakis 2016-01-17 21:26:20 UTC
@ae: this bug persists also on 10.2-RELEASE. Could you reflect this to the Version assigned above?
I have a router with native IPv6 and saw your patch at http://people.freebsd.org/~ae/ipfw_ip6reass.diff, I would be willing to give it a try.
Comment 7 Andrey V. Elsukov freebsd_committer freebsd_triage 2016-01-18 06:18:14 UTC
(In reply to g_amanakis from comment #6)
> @ae: this bug persists also on 10.2-RELEASE. Could you reflect this to the
> Version assigned above?
> I have a router with native IPv6 and saw your patch at
> http://people.freebsd.org/~ae/ipfw_ip6reass.diff, I would be willing to give
> it a try.

This patch isn't correct.
We can't just use the generic IPv6 fragmentation code here like we do for IPv4. IPv6 router must not fragment packets that it routes. We need adjust frag6 code to support such case, or use something similar that PF does. PF uses its own implementation. But currently I have not the time for this project.
Comment 8 Mark Felder freebsd_committer freebsd_triage 2016-02-19 14:47:55 UTC
Is it possible/acceptable to patch ipfw to refuse to allow reass unless you specify ip4?
Comment 9 Andrey V. Elsukov freebsd_committer freebsd_triage 2017-04-28 13:14:45 UTC
I prepared the patch https://reviews.freebsd.org/D10533
It can be applied to stable/11 too, so if someone is able to test, you are welcome.
Comment 10 public 2017-05-02 09:02:46 UTC
Andrey, just a big thanks for preparing the patch. Unfortunately, I no longer have access to a FreeBSD system I can use for testing, so I hope someone else can!
Comment 11 commit-hook freebsd_committer freebsd_triage 2018-03-12 09:41:25 UTC
A commit references this bug:

Author: ae
Date: Mon Mar 12 09:40:46 UTC 2018
New revision: 330792
URL: https://svnweb.freebsd.org/changeset/base/330792

Log:
  Do not try to reassemble IPv6 fragments in "reass" rule.

  ip_reass() expects IPv4 packet and will just corrupt any IPv6 packets
  that it gets. Until proper IPv6 fragments handling function will be
  implemented, pass IPv6 packets to next rule.

  PR:		170604
  MFC after:	1 week

Changes:
  head/sbin/ipfw/ipfw.8
  head/sys/netpfil/ipfw/ip_fw2.c
Comment 12 commit-hook freebsd_committer freebsd_triage 2018-03-19 09:52:33 UTC
A commit references this bug:

Author: ae
Date: Mon Mar 19 09:52:17 UTC 2018
New revision: 331201
URL: https://svnweb.freebsd.org/changeset/base/331201

Log:
  MFC r330792:
    Do not try to reassemble IPv6 fragments in "reass" rule.

    ip_reass() expects IPv4 packet and will just corrupt any IPv6 packets
    that it gets. Until proper IPv6 fragments handling function will be
    implemented, pass IPv6 packets to next rule.

    PR:		170604

Changes:
_U  stable/11/
  stable/11/sbin/ipfw/ipfw.8
  stable/11/sys/netpfil/ipfw/ip_fw2.c
Comment 13 commit-hook freebsd_committer freebsd_triage 2018-03-19 09:54:45 UTC
A commit references this bug:

Author: ae
Date: Mon Mar 19 09:54:17 UTC 2018
New revision: 331202
URL: https://svnweb.freebsd.org/changeset/base/331202

Log:
  MFC r330792:
    Do not try to reassemble IPv6 fragments in "reass" rule.

    ip_reass() expects IPv4 packet and will just corrupt any IPv6 packets
    that it gets. Until proper IPv6 fragments handling function will be
    implemented, pass IPv6 packets to next rule.

    PR:		170604

Changes:
_U  stable/10/
  stable/10/sbin/ipfw/ipfw.8
  stable/10/sys/netpfil/ipfw/ip_fw2.c
Comment 14 Oleksandr Tymoshenko freebsd_committer freebsd_triage 2019-01-20 01:29:47 UTC
Andrey, can this PR be closed now?

Thanks
Comment 15 Sigi 2019-08-26 20:03:27 UTC
This seems to be still a problem in 12.0-STABLE r350899. The workaround is simply to ignore IPv6 reassemble statement. Has ipfw development stalled? Or would you recommend to switch firewall type?
Comment 16 Scott Aitken 2019-12-09 14:47:47 UTC
(In reply to Oleksandr Tymoshenko from comment #14)

No, this bug can't be closed.  From the comments above it appears that negative interactions between IPv6 fragments and IPFW have been resolved, but the real problem of no IPv6 reassembly on end-hosts has not been addressed.

IPv4 reassembly works; IPv6 packet reassembly is a requirement for IPv6 end-hosts (but does not work).
Comment 17 Helge Oldach 2019-12-09 18:14:46 UTC
(In reply to Scott Aitken from comment #16)
Not quite.

IPv6 fragmentation and reassembly works a bit differently than IPv4. IPv6 routers are not allowed to fragment packets, only the end hosts can "fragment". Actually IPv6 end hosts mandatorily do PMTU discovery, so the IP layer will only see packets that fit into MTU. In other words, there is practically (!) no necessity to reassemble IPv6 packets on end systems.

Being able to reassemble IPv6 on firewall layer (specifically as IPv6 has a dedicated fragment header) would be a nice security feature though.
Comment 18 Scott Aitken 2019-12-10 01:05:07 UTC
(In reply to Helge Oldach from comment #17)

It is not true to say routers must not fragment.  Most routers also act as end-hosts (or nodes) and so the rule of not fragmenting only applies when a router is forwarding.  It is perfectly acceptable for a router to fragment when:
a) pinging or responding to a ping,
b) encapsulating to put data into a tunnel
c) doing many other things

Basically anything that doesn't decrement the hop count should be subjected to fragmentation if the outgoing link MTU is too small.  I agree this can be mitigated by PMTU discovery, however PMTU discovery is optional (although you assert otherwise):
"It is strongly recommended that IPv6 nodes implement Path MTU Discovery"
whereas reassembly (which is really what we're talking about) is mandatory:
"A node must be able to accept a fragmented packet that, after reassembly, is as large as 1500 octets."

And the implementers of the v6 stack in FreeBSD agree, as FreeBSD DOES reassembly.

If your argument is that "there is practically (!) no necessity to reassemble IPv6 packets on end systems" then you must also argue that having the reassembly code in the v6 stack should be removed (why have it if it's not needed?).

The important point is this:
Given that a FreeBSD system can process fragmented packets on arrival, any firewall protecting that system MUST also process them, in a way that secures the system.

The ways of resolving this bug are:
a) assert it's not a valid requirement.  Close it.
b) agree it's a requirement, but too much effort.  Close it.
c) agree it's a requirement and leave it open until implemented.

The assignee should close it post haste if (a) or (b) is the outcome. Then we can all move on and find alternatives.

Scott
Comment 19 Helge Oldach 2019-12-10 05:42:29 UTC
(In reply to Scott Aitken from comment #18)
Please see Andrey's comments #5 and #7 which describe IPv6 router behaviour correctly. The motivation for different behaviour of IPv6 vs. IPv4 is that fragmentation and reassembly involve copying data and thus are expensive operations, contradicting to the aim of wire speed forwarding. Encapsulation, in contrast, is easily done by pre-allocating packet space for the prepended headers to avoid copying; decapsulation is even easier.

Here's a concise description of IPv6 fragmentation versus IPv4: https://network-insight.net/2015/10/ipv6-fragmentation/

Indeed it would be nice to be able to ipv6 reass in ipfw in order to catch corner cases, but it's not a fundamental necessity similar to IPv4.
Comment 20 Scott Aitken 2019-12-10 06:01:35 UTC
(In reply to Helge Oldach from comment #19)

Hi.  I couldn't care less about fragmentation.  What I care about is reassembly.  Something that FreeBSD already does despite the cost.

IPv6 reassembly is AS IMPORTANT as IPv4 reassembly when the FreeBSD host running IPFW is the end-host/target/destination node.

The RFC MANDATES it.

Say you have an END HOST (ie, not a router).
It sits on the Internet and happily reassembles any IPv6 fragments that come its way, passing them to the upper layers.
Now you want to secure it.
You want to use IPFW.
Well, you can't, because your only options are to allow or deny IPv6 fragmentation headers.  You don't have the ability to scrutinise IPv6 packets in their entirety that were otherwise arriving and being processed by the v6 stack.

Now run that scenario with IPv4.  With IPFW you CAN.

For feature parity between v4 and v6, you either enable reassembly for locally destined IPv6 packets, or you turn off reassembly for locally destined IPv4 packets (which is obviously a dumb thing to do).

The noise about IPv6 routers not fragmenting is not relevant.

Scott
Comment 21 Helge Oldach 2019-12-10 14:38:09 UTC
(In reply to Scott Aitken from comment #20)
The gotcha on an IPv6 end host is that mandatory PMTUD takes care that no fragmentation of TCP is needed. Similarly for UDP based application traffic (for example DNS - see draft-andrews-dnsext-udp-fragmentation-01). Note also the minimum MTU has been raised to 1280 in IPv6 which makes fragmentation less needed.

Again: Not saying that ip6 reass isn't a good thing, but lack thereof by far isn't as "dumb" as for IPv4.
Comment 22 Scott Aitken 2019-12-10 15:04:11 UTC
(In reply to Helge Oldach from comment #21)

"The gotcha on an IPv6 end host is that mandatory PMTUD takes care that no fragmentation of TCP is needed."

This is plain wrong, and if you'd read my earlier reply, or at least the RFCs, you would know that RFC 8200 says:
"It is strongly recommended that IPv6 nodes implement Path MTU Discovery [RFC8201]"
And RFC 8201 says:
"IPv6 nodes should implement Path MTU Discovery".

Note the use of the words RECOMMENDED and SHOULD in the above citations.  Neither of these mean mandatory.  Read RFC 2119 for help with explanations of common RFC terms.

What IS mandatory, is reassembly (as per RFC 8200):
A node must be able to accept a fragmented packet that, after reassembly, is as large as 1500 octets.

Disabuse yourself of your incorrect reading, or lack thereof, of the RFCs.  Your lack of care and resistance to a straightforward request is not entirely helpful, nor is this the right forum for education.

If you believe that an IPv6 node that MUST (and DOES) reassemble fragments does not require a firewall that does the same, close this ticket.
Comment 23 Peter Much 2022-06-22 21:36:23 UTC
Andrey, Your patch works like a charm! Thanks so much!

The question is not if we should defragment or not, or if we should only defragment on final or also inflight - because, as a matter of fact, we are doing it already, and we are doing it in either case:

   09760     2     1556 count ipv6-icmp from <my-site> to <remote-site>
   09765 82551 59384861 divert 8533 // internet(6)[FILTER][suricata]
   09770     1     1500 count ipv6-icmp from <my-site> to <remote-site>

[ For full details see here: https://forums.freebsd.org/threads/ipfw-and-ipv6-fragments.73311/post-572262 ]

The question, therefore, is only: how do I get my data to the destination?

And the big advantage of Andrey's patch is: as we do defragment anyway, with this patch at least my rules do work as normal (with the port numbers etc.). 
Now working on the remaining issues...