DNAT reflection for local requests (originating from router)

Greetings.

I have an HTTP(S) server that's running inside my local network (on a personal server, not on the router) that I expose to the Internet via a port forwarding rule for tcp port 80 (and a completely equivalent rule for port 443).

# cat /etc/config/firewall
<...>
config redirect
        option target 'DNAT'
        option src 'wan'
        option dest 'lan'
        option src_dport '80'
        option dest_ip '10.196.254.2'
        option dest_port '80'
        option proto 'tcp'
        option name 'http@stratofortress'
<...>

With NAT reflection enabled by default for this redirect rule, it yields 3 iptables rules:

# iptables -S -t nat | grep 'http@stratofortress'
-A zone_lan_postrouting -s 10.196.254.0/24 -d 10.196.254.2/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: http@stratofortress (reflection)" -j SNAT --to-source 10.196.254.1
-A zone_lan_prerouting -s 10.196.254.0/24 -d 95.84.164.43/32 -p tcp -m tcp --dport 80 -m comment --comment "!fw3: http@stratofortress (reflection)" -j DNAT --to-destination 10.196.254.2:80
-A zone_wan_prerouting -p tcp -m tcp --dport 80 -m comment --comment "!fw3: http@stratofortress" -j DNAT --to-destination 10.196.254.2:80

This works OK for requests from the Internet and LAN likewise, but does not work for the requests originating from the router itself.

Maybe there is a configuration option that I missed that will do everything properly? If there isn't, which rules do I need to add to support NAT reflection for local requests?

First, at least in my opinion, properly managing DNS is a much more robust approach than hairpin NAT, and may be what you need to resort to.

If you want to continue with NAT, with the server on the same box, the route will be through loopback and will never hit a forward rule. It is a direct connection. Edit: No forward in play for router to inside host either.

2 Likes

Add the FQDN of the server in /etc/config/dhcp

config domain
        option name 'www.stratofortress.com'
        option ip '10.196.254.2'

and restart dnsmasq service. No need for *NATs

3 Likes

@jeff @trendy No, I explicitly do not want to use any kind of a split DNS setup. My DNS setup is very complex (to be clear, I'm not using builtin OpenWRT's dnsmasq) and I do not want to make it even more complex.

Also, split DNS is hardly "properly managing DNS" :slight_smile: Won't work with DNSSEC too.

@jeff

If you want to continue with NAT, with the server on the same box, the route will be through loopback and will never hit a forward rule. It is a direct connection. Edit: No forward in play for router to inside host either.

To clarify, the router and the server are not the same box.

You can try something like

iptables -t nat -A OUTPUT -p tcp -d 12.34.56.78 --dport 80 -j DNAT --to-destination 10.196.254.2

however it seems to me way easier to add an entry in hosts file.

1 Like

It would appear that OUTPUT chains are consulted after routing. Indeed, if I add this rule, fire up tcpdump -i eth0.2 -vvv 'tcp port 80' (where eth0.2 is my WAN interface) and make a request, it shows that the packet to 10.196.254.2 is sent from the WAN interface. That's exactly the problem I've hit originally.

Any ideas?

Try postrouting chain, or use the hosts file.