Subject: Thoughts on draft-gont-6man-deprecate-atomfrag-generation-01

From: Alberto Leiva <[email-masked]>
Date: Wed, 26 Nov 2014 15:52:30 -0600

Hello.

I'm an implementor of a NAT64 on Linux (www.jool.mx).

I've been reading draft-gont-6man-deprecate-atomfrag-generation-01, and I'm
a huge fan of the changes it proposes to RFC 6145.

RFC 6145's reliance on the DF flag has always been obnoxious to implement,
because DF doesn't seem to be too widely acknowledged by IPv4 stacks in the
wild.

By that I mean, the defragmenters of Linux 3.6 and below have a really bad
habit of turning it off (
http://lxr.free-electrons.com/source/net/ipv4/ip_fragment.c?v=3.6#L651),
and this is not even reverted when the packet is forwarded. RFC 6145's
decision making based on DF has always been a major thorn in the back
whenever we've wanted the defragmenter and our NAT64 to coexist peacefully;
we have been forced to disregard corner-case scenarios and/or estimate the
original intended value, which has left something to be desired during
testing.

(In particular, the defragmenter needs to be present if a stateful Linux
firewall is in the way.)

The IPv6 defragmenters of kernels 3.13 and above also try very hard to
conceal the fragment header, though this is a lot easier to work around.

It seems to me the draft proposes a more robust NAT64. I would be very
happy to see this draft upgraded to RFC status so I can blatantly delete
(or at least out-default) the troublesome code.

Thank you for reading
Alberto Leiva

---

From: Fernando Gont <[email-masked]>
Date: Thu, 27 Nov 2014 09:12:25 -0300

Hi, Alberto,

Thanks so much for your feedback! -- Please find my comments in-line...

On 11/26/2014 06:52 PM, Alberto Leiva wrote:
> 
> I'm an implementor of a NAT64 on Linux (www.jool.mx <http://www.jool.mx>).
> 
> I've been reading draft-gont-6man-deprecate-atomfrag-generation-01, and
> I'm a huge fan of the changes it proposes to RFC 6145.
> 
> RFC 6145's reliance on the DF flag has always been obnoxious to
> implement, because DF doesn't seem to be too widely acknowledged by IPv4
> stacks in the wild.
> 
> By that I mean, the defragmenters of Linux 3.6 and below have a really
> bad habit of turning it off
> (http://lxr.free-electrons.com/source/net/ipv4/ip_fragment.c?v=3.6#L651), and
> this is not even reverted when the packet is forwarded. 

Defragmenters == fragment-reassembly code? Something else?

> conceal the fragment header, though this is a lot easier to work around.

Could you elaborate a bit ore on what you mean here?

> (or at least out-default) the troublesome code.

Thanks!

Best regards,
-- 
Fernando Gont
e-mail: [email-masked] || [email-masked]
PGP Fingerprint: 7809 84F5 322E 45C7 F1C9 3945 96EE A9EF D076 FFF1

---

From: Alberto Leiva <[email-masked]>
Date: Thu, 27 Nov 2014 12:12:06 -0600

Hello

I apologize for the briefness of my earlier message. I will try to
ellaborate here.

> Defragmenters == fragment-reassembly code? Something else?

Correct. In particular, I'm talking about the nf_defrag_ipv4 and
nf_defrag_ipv6 kernel modules. See below.

> Could you elaborate a bit ore on what you mean here?

About the firewall statement:

The Linux firewall (iptables) requires connection tracking (conntrack)
while operating on stateful mode. Connection tracking, in turn, depends on
defragmentation.

This can be seen while configuring a stateful firewall. The iptables
command automatically inserts the respective defrag if needed:

$ # List all modules named "defrag".
$ lsmod | grep defrag
$
$ # Create a random stateful rule.
# iptables -A FORWARD -i ppp0 -m state ! --state NEW -j DROP
$
$ # List the modules again.
$ # First column in the output is module name. Fourth column is modules
which depend on it.
$ lsmod | grep defrag
nf_defrag_ipv4         12758  1 nf_conntrack_ipv4

My dilemma is that this has several side effects, of which the most
hazardous one for my implementation is the unavoidable disregard of the DF
flag of nf_defrag_ipv4 from certain kernels. If I put an Ubuntu 12.04
machine (kernel 3.2) as a firewall, it turns off the DF flag of any
fragments that traverse it.

Of course, fragments with DF=true are pretty nonsensical anyway (as far as
I know), but they aren't illegal either.

--------------------------------------

About the fragment header problem:

It's not very important, since it's not completely eradicated by the draft
yet it's not hard to work around anyway, but in case you're curious...

After packets have traversed one of the defragmentation modules, the
tendency of the packet manipulation API of the Linux kernel is to hide the
packet's fragmentation-related data. I guess this is done to simplify the
code elsewhere. Any module who depends on either defrag does not have to
worry about fragmentation at all.

For example, in kernels 3.13 and above, the fragment headers of IPv6
fragments are deleted and subsecuent fragments (fragment offset != 0) are
hidden. When I ask for the length of the packet, it returns the length of
all fragments combined (minus redundant layer 3 headers, of course). Even
though by analyzing the memory I can see that the packet I'm fetched is
truncated, I can ask for data and the API will peek on subsequent fragments
if needed. This is all reverted when the packet is forwarded (unless some
random module "linearizes" the packet, in which all fragmentation leftovers
are irreversibly eradicated and I might well be reading and forwarding
misleading data).

It's nice, but it demands some hackery when I need to compatibilize with
the following idea from RFC 6145:

    In addition, the rules in Section 4.1 use the presence of an IPv6
Fragment Header to indicate that the sender might not be using path MTU
discovery

I think that's all. Regards,
Alberto

On Thu, Nov 27, 2014 at 6:12 AM, Fernando Gont <[email-masked]> wrote:

> > I'm an implementor of a NAT64 on Linux (www.jool.mx <http://www.jool.mx
> >).
> >

---

From: Alberto Leiva <[email-masked]>
Date: Thu, 27 Nov 2014 15:22:38 -0600

> It's not very important, since it's not completely eradicated by the
draft yet it's not hard to work around anyway

Never mind the "it's not hard to work around" part. I just noticed
nf_defrag_ipv6 on newer kernels also deletes the fragment header on atomic
fragments and doesn't bother to ever return it.
It's really bad. Looks like we have no way to reliably implement "use the
presence of an IPv6 Fragment Header to indicate that the sender might not
be using path MTU discovery".

Sorry for the double message.
Alberto