Help requested for NAT Loopback

Hi!
I have a web server running in a DMZ, which is an interface defined on its own VLAN (you can find plenty of guide on how to configure a DMZ). This web server correctly connects to the internet and is reachable from WAN, so the port forward rules work. These rules are nothing special:

  • WAN 80/tcp -> internalIP 80/tcp
  • WAN 443/tcp -> internalIP 443/tcp.

Now, I'd like to reach the web server from LAN by using my domain instead of its internal hostname, possibly without defining hostnames from LuCI, as I'm using plenty of subdomains (a.mydomain.org, b.mydomain.org...) and I'm lazy. So here's when I discovered about NAT Loopback, but it doesn't work. curling https://a.mydomain.org returns "Connection refused", whereas http://a.mydomain.org returns "Rejected request from RFC1918 IP to public server address", so I think in this case it's LuCI that's replying.
What's the correct way to set up NAT Loopback?

What is the output of
uci export network ; uci export firewall ; iptables-save -c | grep reflection

1 Like

How about SNAT requests from lan network to lan gateway ip address?

iptables -t nat -A POSTROUTING -s lan-net -p tcp -m tcp --dport 80 -j SNAT --to-source lan-gw

EDIT: OpenWrt firewall config has NAT loopback (reflection) support builtin, see (https://openwrt.org/docs/guide-user/firewall/firewall_configuration#redirects)

I know of no direct way to setup a "NAT loopback" on OpenWrt - except for the exact IP in question (as there is a check box).

Since you don't want to edit your DNS, I'd suggest making a redirect that drops the packet back in the same network, so it forwards to the VLAN with the private IP. FYI, the domain method is most recommended on the forum - as this takes CPU resources on the router to NAT.

config redirect
	option target 'DNAT'
	option src 'wan'
	option proto 'tcp'
	option src_dport '80'
	option dest_ip '192.168.x.y'
	option dest_port '80'
	option src_ip '192.168.1.0/24'
	option dest 'lan'
	option name 'REDIRECT_HTTP_LAN'

This seems like it's a reply from your web server, as the source IP is a private address to a Public...it also reminds me of an OpenWrt security error...

@trendy

package network

config interface 'loopback'
        option ifname 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fd6a:e0c4:6dd0::/48'

config interface 'lan'
        option type 'bridge'
        option ifname 'eth0.1'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

config interface 'wan'
        option ifname 'eth0.2'
        option proto 'pppoe'
        option password 'timadsl'
        option ipv6 'auto'
        option username 'timadsl'
        list dns '193.183.98.66'
        list dns '192.71.245.208'
        option peerdns '0'

config device 'wan_eth0_2_dev'
        option name 'eth0.2'
        option macaddr 'e8:94:f6:d4:31:1b'

config switch
        option name 'switch0'
        option reset '1'
        option enable_vlan '1'

config switch_vlan
        option device 'switch0'
        option vlan '1'
        option ports '5 4 3 2 0t'
        option vid '1'

config switch_vlan
        option device 'switch0'
        option vlan '2'
        option ports '1 0t'
        option vid '2'

config switch_vlan
        option device 'switch0'
        option vlan '3'
        option ports '5t 4t 3t 2t 0t'
        option vid '3'

config interface 'guest'
        option proto 'static'
        option ipaddr '192.168.2.1'
        option netmask '255.255.255.0'

config interface 'DMZ'
        option ifname 'eth0.3'
        option proto 'static'
        option ipaddr '192.168.3.1'
        option netmask '255.255.255.0'

config interface 'Modem'
        option ifname 'eth0.2'
        option proto 'static'
        option netmask '255.255.255.0'
        option ipaddr '192.168.0.2'

package firewall

config defaults
        option syn_flood '1'
        option output 'ACCEPT'
        option forward 'REJECT'
        option input 'ACCEPT'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        option network 'lan'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        option network 'wan Modem'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option src_ip 'fc00::/6'
        option dest_ip 'fc00::/6'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config include
        option path '/etc/firewall.user'

config zone
        option network 'guest'
        option forward 'REJECT'
        option name 'guest'
        option output 'ACCEPT'
        option input 'REJECT'

config forwarding
        option dest 'wan'
        option src 'guest'

config rule
        option src 'guest'
        option name 'Guest DNS'
        option target 'ACCEPT'
        option dest_port '53'

config rule
        option dest_port '67-68'
        option src 'guest'
        option name 'Guest DHCP'
        option target 'ACCEPT'
        list proto 'udp'

config zone
        option network 'DMZ'
        option forward 'REJECT'
        option name 'dmz'
        option input 'REJECT'
        option output 'ACCEPT'

config rule
        option dest_port '53'
        option src 'dmz'
        option name 'DMZ DNS'
        option target 'ACCEPT'

config rule
        option dest_port '67-68'
        option src 'dmz'
        option name 'DMZ DHCP'
        option target 'ACCEPT'
        list proto 'udp'

config forwarding
        option dest 'wan'
        option src 'dmz'

config forwarding
        option dest 'dmz'
        option src 'lan'

config redirect
        option dest_port '80'
        option src 'wan'
        option name 'Web server HTTP'
        option src_dport '80'
        option target 'DNAT'
        option dest_ip '192.168.3.10'
        option dest 'dmz'
        list proto 'tcp'

config redirect
        option dest_port '443'
        option src 'wan'
        option src_dport '443'
        option target 'DNAT'
        option dest_ip '192.168.3.10'
        option dest 'dmz'
        list proto 'tcp'
        option name 'Web server HTTPS'

[0:0] -A zone_dmz_postrouting -s 192.168.3.0/24 -d 192.168.3.10/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: Web server HTTP (reflection)" -j SNAT --to-source 192.168.3.1
[0:0] -A zone_dmz_postrouting -s 192.168.3.0/24 -d 192.168.3.10/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: Web server HTTPS (reflection)" -j SNAT --to-source 192.168.3.1
[0:0] -A zone_dmz_prerouting -s 192.168.3.0/24 -d 95.237.136.248/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: Web server HTTP (reflection)" -j DNAT --to-destination 192.168.3.10:80
[0:0] -A zone_dmz_prerouting -s 192.168.3.0/24 -d 192.168.0.2/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: Web server HTTP (reflection)" -j DNAT --to-destination 192.168.3.10:80
[0:0] -A zone_dmz_prerouting -s 192.168.3.0/24 -d 95.237.136.248/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: Web server HTTPS (reflection)" -j DNAT --to-destination 192.168.3.10:443
[0:0] -A zone_dmz_prerouting -s 192.168.3.0/24 -d 192.168.0.2/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: Web server HTTPS (reflection)" -j DNAT --to-destination 192.168.3.10:443

NAT Loopback is configured correctly. However since you have enabled for WAN->DMZ traffic, it works for incoming traffic from DMZ.

Try these rules and it should be fine. Save them in /etc/firewall.user

iptables -t nat -A zone_lan_postrouting -s 192.168.1.0/24 -d 192.168.3.10/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: Web server HTTP (reflection)" -j SNAT --to-source 192.168.1.1
iptables -t nat -A zone_lan_postrouting -s 192.168.1.0/24 -d 192.168.3.10/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: Web server HTTPS (reflection)" -j SNAT --to-source 192.168.1.1
iptables -t nat -A zone_lan_prerouting -s 192.168.1.0/24 -d 95.237.136.248/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: Web server HTTP (reflection)" -j DNAT --to-destination 192.168.3.10:80
iptables -t nat -A zone_lan_prerouting -s 192.168.1.0/24 -d 192.168.0.2/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: Web server HTTP (reflection)" -j DNAT --to-destination 192.168.3.10:80
iptables -t nat -A zone_lan_prerouting -s 192.168.1.0/24 -d 95.237.136.248/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: Web server HTTPS (reflection)" -j DNAT --to-destination 192.168.3.10:443
iptables -t nat -A zone_lan_prerouting -s 192.168.1.0/24 -d 192.168.0.2/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: Web server HTTPS (reflection)" -j DNAT --to-destination 192.168.3.10:443

I only tried the first two lines because I think, although I'm not sure, I only need those. Anyway, they both return an error: "iptables: No chain/target/match by that name."

Try adding -t nat to those commands

1 Like

Thanks @yousong for catching it, I fixed the post above.

OK, these commands did the trick!
Apparently I only need these ones:

iptables -t nat -A zone_lan_prerouting -s 192.168.1.0/24 -d 95.237.136.248/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: Web server HTTP (reflection)" -j DNAT --to-destination 192.168.3.10:80
iptables -t nat -A zone_lan_prerouting -s 192.168.1.0/24 -d 95.237.136.248/32 -p tcp -m tcp --dport 443 -m comment --comment "!fw3: Web server HTTPS (reflection)" -j DNAT --to-destination 192.168.3.10:443

The first 2 lines @trendy posted seem to be unnecessary to me, and the rules referring to 192.168.0.2 are related to my modem interface, in this case I'm sure I don't need them.

My IP address is dynamic, but since /etc/firewall.user is a shell script I could just fire up some commands and save my current address in a variable :slight_smile:

If your problem has been solved feel free to mark the topic as solved :slight_smile:

1 Like

I found out that my request has been marked as a bug for a long time: https://bugs.openwrt.org/index.php?do=details&task_id=1645&dev=4

  • The person who made that bug ticket also misunderstands the NAT loopback function.
  • The same bug for LuCI was closed too.
  • Actually it was converted to a feature request, because it works as intended. I'm not sure how you missed that on the page you linked.

Did you see my post:

Most importantly, did you see the developer's response in the bug report, who says it should work for the zone too and addresses the future of your said request:

This is by design. The setup of NAT loopback rules is currently tied to the zone of the target host.

I might look into introducing a new option "reflection zones" or similar to change set but I can't promise that it'll happen anytime soon.

~ @jow

Easy @lleachii, I didn't mean to be rude or to complain, my intention was just to point future readers to that ticket. It is a feature wanted not by just a single individual, apparently.
Also, some people call "bug" any report filed in a bug tracker, regardless of its kind, and the LuCI "bug" was closed not because it's a pointless feature but because it's not implemented in backend to begin with.

Anyway, @trendy kindly provided me a solution, so I'm not stuck doing what I want.

I never said it was pointless.

And I think you (maybe) understand why it was closed now; as I noted there's no magical button (currently).

  • Are you willing to script this behavior and offer as code request?
  • Also, if you did so, how would the OpenWrt know what zones to allow the redirect for? Perhaps that has to be coded too...

You may wish to open a thread in the For Developers section (or move this one).

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.