How to configure uHTTPd server on dynamic address

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

config uhttpd 'external'
        option tcp_keepalive '1'
        option redirect_https '0'
        option rfc1918_filter '0'
        option home '/www-ext'
        option cert '/etc/acme/x/x.cer'
        option key '/etc/acme/x/x.key'
        option no_symlinks '1'
        option no_dirlists '1'
        list listen_http 'w.x.y.z:80'
        list listen_https 'w.x.y.z:443'

Thanks for your attention.

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

2 Likes

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

/etc/hotplug.d/iface/90-uhttpd-ip-changer:

#!/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.

My bad, I totally misread that =]

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?

You can even specify your own ports for certbot to use.