Stop the frequent firewall and https-dns-proxy reloads on DHCP lease renewals

[ EDIT 1: Changed the https-dns-proxy code… the old code would still check IP addresses and not restart if the ‘old’ and ‘new’ IP addresses were the same, even when a manual restart command was issued. ]

Comcast sometimes sets a WAN IP leasetime of 3600 seconds, sometimes of 7200 seconds.

Each time, I get the same exact IP addresses, but each time, the firewall and https-dns-proxy reload. They don’t have to. So we’re going to fix it so they don’t reload unless the WAN IP addresses actually change, or there is a configuration change.

Issue:

vi /etc/hotplug.d/iface/20-firewall

… and press i to enter editing mode.

Paste the following code in, right above the last 2 lines of already-existing code:

# === SAME-IP RELOAD BYPASS START ===
if [ "$INTERFACE" = "wan" ] || [ "$INTERFACE" = "wan6" ]; then
	WAN4_CACHE="/tmp/last_wan4_ip"
	WAN6_CACHE="/tmp/last_wan6_ip"

	# Fetch current data for both interfaces
	CURRENT_WAN4=$(ubus call "network.interface.wan" status | jsonfilter -e '@["ipv4-address"][0].address')
	[ -z "$CURRENT_WAN4" ] && CURRENT_WAN4=$(ifstatus "wan" | jsonfilter -e '@["ipv4-address"][0].address')

	CURRENT_WAN6=$(ubus call "network.interface.wan6" status | jsonfilter -e '@["ipv6-prefix"][0].address')
	[ -z "$CURRENT_WAN6" ] && CURRENT_WAN6=$(ifstatus "wan6" | jsonfilter -e '@["ipv6-prefix"][0].address')

	# Read cache data if it exists
	OLD_WAN4=""
	OLD_WAN6=""
	[ -f "$WAN4_CACHE" ] && OLD_WAN4=$(cat "$WAN4_CACHE")
	[ -f "$WAN6_CACHE" ] && OLD_WAN6=$(cat "$WAN6_CACHE")

	# Only attempt reload-bypass if current data and cache data exist
	if [ -n "$CURRENT_WAN4" ] && [ -n "$CURRENT_WAN6" ] && [ -f "$WAN4_CACHE" ] && [ -f "$WAN6_CACHE" ]; then
		# Check if both current values match old values during a DHCP renewal
		if [ "$CURRENT_WAN4" = "$OLD_WAN4" ] && [ "$CURRENT_WAN6" = "$OLD_WAN6" ] && [ "$ACTION" = "ifupdate" ]; then
			logger -t firewall "Bypassing firewall reload: WAN IPv4 ($CURRENT_WAN4) & IPv6 ($CURRENT_WAN6) unchanged."
			exit 0
		fi
	fi

	# 4. Update cache data
	[ -n "$CURRENT_WAN4" ] && echo "$CURRENT_WAN4" > "$WAN4_CACHE"
	[ -n "$CURRENT_WAN6" ] && echo "$CURRENT_WAN6" > "$WAN6_CACHE"
fi
# === SAME-IP RELOAD BYPASS END ===

That’ll go right above this code:

logger -t firewall "Reloading firewall due to $ACTION of $INTERFACE ($DEVICE)"
fw4 -q reload

Then press Esc to exit editing mode, and :wq to save and exit.

That fixes the firewall. Now let’s fix https-dns-proxy:

Issue:

vi /etc/init.d/https-dns-proxy

… and press i to enter editing mode.

At the very bottom, paste this code in:

# Intercept standard procd reloads
service_reload() {
        hdp_bypass_check
}

# Intercept legacy subsystem reloads
reload_service() {
        hdp_bypass_check
}

