5

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?

1 Answer 1

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)!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .