Hi Kristof, glad to read You!
I do not believe that to be the case. The first fragment, containing the protocol header, will also have an IPv6 fragment header and will also be allowed unconditionally.
No, doc clearly says
Such rule would match all not the first fragment datagrams
and this is how it works. I did this for testing, and it got the things through.
I agree that this is not a very safe solution, only slightly better than the one mentioned before.
Sadly it's not. The awful choice here, either deny IPv6 fragmentation at all, or open a simple way of bypassing firewall policy, is what motivated me to fix this issue in pf in the first place.
pf fully reassembles the packet before processing it. That fixes the above concerns, but comes at a performance cost.
Ah. Yes, that's what Andrey's patch in the bug report also does. And it works here. Only, it does not really solve the problem...
Performance is the reason, yes. Not fragmenting in routers along the path allows them to implement everything in hardware. Fragmenting is typically handled by the router's software, and this is much, much slower.
Performance is not the only reason, as I learned yesterday. Inflight de-/refragmentation does just
not work in IPv6. And now I am very very curious how You tackle this issue.
Situation :
Code:
router --<mtu=1492>-- INTERNET --<mtu=1480>-- othersite
|
client
What happens:
Code:
client# ping -u -c 1 -s 1452 othersite
PING6(1500=40+8+1452 bytes)
out: IP6 ICMP6, echo request, seq 0, length 1460
in: IP6 ICMP6, packet too big, mtu 1492
## this comes back from router, and it is correct.
## next try:
client# ping -u -c 1 -s 1452 othersite
PING6(1500=40+8+1452 bytes)
out: frag (0|1440) ICMP6, echo request, seq 0, length 1440
out: frag (1440|20)
in: ICMP6, packet too big, mtu 1480
## this now comes back from INTERNET, and it is also correct
## next try:
client# ping -u -c 1 -s 1452 othersite
PING6(1500=40+8+1452 bytes)
out: frag (0|1432) ICMP6, echo request, seq 0, length 1432
out: frag (1432|28)
in: ICMP6, packet too big, mtu 1480
Ouch - why does this happen? On the router is this:
[edit:
ping -m
is
ping -u
if you're on rel 12 or 13]
Code:
09760 2 1556 count ipv6-icmp from any to <othersite>
09765 82551 59384861 divert 8677 // internet(6)[FILTER][suricata]
09770 1 1500 count ipv6-icmp from any to <othersite>
And the manpage says:
Incoming packet fragments diverted by divert are reassembled before delivery to the socket.
Now it gets interesting: packets that come back from a divert socket are not sent per
netinet6/ip6_forward.c, they are sent with
netinet6/ip6_output.c. And
ip6_output() does (re)fragment.
But, the router can only see it's own mtu=1492. The ICMP6 "packet too big" from INTERNET had been sent to the client, the router cannot know this! So the whole thing is stuck at this point.
If, alternatively, we would send with
ip6_forward(), then this would only create another
ICMP packet too big, mtu 1492
sent to the client - which doesn't help either.
So this is the reason why inflight de-/refragmentation is not a good idea: if you do it, while everybody else does rather send icmp too-big, then that doesn't interplay.