Claude 67806d0255 Wire services end-to-end: Caddy reload, NAT reflection, port forward
Fully wired service proxy deployment:

Backend:
- /api/services/status: full checklist (OPNsense API, SSH, NAT
  reflection, port forward 443, Caddyfile.services, service count)
- /api/services/enable-nat-reflection: enables NAT reflection on
  OPNsense via SSH config.xml edit + filter reload
- /api/services/create-port-forward: creates WAN TCP 443 → Caddy
  port forward via OPNsense NAT API, tracks rule UUID
- /api/services/deploy: writes Caddyfile.services, reloads Caddy
  (tries docker compose exec, then restart, then systemctl), checks
  NAT reflection status, verifies port forward exists

Infrastructure:
- docker-compose.yml: mount Caddyfile.services into Caddy container,
  switch-manager volume writable (for writing Caddyfile.services)
- Caddyfile.template: auto-imports /etc/caddy/Caddyfile.services

Frontend:
- Setup Checklist panel with green/red dots for each prerequisite
- Enable NAT Reflection button (one-click)
- Create Port Forward button (one-click)
- Deploy button writes Caddyfile, reloads Caddy, verifies everything
- Caddyfile preview in deploy results

https://claude.ai/code/session_01Do9bsN39MTuy2GVv7yzSrE
2026-03-28 01:36:28 +00:00
2026-03-23 08:52:01 -04:00
2026-03-23 08:52:01 -04:00
2026-03-23 08:52:01 -04:00
2026-03-23 08:52:01 -04:00

Avaya / Extreme ERS Switch Manager

A browser-based management interface for Avaya / Extreme Networks ERS switches. You click buttons. The software figures out the CLI. You never type a switch command.

Compatible with: ERS 5928, ERS 5948, ERS 5952, ERS 5952-PWR+, ERS 59100GTS-PWR+


Requirements

Management computer OS: Linux (Ubuntu / Debian recommended — Raspberry Pi OS works perfectly)

The setup script uses apt, systemd, picocom, and Docker. It will not run on Mac or Windows. The management computer does not need a monitor — a headless Raspberry Pi or thin client is ideal. Once running, the web UI is accessible from any browser on any device on your network.

The switch UI itself (the browser interface) works from any OS — phone, tablet, Mac, Windows, Linux.

Switch OS: BOSS (Baystack Operating System Software) v7.9.6

BOSS is the firmware that runs on Avaya / Extreme ERS switches. This project is written and tested against BOSS v7.9.6 on the ERS 59100GTS-PWR+. It is not Cisco IOS or any other vendor's CLI — commands are different. BOSS firmware is pre-installed on the switch and does not need to be downloaded or installed.


Physical Setup — First Time Out of the Box

Everything here happens before you run any software. You need a console cable and a laptop.


Step 1 — Find the Service Port

The console (service) port is a physical RJ-45 serial port on the switch. It is not a regular ethernet port.

ERS 59100GTS-PWR+: The console port is on the front panel, left side. It is labelled "Console" and looks like a standard ethernet jack but is wired as RS-232 serial. It is located next to the USB port and the out-of-band management port.

ERS 5952 / 5952-PWR+: The console port is on the front panel, far left, labelled "Console".


Step 2 — Get a Console Cable

Search "RJ45 to USB console cable Cisco compatible" — around $8. This is the same cable used for Cisco, Juniper, and most enterprise switches. It has an RJ-45 plug on one end and USB-A on the other.

Do not use a standard ethernet cable — it will not work.


Step 3 — Connect and Open a Terminal

Important: Plug the console cable in — both the RJ-45 end into the switch and the USB end into your laptop — before powering on the switch. If you plug in after power-on, screen and picocom may not detect the device correctly.

Settings: 9600 baud · 8 data bits · No parity · 1 stop bit · No flow control

Open a terminal session:

OS Command
Linux sudo picocom -b 9600 /dev/ttyUSB0
Mac screen /dev/tty.usbserial-* 9600
Windows PuTTY → Serial → COM port → 9600 baud

To find your COM/device name if unsure:

  • Linux: ls /dev/ttyUSB* before and after plugging in
  • Mac: ls /dev/tty.usb* before and after plugging in
  • Windows: Device Manager → Ports (COM & LPT)

Console vs SSH: The console cable gives you direct CLI access to type commands on the switch. It is only needed for initial setup. Once SSH is configured, the management script connects over Ethernet (port 22) and you never need the console cable again — unless you lock yourself out.


