In the course of helping another forum member earlier, I had cause to tinker with SNAT and DNAT. Reflexively I reached for the latest stable version of OpenWRT (19.07.7) and got stuck in. And then promptly got confused.
The other forum member was using 18.06.4, so I checked my thinking and spun up 18.06.4 alongside 19.07.7 for a comparison.
I set up SNAT and DNAT on both 18.06.4 and 19.07.7, and compared the GUI, the /etc/config/firewall
files, and the iptables rules for the NAT table. For example IP addresses, I picked addresses which resembled the OpenWRT version numbers, purely for illustrative purposes.
First the iptables rules.
DNAT:
- 18.06.4:
-A zone_wan_prerouting -d 18.0.6.4/32 -m comment --comment "!fw3: Inbound DNAT 18.06.4" -j DNAT --to-destination 172.18.6.4
- 19.07.7:
-A zone_wan_prerouting -d 19.0.7.7/32 -m comment --comment "!fw3: Inbound DNAT 19.07.7" -j DNAT --to-destination 172.19.7.7
SNAT:
- 18.06.4:
-A zone_wan_postrouting -s 172.18.6.4/32 -m comment --comment "!fw3: Outbound SNAT 18.06.4" -j SNAT --to-source 18.0.6.4
- 19.07.7:
-A zone_wan_postrouting -s 172.19.7.7/32 -m comment --comment "!fw3: Outbound SNAT 19.07.7" -j SNAT --to-source 19.0.7.7
Unless I miss my guess, that looks alright. Both sets of SNAT and DNAT rules appear to accomplish what one would expect from their purpose. So... what's the problem, right?
The GUI for DNAT looks reasonably sane:
The 19.07.7 GUI has some cosmetic changes, but the description of the NAT actions seems understandable across both versions.
The GUI for SNAT starts to look a bit odd:
18.06.4 clearly shows that the source host is in the "lan" zone. In contrast, 19.07.7 says the source host can be in any
zone.
The contents of /etc/config/firewall
seem consistent for DNAT:
18.06.4:
config redirect
option target 'DNAT'
option src 'wan'
option dest 'lan'
option name 'Inbound DNAT 18.06.4'
option src_dip '18.0.6.4'
option dest_ip '172.18.6.4'
option proto 'all'
19.07.7:
config redirect
option src 'wan'
option name 'Inbound DNAT 19.07.7'
option src_dip '19.0.7.7'
option dest_ip '172.19.7.7'
option dest 'lan'
option target 'DNAT'
list proto 'all'
But, the contents of /etc/config/firewall
for SNAT have melted my brain. I think I know what Winnie the Pooh felt like.
18.06.4:
config redirect
option enabled '1'
option target 'SNAT'
option src 'lan'
option dest 'wan'
option proto 'all'
option src_dip '18.0.6.4'
option name 'Outbound SNAT 18.06.4'
option src_ip '172.18.6.4'
19.07.7:
config nat
option name 'Outbound SNAT 19.07.7'
option src_ip '172.19.7.7'
option target 'SNAT'
option snat_ip '19.0.7.7'
option src 'wan'
list proto 'all'
18.06.4 draws a distinction between the real source (the internal host), the translated source (the public IP address), and the destination (the outside world), and shows this distinction with its src
, src_dip
and dest
directives. This makes sense to me: where did the traffic originate (a host on the LAN), where is it going to (somwhere in the outside world), and what source IP address will the packets have when they sally bravely forth from the router (the translated public IP address)?
19.07.7, on the other hand, does not have a dest
directive, and instead shows the source of the traffic as the outside world (src 'wan'
). This does not make sense to me. If I ask myself, "where did the traffic originate?" I still come back with the answer: the internal host.
Indeed, if I try to "correct" the configuration to what I think it ought to be (src 'lan'
and dest 'wan'
), /etc/init.d/firewall
whines at me that "Option @nat[0].dest is unknown
", and the corresponding SNAT rule moves from the zone_wan_postrouting
chain to the zone_lan_postrouting
chain.
If the end result is that iptables shows a sensible SNAT rule, then I guess it's all working properly. But the files and pages to administer that SNAT rule look, well, just weird.
I've looked at the v19 changelogs to see if there's anything obvious which might explain this, but without success. Either there's nothing obvious there, or there is but I'm missing it.
So, am I being dim and misunderstanding something fundamental about the latest incarnation of OpenWRT? Or is there genuinely an error in the code used to manage and display that SNAT configuration to the intrepid administrator?