# Bypass logic
hdp_bypass_check() {
        # Inspect current process invocation to look for an explicit restart command
        if grep -Fq "restart" "/proc/$$/cmdline" 2>/dev/null; then
            logger -t https-dns-proxy "Manual restart detected via CLI. Restarting..."
            stop
            sleep 2
            start
            return 0
        fi

        local CURRENT_WAN4 CURRENT_WAN6 OLD_WAN4 OLD_WAN6

        # Fetch current IPs
        CURRENT_WAN4=$(ubus call "network.interface.wan" status | jsonfilter -e '@["ipv4-address"][0].address')
        CURRENT_WAN6=$(ubus call "network.interface.wan6" status | jsonfilter -e '@["ipv6-prefix"][0].address')

        # Read cache files
        [ -f "/tmp/last_wan4_ip" ] && OLD_WAN4=$(cat /tmp/last_wan4_ip)
        [ -f "/tmp/last_wan6_ip" ] && OLD_WAN6=$(cat /tmp/last_wan6_ip)

        # If cache files exist and both IPs match, exit without restarting https-dns-proxy
        if [ -n "$CURRENT_WAN4" ] && [ "$CURRENT_WAN4" = "$OLD_WAN4" ] && [ -n "$CURRENT_WAN6" ] && [ "$CURRENT_WAN6" = "$OLD_WAN6" ]; then
                logger -t https-dns-proxy "Bypassing https-dns-proxy reload: WAN IPv4 ($CURRENT_WAN4) & IPv6 ($CURRENT_WAN6) unchanged."
                return 0
        fi

        # If either WAN4 or WAN6 IP changes, or a config file is updated, restart https-dns-proxy
        logger -t https-dns-proxy "https-dns-proxy reloading: WAN IP changed or config update."

        # Call the script's internal stop/start logic
        stop
        sleep 2
        start
}

Press Esc to exit editing mode, then :wq to save and exit.

And in /etc/rc.local (at System >> Startup >> Local Startup), enter the code below, above the ‘exit 0’ blurb:

# Seed firewall hotplug and https-dns-proxy IP address caches on boot
# ===========================================
(
ubus call "network.interface.wan" status | jsonfilter -e '@["ipv4-address"][0].address' > /tmp/last_wan4_ip 2>/dev/null
ubus call "network.interface.wan6" status | jsonfilter -e '@["ipv6-prefix"][0].address' > /tmp/last_wan6_ip 2>/dev/null
) &
# ===========================================

Manually populate the /tmp/last_wan4_ip and /tmp/last_wan6_ip files:

ubus call "network.interface.wan" status | jsonfilter -e '@["ipv4-address"][0].address' > /tmp/last_wan4_ip 2>/dev/null
ubus call "network.interface.wan6" status | jsonfilter -e '@["ipv6-prefix"][0].address' > /tmp/last_wan6_ip 2>/dev/null

Restart the relevant services…

/etc/init.d/https-dns-proxy restart
/etc/init.d/firewall restart
/etc/init.d/log restart

Now you can watch your logs (Status >> System Log or logread -f) as you test it by forcing a DHCP lease renewal of your WAN IP addresses:

kill -SIGUSR1 $(cat /var/run/udhcpc-eth0.pid)

Which should return something like this in your logs if your ISP returns to you the same IP addresses:

[Oct 2, 2026, 19:56:48] daemon.notice: netifd: wan (2937): udhcpc: sending renew to server 96.113.84.149
[Oct 2, 2026, 19:56:48] daemon.notice: netifd: wan (2937): udhcpc: lease of 73.32.15.32 obtained from 96.113.84.149, lease time 4350
[Oct 2, 2026, 19:56:48] user.notice: firewall: Bypassing firewall reload: WAN IPv4 (73.32.15.32) & IPv6 (2601:2c1:9480:a918::) unchanged.
[Oct 2, 2026, 19:56:49] user.notice: https-dns-proxy: Bypassing https-dns-proxy reload: WAN IPv4 (73.32.15.32) & IPv6 (2601:2c1:9480:a918::) unchanged.

And of course, we have to make sure the changes survive firmware updates, so add:

/etc/hotplug.d/iface/20-firewall
/etc/init.d/https-dns-proxy

… to the System >> Backup / Flash firmware >> Configuration tab.