Django web UI for discovering AMP instance ports and managing firewall rules through pluggable providers.
Clone the repository:
git clone <repo-url>
cd arksa-ports-webUpdate an existing checkout:
git pull --ff-only- This service is intended to run on the same host machine where AMP is running.
- Local providers (
iptables,ufw) execute commands on the local host, so running remotely will not manage the AMP host firewall unless you use a remote provider (for example OpenWrt RPC).
- Reads instance + port data from AMP.
- Keeps a local snapshot in sync (adds new, updates existing, removes deleted).
- Shows per-port firewall status.
- Supports single and bulk actions (enable/disable).
- Supports OpenWrt orphan
AMP:rule cleanup (disable/delete, including bulk delete).
git clone <repo-url>
cd arksa-ports-web
./install.shinstall.sh creates the virtual environment in .venv.
For manual Django commands, activate it first:
source .venv/bin/activateLocal firewall providers call commands through sudo -n, so the runtime user must have passwordless sudo for those binaries.
- Find the runtime user (the account running
run-ports-web.sh/ Django). - Create a sudoers file using
visudo:
sudo visudo -f /etc/sudoers.d/amp-firewall-web- Add rules (replace
AMPWEBUSERwith your runtime user):
AMPWEBUSER ALL=(root) NOPASSWD: /usr/sbin/iptables
AMPWEBUSER ALL=(root) NOPASSWD: /usr/sbin/ufw
- Ensure file permissions are correct:
sudo chmod 440 /etc/sudoers.d/amp-firewall-websource .venv/bin/activate
./run-ports-web.shOpen: http://127.0.0.1:8001/
You can also open it from your local network using the host LAN IP, for example:
http://192.168.x.x:8001/
Do not expose this service directly to the public internet.
This repository includes a systemd unit template that runs the app as the current project user and restarts it automatically if it exits.
Files:
run-ports-web-service.sharksa-ports-web.serviceinstall-systemd-service.sh
Install and start it:
sudo ./install-systemd-service.shCommon service commands:
sudo systemctl start arksa-ports-web.service
sudo systemctl status arksa-ports-web.service
sudo systemctl restart arksa-ports-web.service
sudo systemctl stop arksa-ports-web.service
sudo systemctl enable arksa-ports-web.service
sudo systemctl disable arksa-ports-web.service
journalctl -u arksa-ports-web.service -n 100 --no-pager
journalctl -u arksa-ports-web.service -fWhen to restart the service:
sudo systemctl restart arksa-ports-web.serviceRestart it after:
- changing Python code
- changing templates
- changing
.env - reinstalling dependencies
When you pull new code:
git pull --ff-only
source .venv/bin/activate
python manage.py migrate
sudo systemctl restart arksa-ports-web.serviceFull service lifecycle example:
sudo ./install-systemd-service.sh
sudo systemctl status arksa-ports-web.service
sudo systemctl restart arksa-ports-web.service
sudo systemctl stop arksa-ports-web.service
sudo systemctl start arksa-ports-web.service
sudo systemctl disable arksa-ports-web.serviceNotes:
- The install script resolves the runtime user automatically from
sudoor the project directory owner - It uses
<project-dir>/.envas an optional environment file - It listens on
0.0.0.0:8001by default - It uses
runserver --noreloadsosystemdsees a single stable process
- AMP and firewall provider configuration are managed from the UI:
http://127.0.0.1:8001/providers
- AMP connection (
url,username,password) is configured in UI. - AMP password is stored encrypted in DB and decrypted only when AMP API calls are made.
- Localhost providers (
ufw,iptables) are auto-detected. - OpenWrt provider is configured using UI fields (no JSON config editing).
- OpenWrt password is stored encrypted in DB and decrypted only when provider calls are executed.
- All application routes now require Django authentication. Create a superuser before first use:
source .venv/bin/activate
python manage.py createsuperuser- Safer defaults are now enabled:
DJANGO_DEBUG=0by defaultDJANGO_ALLOWED_HOSTS=127.0.0.1,localhost,[::1]by default
- AMP and OpenWrt management URLs are restricted to
http://orhttps://, with no embedded credentials, no query string, and only private/loopback/link-local destinations. - You can further pin allowed management hosts with:
AMP_ALLOWED_HOSTS=host1,host2OPENWRT_ALLOWED_HOSTS=host1,host2
- Local firewall commands use an execution timeout. Override if needed with:
FIREWALL_COMMAND_TIMEOUT=10
- Firewall actions are validated against the discovered AMP snapshot, so tampering with hidden form fields cannot open arbitrary ports.
These values are read from environment variables. The simplest way to use them is to create a .env file in the project root.
Example:
DJANGO_DEBUG=0
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost,[::1]
AMP_ALLOWED_HOSTS=127.0.0.1
OPENWRT_ALLOWED_HOSTS=192.168.1.1
FIREWALL_COMMAND_TIMEOUT=10Use this when you only open the web UI on the same machine where this app is running.
DJANGO_DEBUG=0
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost,[::1]
AMP_ALLOWED_HOSTS=127.0.0.1,localhost
OPENWRT_ALLOWED_HOSTS=
FIREWALL_COMMAND_TIMEOUT=10- Open the UI with
http://127.0.0.1:8001/ - If AMP is local, use an AMP URL like
http://127.0.0.1:8080
Use this when the web UI is on one machine and you open it from another machine on your home/server network.
DJANGO_DEBUG=0
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost,192.168.1.50
AMP_ALLOWED_HOSTS=192.168.1.10
OPENWRT_ALLOWED_HOSTS=
FIREWALL_COMMAND_TIMEOUT=10- Replace
192.168.1.50with the IP of the machine running this web app - Replace
192.168.1.10with the AMP server IP - Open the UI with
http://192.168.1.50:8001/ - In the provider page, AMP URL can be
http://192.168.1.10:8080
Use this when AMP is on your LAN and firewall management happens through an OpenWrt router.
DJANGO_DEBUG=0
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost,192.168.1.50
AMP_ALLOWED_HOSTS=192.168.1.10
OPENWRT_ALLOWED_HOSTS=192.168.1.1
FIREWALL_COMMAND_TIMEOUT=10- Replace
192.168.1.50with the IP of the machine running this web app - Replace
192.168.1.10with the AMP server IP - Replace
192.168.1.1with the OpenWrt router IP - AMP URL can be
http://192.168.1.10:8080 - OpenWrt RPC URL can be
http://192.168.1.1/ubus
-
DJANGO_DEBUG=0Keeps Django debug pages disabled. Leave this as0unless you are actively debugging locally. -
DJANGO_ALLOWED_HOSTS=host1,host2Controls which hostnames or IPs are allowed to reach this web app. If you browse tohttp://192.168.1.50:8001/, then192.168.1.50must be listed here. -
AMP_ALLOWED_HOSTS=host1,host2Restricts which AMP hosts this app is allowed to connect to. If AMP runs athttp://192.168.1.10:8080, then192.168.1.10should be listed here. -
OPENWRT_ALLOWED_HOSTS=host1,host2Restricts which OpenWrt hosts this app is allowed to connect to. If OpenWrt RPC ishttp://192.168.1.1/ubus, then192.168.1.1should be listed here. -
FIREWALL_COMMAND_TIMEOUT=10Maximum seconds a localiptablesorufwcommand is allowed to run before it is aborted.
Allowed:
http://127.0.0.1:8080http://192.168.1.10:8080http://192.168.1.1/ubus
Rejected:
https://user:pass@192.168.1.1/ubushttp://example.com/ubushttp://1.2.3.4/ubushttp://192.168.1.1/ubus?test=1
Rules enforced by URL validation:
- Only
http://andhttps://are allowed - Username/password inside the URL are not allowed
- Query strings and fragments are not allowed
- Targets must resolve to private, loopback, or link-local IP addresses
Hidden Field Protection
The UI sends port actions using normal HTML form fields, but the server no longer trusts those values directly.
When a user clicks enable/disable:
- The requested instance/port/protocol must exist in the current discovered AMP snapshot
- If it does not exist, the firewall action is rejected
- This prevents someone from editing browser form data and opening arbitrary ports manually
Open: matching enabled allow/forward rule exists.Disabled: matching managed rule exists but is disabled.Closed: no matching usable rule.Unknown: provider cannot determine state.
- Implement a new class using
FirewallProvidercontract inports/firewall/base.py. - Add it to
FIREWALL_PROVIDERSinportadmin/settings.py.