My question: is there a way to bind uHHTPd to the WAN interface only without specifying a specific IP address or 0.0.0.0?
I've set up a second uHHTPd server for external WAN access to a small number of fairly static information. I don't want to expose the LuCI interface for the router on the external WAN address. My issue is that my ISP provides a dynamic address and each time the WAN address changes, I have to manually reconfigure the listen_http and listen_https directives. If I bind on 0.0.0.0 then that will interfere with the 'standard' LuCI interface bound to 192.168.1.1
The relevant section from /etc/config/uhttpd follows
I don't think what you are asking for is possible. I would make a base config file without the listen lines, and a shell script that reads the external IP (search the web for examples), checks if it has changed, copies the base config over the normal one and adds
echo " list listen_http '$newip:80'" >> /etc/config/uhttpd
echo " list listen_https '$newip:443'" >> /etc/config/uhttpd
and then restarts the server, and run it as a cron job.
First off, I'd never expose uhttpd to the public Internet. It certainly isn't designed, built, or tested to meet all that the wild world throws at web servers. If you are going to expose web services to the Internet, please use a more robust server, such as nginx or current apache.
Should you decide that the risks of router compromise and associated credential and data loss are acceptable, and willing to allow your compromised router to be used in other attacks, to achieve "address independence" I'd suggest running the server on loopback on a different port (NNNN), then using port-forwarding to access it on localhost:NNNN
As @jeff mentioned, LuCI, as with every other management WebUI, should NEVER be exposed to WAN, period.
If you want access to LuCI from WAN, configure a SSH connection (disabling password auth completely, regardless) with a tunnel to router's LAN IP on port 443.
PuTTY:
Connection -> SSH -> Tunnels
Source Port(Arbitrary):20443
Destination:192.168.1.1:443
Assumes router's IP is 192.168.1.1
Select Add
Once SSH session is connected, navigate to: https://127.0.0.1:20443
#!/bin/sh
if [ "$ACTION" != "ifup" ] && [ "$ACTION" != "ifupdate" ]; then exit 0; fi
. /lib/functions/network.sh
network_flush_cache
network_get_ipaddr ip wan
[ -n "$ip" ] || exit 0
logger -t uhttpd-ip-changer "Updating WAN IP: $ip due to $ACTION of $INTERFACE ($DEVICE)"
uci set uhttpd.external.listen_http="${ip}:80"
uci set uhttpd.external.listen_https="${ip}:443"
uci commit uhttpd
/etc/init.d/uhttpd restart
Thank you all for the information. The largest use-case that I have for an internet facing webserver is for ACME/LetsEncrypt renewals. I actively do not want external access to LuCI (and mentioned this in my original post).
I'll have a look at alternatives and see is it possible to set them up in a non-root context without twisting myself into hoops. If not, then I'll see about disabling ACME renewals and finding a manual alternative.
Which are only up for a minute, once every three months, and only serve a single token at a non-root location, for those not familiar with the process.
What about just using certbot in --standalone mode rather than uhttpd?