NAT loopback not working for home assistant

I have a home assistant instance running on a raspberry pi at 10.4.20.10 using a letsencrypt ssl cert for external access. In order to use the same url from both internal and external access, I was previously using NAT loopback on an edgrouter x. After switching to a nanopi R6s, I can no longer get this working. I have configured port forwarding with NAT loopback from within luci but it doesn't seem to be working correctly.

I can access home assistant externally but not internally. Can anyone spot what I'm doing wrong?

config defaults
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        option synflood_protect '1'
        option fullcone '1'

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

config zone
        option name 'wan'
        option output 'ACCEPT'
        option fullcone4 '1'
        option fullcone6 '1'
        option masq '1'
        option mtu_fix '1'
        option input 'REJECT'
        option forward 'REJECT'
        list network 'wan'
        list network 'wan6'

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 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 'miniupnpd'
        option type 'script'
        option path '/usr/share/miniupnpd/firewall.include'

config redirect
        option dest 'lan'
        option target 'DNAT'
        option name 'HomeAssistant443'
        list proto 'tcp'
        option src 'wan'
        option src_dport '443'
        option dest_ip '10.4.20.10'
        option dest_port '443'
        option reflection_src 'external'
        option enabled '1'
        option reflection '1'

config redirect
        option dest 'lan'
        option target 'DNAT'
        option name 'HomeAssistant8123'
        list proto 'tcp'
        option src 'wan'
        option src_dport '8123'
        option dest_ip '10.4.20.10'
        option dest_port '8123'
        option reflection_src 'external'
        option enabled '1'
        option reflection '1'

config zone
        option name 'vpn'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'Wireguard'

config forwarding
        option src 'lan'
        option dest 'vpn'

config forwarding
        option src 'vpn'
        option dest 'wan'

config rule
        option target 'ACCEPT'
        option src 'wan'
        option dest_port '51820'
        option name 'wg'
        option proto 'udp'

I've never used NAT loopback, sorry, can't help you there. But I'm wondering if the objective could be more efficiently accomplished by simply setting dnsmasq up with the external hostname that points to the internal address.

1 Like

Example using 80/tcp:

Correct me if I'm wrong but this will have all local devices try to connect on the 10.4.20.10 local address and then the SSL cert will error out because it is not using the public address.

OK.

  • No, the router will do the NATing (no different than any other NAT) - the client believes it's connecting to its usual DST IP
  • That's what any port forward does
  • Certs are by domain name anyway, not IP. So the rule solves that

(I'm not sure how this part is OpenWrt-specific, though.)