Okay, the workaround works. Since I spend more than 1 day to figure it out, I would like to share the solution here (of course I just collected it from different sources). Hopefully it helps someone.
Actually the title should be "zone-to-zone nat loopback"
It seems pretty common if someone hosts something on own servers (e.g. webserver) at home.
Nat loopback ~= if a server (reachable on the internet) runs in own private network, then the traffic is not routed though the internet but only internally.
Everything starts with "port forwarding".
→ Network → Firewall → Port Forwards → ... → Advanced settings → check: Enable NAT Loopback + Loopback source IP: use internel IP address (both are defaults)
via ssh it would be:
cat /etc/config/firewall
config redirect
option dest 'lan' #"option dest" is required for "reflection"
option reflection '1'
option reflection_src 'internal'
but those entries are not visable because they are default. Official doc can be found here: https://openwrt.org/docs/guide-user/firewall/firewall_configuration#redirects
This nat loopback (reflection) creates automatically the correct redirect iptables rules for all zones where the actual server (e.g. webserver) is located (in my case lan
).
But guest
is not part of the zones that's why no redirect iptables rules are created for.
Examples for the automated redirect iptables rules can be found here:
iptables-save -c | grep reflection
[39:2849] -A zone_lan_postrouting -s 192.168.12.0/24 -d 192.168.12.77/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: https (reflection)" -j SNAT --to-source 192.168.12.1
[39:2849] -A zone_lan_prerouting -s 192.168.12.0/24 -d xx.xx.xx.xx/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: https (reflection)" -j DNAT --to-destination 192.168.12.77:443
So we have to implement similar rules for the zone guest
manually (based on https://bugs.openwrt.org/index.php?do=details&task_id=1645&dev=4):
→ Network → Firewall → Custom Rules
alternatively: vi /etc/firewall.user
. /lib/functions.sh
. /lib/functions/network.sh
network_get_subnet guest guest
network_get_ipaddr wan wan
network_get_ipaddr lan lan
webserverip=192.168.12.77
webserverport=443
iptables -t nat -A postrouting_guest_rule -s $guest -d $webserverip/32 -p tcp -m tcp --dport $webserverport -j SNAT --to-source $lan -m comment --comment "firewall.user: webserver https guest to lan rule (reflection)"
iptables -t nat -A prerouting_guest_rule -s $guest -d $wan -p tcp -m tcp --dport $webserverport -j DNAT --to-destination $webserverip:$webserverport -m comment --comment "firewall.user: webserver https guest to lan rule (reflection)"
btw: wan ip is dynamic. so even after getting a new ip it is correct.
btw: "postrouting_guest_rule" ==> "guest" matters!!!
→ Save
restart firewall (reload is not enough yet!)
/etc/init.d/firewall restart
#be sure there are no errors
in order to make it safe for OpenWrt reboots:
based on: https://dev.archive.openwrt.org/ticket/20249.html
vi /etc/config/firewall
config include
option path '/etc/firewall.user'
option reload '1'
/etc/init.d/firewall reload
now reload
is enough and a restart
is not needed anymore.
The results can be checked via:
iptables-save -c | grep reflection | grep firewall.user
[0:0] -A postrouting_guest_rule -s 192.168.3.0/24 -d 192.168.12.77/32 -p tcp -m tcp --dport 443 -m comment --comment "firewall.user: webserver https guest to lan rule (reflection)" -j SNAT --to-source 192.168.12.1
[17:1020] -A prerouting_guest_rule -s 192.168.3.0/24 -d xx.xx.xx.xx/32 -p tcp -m tcp --dport 443 -m comment --comment "firewall.user: webserver https guest to lan rule (reflection)" -j DNAT --to-destination 192.168.12.77:443
PS: officially its not a bug but more a new feature request in order to support it without the manual workaround.