PF IPv6 fragments handling
Kristof Provost
kristof at sigsegv.be
Sat Mar 14 02:05:07 UTC 2015
On 2015-02-10 00:24:16 (+0100), Kristof Provost <kristof at sigsegv.be> wrote:
> On 2015-02-03 21:25:20 (+0100), Kristof Provost <kristof at sigsegv.be> wrote:
> > Two of my systems are currently running them, seemingly without
> > problems.
> >
> The initial patch set had problems refragmenting in forwarding
> scenarios. That should be fixed with the update to
> https://reviews.freebsd.org/D1767 and the extra patch in
> https://reviews.freebsd.org/D1815
>
Status update: all these patches other than D1815 have been committed.
There's one crash I know about in forwarding scenarios (and scrub on
output). There's a fix which will be committed as soon as it's had a bit
more testing.
The blocking point is D1815. There's no consensus on it right now, so
I'd like to go over the problem and the two possible solutions I see.
The problematic scenario is when we're forwarding fragmented IPv6
packets. Right now the fragmented packets are gathered up on the
ip6_input() netpfil hook (through pf_test6() -> pf_normalize_ip6() ->
pf_reassemble6()).
When we've found all of the fragments pf_reassemble6() will create a
reassembled fragment and tag it as having been reassembled.
pf_test6() then returns the reassembled packet to the IP stack. That
passes through ip6_input() and is handed to ip6_forward().
At that point we run into the packet size check, which in ip6_forward()
is done before the pfil(PFIL_OUT) hook. That means that we'll send an
ICMP6_PACKET_TOO_BIG error rather than forwarding the packet.
The proposed fix in D1815 is to simply move the size check after the
pfil(PFIL_OUT) hook so pf has the chance to refragment the packet (which
it does in pf_test6() -> pf_refragment6() because the packet has the
PF_REASSEMBLED tag).
That's also what the OpenBSD stack does.
In the D1815 review Gleb Smirnoff proposed a different solution. Instead
of returning a reassembled packet from pfil(PFIL_IN) in ip6_input() we
could change netpfil so we could return multiple packets. That means
we'd reassemble and immediately refragment on the input, and then do the
same on the output side.
I have a preference for the solution in D1815 for two reasons:
- it's less work for me. It's a relatively small change in ip6_output()
and nothing else. Changing netpfil so it can return multiple packets
is a more invasive change and will impact other firewalls too.
- it's less work for the kernel when forwarding. Not only do we only
reassemble and refragment once, but we also only need to do
ip6_forward() processing on a single packet, rather than for each
fragment.
Thoughts?
Regards,
Kristof
More information about the freebsd-net
mailing list