4

I am trying 1:1 stateless NAT traffic. The traffic is coming in via a GRE tunnel and exiting via a VPN.

I have done enough research to understand that traffic entering a linux box off of the GRE tunnel does not hit Conntrack and also will not hit iptables -t nat. iptales SNAT, DNAT or NETMAP all are required to be in the -t nat table.

There was a iproute2 stateless nat option, but it was removed in kernel version 2.6. Before that was removed you could do a ip route add nat 192.168.50.2 via 192.168.60.2

When the stateless nat was removed from iproute2, there was an RAWDNAT and RAWSNAT option in Xtables-addons package. Xtables-addons. Xtables-addons documentation still offers RAWDNAT and RAWSNAT as options, but they throw errors and Xtables-addons remove RAWSNAT/RAWDNAT

So that has now put me into the world of Traffic Control. Traffic control documentation is very sparse and hard to follow. Especially for the ingress handling.

So I have broken the problem down and now I am just trying to get a 1:1 simple stateless nat working using tc over my eth0. I have a box that has an address 192.168.234.5 and a route to 10.40.0.0/16. I am trying to nat 192.168.234.112 to 10.40.0.112, in both directions.

For the inbound packet coming from 10.40.0.112:

tc qdisc add dev eth0 ingress
tc filter add dev eth0 parent ffff: protocol ip prio 10 \
  u32 match ip src 10.40.0.112/32 \
  action nat ingress 10.40.0.112/32 192.168.234.112

and for outbound packets

tc qdisc add dev eth0 root handle 1: htb
tc filter add dev eth1 parent 1: protocol ip prio 10 \
   u32 match ip dst 192.168.234.112/32 \
   action nat egress 192.168.234.112/32 10.40.0.112 

Somehow I was actually able to get the above commands to work, but for the life of me I can no longer get them to work. I found a post on stackoverflow.com that had stated something about the default qdisc in Ubuntu (pfifo_fast) is classless so it does not provide for packet filtering, but I can not longer follow that post. You would think that "tc filter add" would provide an error message if you add to a qdisc that does not support filters, but this seems to succeed.

So here are the commands that I am running:

add the egress qdisc first so the ingress has something to attach to

tc qdisc add dev eth0 root handle 1: htb
tc qdisc add dev eth0 ingress

At this point tc qdisc reports

qdisc htb 1: dev eth0 root refcnt 2 r2q 10 default 0 direct_packets_stat 9 direct_qlen 1000
qdisc ingress ffff: dev eth0 parent ffff:fff1 ---------------- 
qdisc pfifo_fast 0: dev eth1 root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

Now adding the ingress filter like:

tc filter add dev eth0 parent ffff: protocol ip prio 10 \
   u32 match ip src 10.40.0.112/32 \
   action nat ingress 10.40.0.112/32 192.168.234.112

At this point if I ping 10.40.0.112, I would expect the answer to come from 192.168.234.112. But the filter never gets hit. Actually I never see the nat action applied to the packet, but the stats for that filter rule go up.

I would add the egress filter like:

tc filter add dev eth0 parent 1: protocol ip prio 10 \ 
   u32 match ip dst 192.168.234.112/32 \
   action nat egress 192.168.234.112/32 10.40.0.112

At this point the tc filters look like:

root@ubusswan1-VirtualBox:/home/ubusswan1# tc filter show dev eth0
filter parent 1: protocol ip pref 10 u32 
filter parent 1: protocol ip pref 10 u32 fh 800: ht divisor 1 
filter parent 1: protocol ip pref 10 u32 fh 800::800 order 2048 key ht 800 bkt 0 terminal flowid ??? 
  match c0a8ea70/ffffffff at 16
    action order 1:  nat egress 192.168.234.112/32 10.40.0.112 pass
root@ubusswan1-VirtualBox:/home/ubusswan1# tc filter show dev eth0 root
filter parent ffff: protocol ip pref 10 u32 
filter parent ffff: protocol ip pref 10 u32 fh 800: ht divisor 1 
filter parent ffff: protocol ip pref 10 u32 fh 800::800 order 2048 key ht 800 bkt 0 terminal flowid ??? 
  match 0a280070/ffffffff at 12
    action order 1:  nat ingress 10.40.0.112/32 192.168.234.112 pass 

Can you help me understand tc well enough to get this 1:1 nat going? Also is there a better way to debug tc filters that are not working?

2

I think you interchanged the src and dst matches. I've got for now:

#tc qdisc del dev eth0 ingress
#tc qdisc del dev eth0 root

tc qdisc add dev eth0 root handle 1: htb
tc qdisc add dev eth0 ingress

tc filter add dev eth0 parent ffff: protocol ip prio 1 u32 match ip dst $FROMIP action nat ingress $FROMIP $TOIP
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 match ip src $TOIP action nat egress $TOIP $FROMIP

#tc -s qdisc show dev eth0
#tc -s filter show dev eth0
#tc -s filter show dev eth0 parent ffff:

And this seems to work (I'm no tc expert, though)!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.