If it can be of any help to someone looking at this thread one day, here is how I solved the problem for my own use. I have hass.io, used duckdns and lets encrypt, own a decent linux based firewall and uses Pihole on Hass.io.
To put it short, I wanted to be able to use the hass app, without reconfiguring when I’m inside or outside.
So I added a line in my pihole config:
replace XXX / YYY by the proper settings. As mentionned before, you can achieve the same by adding a line in your /etc/hosts file if you don’t use pihole.
Then, I added a line in my firewall:
$IPTABLES -t nat -A PREROUTING -m set --match-set whitelist src -p tcp --dport 8123 -j DNAT --to 192.168.0.XXX
$IPTABLES -A FORWARD -p all -m set --match-set whitelist src -j ACCEPT
for the one not too familiar with iptables, you could narrow it down to:
iptables -t nat -A PREROUTING --dport 8123 -j DNAT --to 192.168.0.XXX
iptables -A FORWARD [-s IP_I_TRUST] -p tcp --dport 8123 -j ACCEPT
The only difference is that I use an ipset to store my whitelisted IP in coordination with port knocking.
(On Iphone, I have an App named KnockonD, it sends a stream of packet in a certain order and the IP they were sent from is added to the whitelist ipset, which himself is whitelisted in my firewall)
You can do the same with basic NAT in your router box. (but I don’t trust any object / technology / app, so I do firewall everything and impose port knocking to any app/tools willing to connect home).
Finally, in the app, I just leave the same good old URL for accessing the app:
Hope this helps.