Step 4 — Power On and Read the Boot Screen

Power on the switch. You will see a banner like this:

Enter Ctrl-Y to begin.

*************************************************************
*** Ethernet Routing Switch 59100GTS-PWR+                ***
*** Copyright (C) 1996-2024 Extreme Networks.            ***
*** HW:22    FW:7.5.0.4    SW:v7.9.6.015                ***
*************************************************************

Press Ctrl-Y. The switch is waiting for this keypress to continue booting — it will not proceed without it. After pressing Ctrl-Y the switch runs POST and boots normally in about 6090 seconds.

When it is ready you will see:

Login:

Step 5 — Log In with Default Credentials

Login:    admin
Password: (press Enter — no password by default)

If that fails, try admin / admin. If the switch was previously configured you may need to do a factory reset (see Troubleshooting below).

You will land at the 5952# or 59100GTS-PWR+# prompt in privileged exec mode.


Step 6 — Bootstrap VLAN 99 via Console

This is the only time you need the console cable for normal operation. Enter these commands one at a time, waiting for the prompt before each:

enable
configure terminal
vlan create 99 name "Management" type port
interface vlan 99
ip address 192.168.99.1 255.255.255.0
no shutdown
exit
vlan members add 99 1
vlan pvid 1 99
ip ssh
username admin password YourPassword
end
save config

