Skip to content

deviationist/asuswrt-merlin-accessctl

Repository files navigation

asuswrt-merlin-accessctl

Allow more than 4 IPs on your ASUS router's admin access-restriction allowlist (Web UI + SSH source filter) on Asuswrt-Merlin — past the GUI's JavaScript-only 4-entry cap. Additive and lock-out-safe. Developed on the RT-BE92U.

The problem

ASUS routers have an admin access restriction feature (Administration → System → Enable access restriction): a source-IP allowlist that says "only these IPs may reach the router's Web UI and SSH." It's a great hardening step — but the GUI's add-a-row form stops you at 4 entries. If you run more than a handful of trusted machines (a couple of workstations, a phone, a jump host, a VPN endpoint…), four isn't enough, and the official answer tends to be "you shouldn't need more than four."

The finding

The 4-entry limit is enforced only by the GUI's JavaScript. The add-a-row form caps itself at 4 — but nothing underneath does:

  • the nvram list (restrict_rulelist) stores as many entries as you give it;
  • the GUI displays more than 4 when they're present;
  • the firmware's iptables backend (write_access_restriction() in rc/firewall.c, which builds the ACCESS_RESTRICTION chain) has no cap — it iterates the whole list.

Verified live on an RT-BE92U (Merlin 3006.102.x) by injecting a 5th entry into nvram: it both enforced and showed up in the GUI. And the old "nvram is too small" rationale doesn't apply — the whole list is ~120 bytes against tens of KB free.

So there's nothing to hack or patch. This tool just writes the entries the GUI won't let you type, using the mechanism the firmware already honors.

What accessctl does

A single busybox sh script (/jffs/scripts/accessctl) that manages the extra admin-allowed IPs — the ones beyond the GUI's own list — from a small config file, access-extra.conf (one <ip> <web|ssh|both> per line):

accessctl add 192.168.1.50 both    # allow a host for Web UI + SSH
accessctl add 192.168.1.51 ssh     # SSH only
accessctl del 192.168.1.50         # remove (config-managed IPs only)
accessctl list                     # show the managed extras
accessctl status                   # config vs nvram vs the live iptables chain
accessctl apply                    # re-sync nvram + firewall from the config

add/del/apply write the config's IPs into nvram (restrict_rulelist, plus http_clientlist for display parity) and run service restart_firewall, so the firmware rebuilds the ACCESS_RESTRICTION chain with your extra IPs included — GUI-visible and backend-enforced.

It cannot lock you out (by design)

This is the whole point, so it's worth being explicit:

  • Additive only. accessctl only ever touches the IPs in its own config. It never modifies or removes the GUI's own base entries.
  • del refuses any IP it doesn't manage — so it can't remove the base entry that is your escape hatch.
  • add refuses any IP that's already a GUI-managed rule (present in nvram but not in accessctl's config) — it won't silently "capture" one of your base entries.
  • It never touches the master toggle (enable_acc_restriction). Turning restriction on is the one action that can lock someone out (if their own IP isn't allowed yet), so that stays a deliberate GUI action.
  • Reboot-persistent for free: your entries live in nvram, which survives reboots; the firmware rebuilds the chain from it at boot. A firewall-start hook only kicks in for the rare case where a GUI "Apply" truncates your extra IPs back out of nvram — it detects the gap and restores them (recursion-guarded).

Golden rule: always keep at least one always-reachable admin IP in the GUI's own list as your escape hatch. accessctl never touches it.

Break-glass

If you ever do lock yourself out, from any still-allowed host (a VPN whose IP is allowed, a jump host, a LAN machine on the list):

nvram set enable_acc_restriction=0; nvram commit; service restart_firewall

That disables the whole restriction (any IP can reach admin again). enable_acc_restriction is the flag the firewall backend actually reads.

Requirements

  • Asuswrt-Merlin — the tool uses Merlin's user-script hooks (/jffs/scripts/, firewall-start), which stock ASUSWRT doesn't offer. The access-restriction feature itself is stock ASUS; only the automation needs Merlin.
  • JFFS custom scripts enabled: Administration → System → Enable JFFS custom scripts and configs = Yes.
  • SSH access to the router (Administration → System → Enable SSH = LAN only).
  • "Enable access restriction" = Yes, with your own admin IP already in the GUI list, before you add extras — so you can't lock yourself out.

Install

Guided setup (easiest — run on your computer, not the router)

curl -fsSL https://raw.githubusercontent.com/deviationist/asuswrt-merlin-accessctl/main/setup.sh | sh

It asks for your router's address and SSH username (ssh prompts for the password if you haven't set up keys), checks the router is ready, detects whether accessctl is already installed, and offers install / reinstall / uninstall / show-status. Safe to run any number of times.

