Subject: stateless nat *please* tell me how I'm supposed to use it

From: Erik Slagter <[email-masked]>
Date: Mon, 16 May 2011 15:55:56 +0200

Hello devs,

Normally I wouldn't dare to ask my question here, but really there is
nothing to be found that explains how to do this.

For a high availability router-cluster I need to do static nat. The only
thing it needs to do is replace a dst ipv4 address or a src ipv4
address, depending on src/dst host ip. It does not need to keep any
state / connection tracking etc. Actually I'd prefer to not have it
tracked. Both routers need to be able to take over routing from the
other at any given moment and therefore cannot transfer state
information to the other one.

These are the approaches I've tried and/or considered:

- use iptables stateful NAT in combination with a NOTRACK target:
doesn't work, as soon as a packet is marked NOTRACK, it doesn't get
NATted at all
- use iptables stateful NAT anyway and hope for the best: this kind of
works, but I am not happy with it
- use stateless nat from "ip route": abandoned because "deprecated"
- use "mangle" from iptables: doesn't work because you can't "mangle"
the addresses (which is kind of stupid imho)
- use conntrackd: that will probably work, but it's way too complex for
something simple I want to do.
- finally: use tc action nat as seem to be recommended of late.

Attempt 1: using "tc filter ... action nat ..." syntax.

# tc filter add dev eth0 parent root protocol ip prio 10 u32 match u32 0
0 action nat ingress 1.2.3.4 4.5.6.7
RTNETLINK answers: Invalid argument

This suggests that the construct is recognised by tc but the kernel
doesn't (fully) understand this. That's weird because devs said earlier
it should work from somewhere 2.6.29 onwards. I've added some printk's
to the act_nat.c file and that learns that this code isn't called at
all, so probably something else (rtnetlink?) already bails out. So...
this doesn't work.

Attempt 2: using "tc action" syntax

This syntax is not described anywere other than in the help, so I'm just
try-and-error-ing.

# tc action add nat egress 1.2.3.4 4.5.6.7

Now this works, well, it doesn't throw errors. It doesn't do anything
either. I guess this action needs to be called from a filter, other than
incorporating it INTO the filter (which doesn't work). There is no
syntax (described) that allows a filter to call an action indirectly.

So my question is, how am I supposed to do something that simple as
replacing a few bytes in an ip header with the effect of a stateless nat.

Thanks very much.