Replace 1 with the port number your management computer will plug into. Replace YourPassword with a strong password (832 characters; allowed special characters: ! @ # $ % ^ & * - _ = + [ ] ; : , . / — no spaces, no quotes).

Port numbering: On both the ERS 5952 and ERS 59100, use bare port numbers (1, 2, 48…). There is no slot prefix.

What about the switch's existing IP? Out of the box the switch has 192.168.1.1 on VLAN 1. If your router is also 192.168.1.1, they will conflict — two devices with the same IP on the same network causes ARP fights and makes both unreliable.

This setup deliberately avoids that by putting management traffic on a separate VLAN (99) with its own subnet (192.168.99.x). Your management computer gets a static IP on that subnet and talks to the switch there. The switch's original VLAN 1 address is irrelevant once VLAN 99 is up.

If you ever need to change the switch's VLAN 1 IP (e.g. to remove the conflict before VLAN 99 is configured):

config terminal
interface vlan 1
ip address 192.168.1.2 255.255.255.0
exit
ip default-gateway 192.168.1.1
exit
save config

After the last command the switch confirms with CP1 [07/04/15 12:00:00.000:INFO]: Operation Success or similar.


Step 7 — Give the Management Computer a Static IP

On the machine that will run the switch manager software:

# Find your interface name first
ip link show

# Set a static IP on the management network interface (adjust eth0 to your interface)
sudo ip addr add 192.168.99.50/24 dev eth0
sudo ip link set eth0 up

Verify: ping 192.168.99.1 — you should get replies from the switch.


Step 8 — Run the Setup Script

python Avaya_5952_setup.py

The script handles everything from here. When it pauses and asks you to load the SSH public key onto the switch, it will show you exactly what to paste into the console.


Installation

Copy Avaya_5952_setup.py to your always-on management computer (Raspberry Pi, HP T620 thin client, old computer or laptop) and run:

python Avaya_5952_setup.py

That is the entire installation process. The script handles everything automatically. The only step requiring human intervention is loading the SSH public key onto the switch via console cable — the script pauses, shows you exactly what to type, and waits for you to confirm before continuing.


What the Setup Script Does

The script runs 21 steps automatically:

  1. Writes all project files (backend, frontend source, this README)
  2. Installs system packages (picocom, qrencode, wireguard-tools)
  3. Adds your user to the dialout group for console cable access
  4. Installs Python dependencies
  5. Creates the config directory /etc/switch-manager/
  6. Sets a static IP on your management network interface
  7. Asks whether to deploy with Docker (recommended) or native Python
  8. Guides you through console cable setup and software links
  9. Generates an ed25519 SSH keypair
  10. Shows you exactly what to paste on the switch console
  11. Tests the SSH connection and retries if it fails
  12. Pins the switch host key (MITM protection)
  13. Generates your TOTP authenticator secret with QR code
  14. Verifies your authenticator app is working before continuing
  15. Patches the backend config with your switch IP and credentials
  16. Builds the React frontend (requires Node.js)
  17. Installs and enables a systemd service (or Docker container)
  18. Starts the service
  19. Optionally sets up Docker with Caddy HTTPS
  20. Optionally configures WireGuard VPN for remote access
  21. Optionally installs Control D DNS filtering via ctrld

Re-running is safe — completed steps are skipped.


Deployment Options

The script explains both options before asking:

Docker + Caddy (recommended default) Runs the switch manager in a container with all dependencies baked in. Caddy provides automatic HTTPS at a hostname you choose (default: switch.mgmt.lan). Caddy generates its own internal CA — the setup script installs it into your system trust store automatically so browsers show a clean padlock. Updates with one command: docker compose pull && docker compose up -d.

Native Python (bare metal) Runs directly as a Python process managed by systemd. Simpler, lower memory, no Docker required. Access via http://IP:8765 directly. Right choice for very low memory machines or users who prefer managing services directly.


Accessing the Interface

http://[management computer IP]:8765

Or with Docker + Caddy:

https://switch.mgmt.lan

You must be on VLAN 99 (management VLAN) or connected via WireGuard VPN to reach this address. This is intentional — the switch enforces isolation at the network layer.

Getting onto VLAN 99 from your laptop

Linux:

sudo ip link add link eth0 name eth0.99 type vlan id 99
sudo ip addr add 192.168.99.50/24 dev eth0.99
sudo ip link set eth0.99 up

Mac: System Settings → Network → Add VLAN interface → VLAN ID 99

Dedicated port: Ask the switch to put one port on VLAN 99 as an access port. Plug in when managing.

VPN: Connect via WireGuard (configured during setup or via the VPN tab).


The Interface — Eight Tabs

Port Map

Visual 48+4 port chassis, colour-coded by VLAN. Each port shows its VLAN assignment, mode (access/trunk/disabled), and a green dot when PoE is active. Click any port to configure it in the right panel.

Port configuration panel:

  • Description (e.g. "AP-Corridor-1", "Camera-NE")
  • Mode: Access, Trunk, or Disabled
  • VLAN assignment (access) or tagged/native VLANs (trunk)
  • PoE on/off and wattage limit (copper ports, 1W30W)

Live status pulls from the switch every 15 seconds while the tab is active, 60 seconds when backgrounded, and pauses when nobody has the page open.

VLANs

Create, rename, and delete VLANs. Shows port count and subnet per VLAN. VLAN 1 cannot be deleted.

ACL Builder

Build Access Control Lists visually. Each rule specifies action (permit/deny), protocol (ip/tcp/udp/icmp), source, destination, and optional port. The ACL is assigned to a VLAN interface with a direction. The tool generates all CLI syntax — you never write it yourself.

Templates: Click "Use Template" to pre-fill rules for common patterns: Staff (full internet, no management), IoT (internet only, no RFC1918), Guest (internet + ctrld DNS enforcement), Camera (NVR only). All rules are editable after applying the template.

Review & Push

Every change across all tabs is translated into the exact CLI commands the switch understands. This tab shows those commands before anything is sent.

You never write CLI commands. The tool generates them. The review step exists so you can inspect what will be sent.

Push mode choice:

  • Batch — all commands sent in sequence, results shown when complete
  • Step by step — one command at a time, confirm each before the next is sent

Each command is displayed with a plain-English explanation of what it does and what it affects. You can read exactly what is about to happen.

Device Access

Manages which devices can reach the management interface from their normal VLAN without needing VPN. The switch enforces access via an ACL pinhole. TOTP still gates any changes.

MAC address randomization warning: Modern phones and laptops randomize MAC addresses per network. This breaks DHCP reservations. The tab shows per-platform instructions to disable it (iOS, Android, macOS, Windows) before adding a device.

Live DHCP leases pulled from the switch appear as unregistered devices — click Register to add them.

Per device:

  • Name, MAC, IP, VLAN
  • Reserve static IP (DHCP binding pushed to switch)
  • Grant/revoke management access (ACL pinhole pushed to switch)

DHCP

Unified view of all DHCP reservations across switch and OPNsense (if configured).

DHCP server recommendation:

  • Use switch DHCP for VLAN 99 (management) — devices get IPs before OPNsense is reachable
  • Use OPNsense for all other VLANs — integrates with DNS, firewall rules, lease history
  • Never run both for the same VLAN

OPNsense integration (optional): Auto-detects OPNsense at your gateway IP. If found, prompts for API key. Once connected, shows reservations from both switch and OPNsense in one table, colour-coded by source.

Conflict detection: If the same MAC has reservations in both places, a badge appears — red for IP conflicts (same MAC, different IP), yellow for duplicates (same MAC, same IP). Each conflict has a Resolve button with four options: Switch wins, OPNsense wins, Remove from switch, Remove from OPNsense.

DNS Filtering

Configures Control D DNS filtering per VLAN via the ctrld daemon.

How it works: ctrld runs as a local DNS proxy. Devices send normal DNS queries to it. ctrld identifies the source VLAN subnet and routes each query to the correct Control D profile via DoH3. Each VLAN gets different filtering rules. Your ISP sees encrypted HTTPS traffic, not DNS queries.

Three deployment options presented with full explanations:

Option A — ctrld on the management computer (fully automated) Installs ctrld alongside the switch manager. One command downloads and installs it, writes the per-VLAN config, starts it as a system service. The switch DHCP points each VLAN to this machine's IP for DNS.

Option B — ctrld on OPNsense (semi-automated) Generates a single SSH command to paste into OPNsense shell. ctrld installs as a service on OPNsense. OPNsense's IP becomes the DNS server for the network.

Option C — manual / existing setup Generates the ctrld.toml config and install command. You install wherever you choose.

Per-VLAN Resolver IDs: Each VLAN gets its own Control D profile. Enter the Resolver ID from the Control D dashboard (controld.com → Add Device → Router → Resolver ID). VLANs without a Resolver ID use the first configured profile as fallback.

DNS Enforcement: After installing ctrld, use the "Enforce DNS on Switch" button to generate ACLs that block devices from bypassing ctrld by using 8.8.8.8 directly. See DNS Enforcement ACLs below.

Local Hostnames: Optionally run a dnsmasq container so .lan names resolve for all devices. See Local Hostname Resolution below.

References:

VPN

Manages WireGuard VPN for remote access to the management interface from outside the management VLAN.

Add clients: Enter a name (laptop, phone, tablet) and the tool generates a keypair, adds the peer to the server config, reloads WireGuard live, and displays a QR code to scan with the WireGuard app. Also saves a .conf file for desktop import.

Revoke clients: Disconnects the peer immediately and removes it from the server config.

Connected peers: Shows last handshake time and transfer stats for each peer.

SSH tunnel alternative: For power users — one command gives secure access without WireGuard installed:

ssh -L 8765:localhost:8765 user@management-computer-ip

Making Changes — Step by Step

  1. Configure across any tabs — nothing happens on the switch yet
  2. Go to Review & Push — read the generated commands with explanations
  3. Check for dangers — automatic pre-flight runs before authentication
  4. Authenticate — enter 6-digit TOTP code to unlock a push session
  5. Choose push mode — batch (faster) or step-by-step (full control)
  6. Push — commands go one at a time, checked after each
  7. Review results — each command shows success or failure with the switch's error output
  8. Auto-lock — session closes when push completes. New changes need a new TOTP code

Authentication and Sessions

Read-only — no authentication required. Anyone on VLAN 99 can view the dashboard.

Push mode — requires TOTP. One code unlocks exactly one push session. The session closes automatically when the push completes or you cancel. The next set of changes requires a new TOTP code.

Why TOTP and not a password: VLAN 99 isolation is the primary barrier. TOTP adds a second factor confirming it is you making a change. A code is useless after 30 seconds and requires physical access to your authenticator app.


How Commands Reach the Switch

Exact sequence on every push:

  1. Browser sends the command list to the management computer backend
  2. Backend runs a danger check against known lethal patterns
  3. Backend validates every command against an allowlist
  4. Backend opens a fresh SSH connection using the ed25519 key stored on the management computer
  5. Commands execute one at a time via interactive shell
  6. After each command the switch's response is checked for error patterns
  7. On error: push stops immediately, no further commands sent, config not saved
  8. On full success: end then copy running-config nvram:config.cfg — config saved to NVRAM

Blocked Commands

Hard-blocked — refused entirely, must run at the switch console:

Pattern Reason
no vlan 99 Deletes management VLAN
vlan members remove ... 99 Removes VLAN 99 from a port — kills management trunk
no vlan tagging ... 99 Removes VLAN 99 tagging — kills management trunk
no ip ssh Disables SSH — permanent lockout
no ip address Removes IP — management computer loses connectivity
interface vlan 99 Modifies management VLAN interface
boot config flags factory Factory reset

Warning-level — shown for review, push proceeds with confirmation:

Pattern Reason
shutdown Shuts down an interface — confirm not your uplink
default interface Resets interface to defaults
no vlan [id] Deletes a VLAN — confirm no active ports depend on it
spanning-tree ... disable Disables spanning tree — loop risk

SSH Key Security

The ed25519 private key lives at /etc/switch-manager/ers5952_key on the management computer. It never leaves that machine. Your laptop, phone, or tablet never touches it.

The switch host key is pinned after the first connection. If the switch's host key ever changes the backend refuses to connect and reports the mismatch — MITM protection even on the management VLAN.


Console Cable

See Physical Setup — First Time Out of the Box above for the complete walkthrough including where the console port is, what cable to buy, and what to do at the boot screen.

The short version: one-time only, RJ-45 to USB console cable (~$8), 9600 baud, no parity.

Switch password rules: 832 characters. Special characters allowed: ! @ # $ % ^ & * - _ = + [ ] ; : , . /. No spaces. No quotes.


Live Polling

The backend polls the switch using a connection pool:

  • Pool lifetime: 25 seconds (shorter than switch idle timeout)
  • Tab active/visible: polls every 15 seconds
  • Tab backgrounded: polls every 60 seconds
  • No visitors for 5 minutes: polling pauses completely
  • New visitor opens page: immediate poll, resumes normal interval

The switch is never being polled when nobody is looking at the dashboard.


Files Created

File Location Purpose
switch_backend.py Project folder Python API server (34 endpoints)
ers5952-manager.jsx Project folder React app source (8 tabs)
README.md Project folder This file
Dockerfile Project folder Docker image definition
docker-compose.yml Project folder Caddy + switch manager services
Caddyfile Project folder HTTPS reverse proxy config
ctrld.toml Project folder Control D per-VLAN DNS config (if configured)
frontend/dist/ Project folder Built React app
ers5952_key /etc/switch-manager/ SSH private key (chmod 600)
ers5952_key.pub /etc/switch-manager/ SSH public key
known_hosts /etc/switch-manager/ Pinned switch host key
totp_secret /etc/switch-manager/ TOTP seed (chmod 600) — back this up
devices.json /etc/switch-manager/ Registered device list
opnsense.json /etc/switch-manager/ OPNsense API credentials (chmod 600)
ctrld.json /etc/switch-manager/ Control D config (chmod 600)
wg_server_private /etc/switch-manager/ WireGuard server private key (chmod 600)
wg_server_public /etc/switch-manager/ WireGuard server public key
clients/ /etc/switch-manager/ WireGuard client .conf files
switch-manager.service /etc/systemd/system/ Systemd service (native mode)
local-hostnames.json /etc/switch-manager/ User-defined hostname→IP mappings (optional)
dnsmasq.conf /etc/switch-manager/ Generated dnsmasq config (optional)

Back up /etc/switch-manager/totp_secret — if the management computer fails and you have not backed this up you will need to regenerate the TOTP secret and re-scan it into your authenticator app.


Firmware Upgrade

The switch runs two software components that must both be upgraded:

  • Diagnostic image (diag) — upgraded first
  • Agent image (BOSS firmware) — upgraded second

Important rules:

  • Upgrade one version at a time — cannot skip releases
  • Always upgrade the diagnostic image before the agent image
  • USB files must not be marked read-only or the transfer fails
  • Firmware downloads require an active support contract at the Extreme Networks portal
  • Check the ERS Announcements page to find the latest version

Your switch currently runs: BOSS v7.9.6.015 / Diagnostics 7.5.0.4


Method 1 — USB (no network needed, easiest)

  1. Download the diagnostic .bin and agent .img files from the Extreme portal
  2. Copy both files to a USB stick — ensure they are not read-only
  3. Insert the USB stick into the front panel USB port on the switch
  4. Via console or SSH (in enable mode):
download usb diag ers5900diag_7x_x_x_x.bin

Wait for it to complete and confirm, then:

download usb image ers5900_7x_x_x_x.img

The switch will reboot automatically after the agent upgrade.

Alternatively, from the boot menu (option 4 — "Download Agent/Diag") you can trigger a USB download without logging in first.


Method 2 — SFTP over SSH (requires network)

From enable mode on the switch, with an SFTP server running on your management computer:

copy sftp address 192.168.99.50 filename ers5900diag_7x_x_x_x.bin

Wait for completion, then:

copy sftp address 192.168.99.50 filename ers5900_7x_x_x_x.img

The switch reboots after the agent upgrade.


Method 3 — TFTP from a laptop (no dedicated server needed)

Your laptop can act as a temporary TFTP server. The switch has a default IP of 192.168.1.1/24 on VLAN 1 out of the box (or after a factory reset) — so on a fresh switch you can skip console IP configuration entirely. Just plug in Ethernet and go.

Plug both the console cable and an Ethernet cable from the laptop into the switch at the same time.

On the laptop:

sudo apt install tftpd-hpa
sudo cp ers5900diag_*.bin ers5900_*.img /srv/tftp/
sudo ip addr add 192.168.1.50/24 dev eth0    # must be on same /24 as switch default (192.168.1.x)
sudo systemctl start tftpd-hpa

Then on the switch via console (or via SSH to 192.168.1.1 if SSH is already enabled):

enable
copy tftp address 192.168.1.50 filename ers5900diag_7x_x_x_x.bin

Then:

copy tftp address 192.168.1.50 filename ers5900_7x_x_x_x.img

Stop the server when done:

sudo systemctl stop tftpd-hpa

No console needed on a factory switch: The switch answers at 192.168.1.1 immediately after boot. As long as your laptop is on 192.168.1.x/24, the TFTP transfer works without touching the console at all — useful if you only have an Ethernet cable and no console cable handy.


Method 4 — XMODEM over console cable (last resort, no network required)

If the USB port is broken and you have no Ethernet available at all, boot menu option 4 ("Download Agent/Diag") supports XMODEM file transfer directly over the serial console cable. No network required.

Warning: At 9600 baud, a 10 MB firmware file takes approximately 3 hours. Only use this if nothing else is possible.

In screen, after selecting option 4 from the boot menu, send the file with:

Ctrl-A  then  :exec !! sx -b /path/to/ers5900_7x_x_x_x.img

(sx is part of the lrzsz package: sudo apt install lrzsz)


Troubleshooting

Connection banner stuck on "Connecting..." Backend not running or device not on VLAN 99. Check: sudo systemctl status switch-manager or docker compose ps

"Switch unreachable" in status pill Backend running but cannot reach switch. Check: ping 192.168.99.1 from the management computer.

TOTP code rejected Ensure time is synchronised on both the management computer and your phone. Backend allows one 30-second window of clock drift. Sync: sudo timedatectl set-ntp true

Command failed — switch error shown Read the error text — the switch says exactly what was wrong. Fix the configuration and push again. Already-succeeded commands do not need to be resent.

Host key rejection after switch reset Re-pin: ssh-keyscan -H 192.168.99.1 > /etc/switch-manager/known_hosts

Factory reset — wiping a previously configured switch

When to wipe: if the switch has unknown previous configuration, unknown passwords, or you want a guaranteed clean slate. If the switch already responds to admin with no password and has no unexpected VLANs or ACLs, a wipe is not required — you can configure over the existing state.

Method 1 — Boot menu (easiest, works even if you don't know the password)

The console cable must be plugged in before power-on. During boot a diagnostic menu appears briefly:

DIAGNOSTIC BREAK MENU
59100 GTS-PWR+  Diagnostics 7.5.0.4
 1 - Launch Primary   Agent-1   Vers: 7.9.6.015
 2 - Launch Secondary Agent-2   Vers: 7.6.2.019
 3 - Toggle Primary   Agent Selection
 4 - Download         Agent/ Diag
 5 - Reinitialize     Agent Configuration Files
 6 - Display  Error   Log
 7 - Display  System  Information
 8 - Continue Boot    Sequence
 9 - Reset
 A - Power-Cycle
 B - Toggle Do-POST   Selection [ ENABLED ]
 C - Run POST tests
Select:
Booting Agent in 60 seconds...

Press 5 — "Reinitialize Agent Configuration Files". The switch wipes its config and reboots into factory defaults. You have 60 seconds before it boots automatically.

Other useful options: 1/2 switch between primary (v7.9.6) and secondary (v7.6.2) firmware. 6 shows the error log. 7 shows system info. 8 continues normal boot if you entered the menu by accident. 9 resets (reboots). A power-cycles. B toggles POST (hardware self-test) on/off. C runs POST tests manually.

Method 2 — CLI (requires working login)

enable
boot config flags factory
save config
boot

After either method the switch comes up with blank config, default credentials (admin / no password), and management IP 192.168.1.1 on VLAN 1. Continue from Step 5.

ctrld not filtering DNS Check DHCP option 6 is set to the ctrld machine's IP on each VLAN pool. Check ctrld is running: ctrld status. Check the switch is handing out the right DNS: from a device, run nslookup example.com and verify the server IP matches.

WireGuard not connecting Check port 51820 UDP is reachable from outside your network (router port forwarding may be needed for external access). Check: sudo systemctl status wg-quick@wg0

Service logs

# Native
journalctl -u switch-manager -f

# Docker
docker compose logs -f
docker compose ps

Command Reference — Tested Status

Commands the script sends to the switch, with known test status. Use this as a guide when debugging unexpected behaviour — untested commands may behave differently on your firmware version.

Read commands

Command Status Notes
show interfaces confirmed
show poe-main-status confirmed
show vlan confirmed
show sys-info confirmed
show arp confirmed
show config confirmed Returns table output
show ip helper-address not tested
show ip route default not tested
show dhcp-server leases invalid on this firmware Script handles gracefully — returns empty
show dhcp-server static-binding invalid on this firmware Script handles gracefully — returns empty
show dhcp-server invalid on this firmware Script handles gracefully — returns empty

Config / push commands

Command Status Notes
enable confirmed
configure terminal confirmed
terminal length 0 not tested Disables pagination — sent before reads
interface FastEthernet {port} confirmed
vlan members add {vid} {port} confirmed
vlan pvid {port} {vid} not tested Sets native/untagged VLAN on a port
vlan tagging {tagged-set} {port} not tested Adds trunk tagging
vlan create {vid} name "x" type port not tested
no vlan {vid} not tested
name "{description}" (under interface) not tested Sets port description
shutdown (under interface) not tested Disables a port
poe enable / no poe enable not tested
poe poe-limit {milliwatts} not tested
interface vlan {vid} (in config mode) not tested
ip access-list extended {name} not tested
ip access-group {name} in/out not tested
end not tested Returns to enable mode
save config confirmed Caused a reboot on first run — watch the first time you push this

save config reboot note: On at least one switch, issuing save config triggered a reboot. This may be firmware-version-specific or a one-time behaviour after certain config states. Subsequent saves have not reproduced it. Be aware when pushing config changes in a live environment.


Scrollback in screen (console cable sessions)

By default screen does not let you scroll up through output. Enable it with copy mode:

Action Keys
Enter scrollback mode Ctrl-A then [
Scroll up / down Arrow keys or PgUp / PgDn
Exit scrollback mode Esc or q

To increase the scrollback buffer for a session (default is only 100 lines):

Ctrl-A  then  :scrollback 10000

To set it permanently, add this to ~/.screenrc:

defscrollback 10000

Useful when reviewing long show config or show interfaces output during console sessions.


What This Tool Does Not Do

  • Does not manage OPNsense, pfSense, or any other device directly (OPNsense integration is read/sync only)
  • Does not provide a terminal or shell — there is no way to type arbitrary commands through the main interface (CLI mode in settings is available for advanced users but still runs through the safety pipeline)
  • Does not support multiple switches simultaneously
  • Does not provide traffic analytics or bandwidth graphs
  • Does not automatically discover or adopt new network devices

On the ERS Switch Family

These switches have no REST API. Everything this tool does is via SSH sessions that parse text output and send CLI commands — the same thing a human would do at a terminal, automated and wrapped in a browser interface.

There is an inherent limit to how reliably the tool can detect every possible error condition. The danger blocking system catches the known lethal patterns but cannot anticipate every possible misconfiguration. Use the CLI review step. Read what is about to be sent.

The console cable is always your fallback. Keep it accessible.


DNS Filtering — Port 53 Conflict Resolution

When installing ctrld (Option A — local install), ctrld needs to bind port 53. On Ubuntu and Debian, systemd-resolved holds port 53 via its stub listener.

The tool fixes this automatically during installation. It adds DNSStubListener=no to /etc/systemd/resolved.conf and restarts systemd-resolved. The service itself keeps running — it still manages /etc/resolv.conf and local hostname caching. Only the stub listener is disabled.

If the automatic fix fails (permission issue, non-standard config), fix it manually:

echo "[Resolve]" | sudo tee -a /etc/systemd/resolved.conf
echo "DNSStubListener=no" | sudo tee -a /etc/systemd/resolved.conf
sudo systemctl restart systemd-resolved

On OPNsense (Option B): OPNsense runs Unbound DNS on port 53. The correct approach is not to uninstall Unbound — it handles .lan hostnames and local DNS. Instead:

  1. In OPNsense UI: Services → Unbound DNS → General → set Listen Port to 5353, Listen Interface to Loopback (lo0). Save + Apply.
  2. Configure ctrld to forward *.lan and *.local to 127.0.0.1:5353 (the split-horizon block shown in the DNS tab result panel).
  3. ctrld handles all other queries via DoH3 to Control D.

This keeps local names working while all external DNS is filtered per-VLAN through Control D.


DNS Enforcement ACLs

Without enforcement, a device can ignore DHCP-assigned DNS and use 8.8.8.8 directly, bypassing all ctrld filtering.

The DNS tab has an "Enforce DNS on Switch" button that generates ACLs blocking this. For each VLAN:

ip access-list extended DNS-ENFORCE-VLAN10
  1 permit udp 192.168.10.0 0.0.0.255 host [ctrld-ip] eq 53
  2 permit tcp 192.168.10.0 0.0.0.255 host [ctrld-ip] eq 53
  3 deny   udp 192.168.10.0 0.0.0.255 any eq 53
  4 deny   tcp 192.168.10.0 0.0.0.255 any eq 53
  5 deny   tcp 192.168.10.0 0.0.0.255 any eq 853
  6 permit ip any any
interface vlan 10
  ip access-group DNS-ENFORCE-VLAN10 in

Rules 12 permit DNS only to ctrld. Rules 34 block DNS anywhere else (8.8.8.8, Cloudflare, etc.). Rule 5 blocks DNS-over-TLS (port 853) as another bypass path. Rule 6 permits all other traffic so internet still works.

VLAN 99 (management) is automatically excluded — a broken ACL on the management VLAN would lock you out.

The generated commands are shown for review and pushed through the normal TOTP-gated push mechanism. Nothing is sent to the switch automatically.


Inter-VLAN Routing ACL Templates

The ACL Builder tab has a "Use Template" button that pre-fills common policies:

Staff VLAN — full internet, no management access Permits everything except access to VLAN 99 (192.168.99.0/24). Use on a staff or office VLAN where users need full internet but must not reach the management interface.

IoT VLAN — internet only, no RFC1918 Blocks all RFC1918 private address ranges (192.168.x.x, 10.x.x.x, 172.16-31.x.x). IoT devices get internet but cannot reach any other VLAN, internal servers, or management. Permits internet.

Guest VLAN — internet only, DNS must work first Like IoT but explicitly permits DNS to ctrld first (before the deny rules), ensuring DNS filtering continues to work even after RFC1918 is blocked.

Camera VLAN — NVR only Cameras may only send traffic to one NVR/DVR IP. All other traffic is dropped. Prevents cameras from phoning home, scanning the network, or accessing the internet directly.

All templates are fully editable after applying. The template fills the rule table — you adjust IPs, add rules, or delete rules before pushing.


Local Hostname Resolution (dnsmasq)

The DNS tab has a "Local Hostnames" section. It manages an optional dnsmasq container that resolves .lan hostnames for all devices on the network.

How it works:

  1. dnsmasq runs in Docker, listening on port 5353 on the management computer.
  2. ctrld is configured to forward *.lan and *.local queries to 127.0.0.1:5353 (split-horizon rule).
  3. All other queries go through Control D as normal.
  4. switch.mgmt.lan and management.lan always resolve to the management computer's IP.

Setup:

Add hostname→IP mappings in the DNS tab → Local Hostnames section. Click Save & Generate dnsmasq.conf. The tab shows:

  • The generated dnsmasq.conf content and path
  • A docker-compose snippet to add the dnsmasq service
  • A ctrld.toml block to enable split-horizon forwarding

Add the docker-compose snippet to docker-compose.yml, add the toml block to ctrld.toml, then:

docker compose up -d dnsmasq
ctrld restart

The dnsmasq.conf is written to /etc/switch-manager/dnsmasq.conf and mounted read-only into the container.

Files added:

File Location Purpose
local-hostnames.json /etc/switch-manager/ User-defined hostname→IP mappings
dnsmasq.conf /etc/switch-manager/ Generated dnsmasq config
S
Description
Mirror of outis1one/avaya_switch_management from GitHub
Readme
522 KiB
Languages
Python 69.4%
JavaScript 28.7%
Shell 1.9%