Direct install (run on the router)

Over an SSH session on the router itself:

curl -fsSL https://raw.githubusercontent.com/deviationist/asuswrt-merlin-accessctl/main/install.sh | sh

The installer verifies JFFS scripts are enabled, fetches accessctl into /jffs/scripts/, and appends a one-line hook to firewall-start (creating it if absent) — idempotent, safe to re-run.

Manual install (full control)

# from a clone of this repo, copy the tool to the router
scp scripts/accessctl <user>@<router>:/jffs/scripts/
ssh <user>@<router> 'chmod 755 /jffs/scripts/accessctl'

# add the firewall-start hook (restores your IPs if a GUI "Apply" truncates nvram)
ssh <user>@<router> '
  FS=/jffs/scripts/firewall-start
  [ -f "$FS" ] || printf "#!/bin/sh\n" > "$FS"
  chmod 755 "$FS"
  grep -q "accessctl firewall" "$FS" || echo "[ -x /jffs/scripts/accessctl ] && /jffs/scripts/accessctl firewall" >> "$FS"
'

Then, on the router: make sure your own admin IP is in the GUI list and Enable access restriction is on, and start adding extras with accessctl add.

Uninstall

# on the router:
/jffs/scripts/accessctl uninstall     # strips our IPs from nvram (keeps GUI base)
sh install.sh uninstall               # ...and removes the tool + hook + config

# or from your computer:
curl -fsSL https://raw.githubusercontent.com/deviationist/asuswrt-merlin-accessctl/main/uninstall.sh | sh

Uninstalling removes our extra IPs from nvram (your GUI base entries stay), deletes the firewall-start hook line, the tool, and access-extra.conf. Nothing else on your router is touched.

What lands on your router

Path What it is
/jffs/scripts/accessctl the tool (one busybox sh script)
/jffs/scripts/access-extra.conf your list of extra IPs (<ip> <web|ssh|both>)
one line in /jffs/scripts/firewall-start the truncation-recovery hook
nvram restrict_rulelist / http_clientlist your extras, merged with the GUI's own entries

Tip: keep access-extra.conf in your own version control off the router — JFFS survives firmware updates but is wiped by a factory reset. After a reset, copy accessctl + access-extra.conf back and run accessctl apply.

How enforcement actually works

restrict_rulelist entries are <enable>ip>type, where type is a bitmask: 1 = Web UI, 2 = SSH, 3 = both (7 would add Telnet). The firmware's write_access_restriction() reads this list, gated on enable_acc_restriction=1, and builds the ACCESS_RESTRICTION iptables chain — no entry limit in the C code. accessctl status shows all three layers side by side so you can see config → nvram → live chain agree.

Honest limitations

  • Firmware-specific. The nvram var names and the ACCESS_RESTRICTION chain are how current AsusWRT/Merlin builds implement this; verified on the RT-BE92U. Other models/firmware very likely match (it's long-standing ASUS plumbing), but if accessctl status shows your extras in nvram yet not in the chain, your build differs — please open an issue with model + firmware.
  • http_clientlist is legacy. The current backend enforces from restrict_rulelist; we still write http_clientlist for GUI/older-firmware display parity. Don't rely on it for enforcement.
  • Not affiliated with ASUS, Broadcom, or the Asuswrt-Merlin project. This just uses documented nvram + the firmware's own access-restriction backend.

Sibling project

If you're on an RT-BE92U (or another Broadcom ASUS unit) and a Wi-Fi client loses specific LAN hosts after a band roam, see asuswrt-merlin-flowcache-doctor.

About

Manage more than 4 IPs on the router admin access-restriction allowlist (Web UI/SSH source filter) on Asuswrt-Merlin — past the GUI's JavaScript-only 4-entry cap. Additive and lock-out-safe. Developed on the RT-BE92U.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages