From 69987190fc9fbeb57131cf7ec465f8cc9850792c Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Tue, 16 Jun 2026 07:39:53 -0700 Subject: [PATCH] =?UTF-8?q?unifi-wifi:=20roadmap=20=E2=80=94=20pfSense=20g?= =?UTF-8?q?ateway=20compatibility=20layer=20(=C2=A7=20E)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Capture the "UniFi APs/switches behind a pfSense gateway" topology (Cascades, our office, several clients) as a first-class roadmap item: make the gateway verbs (gw-audit / gw-control / VPN) work against pfSense via a thin driver behind the same verbs (gw-audit already detects num_gw=0 = third-party firewall). Includes the verb->pfSense mapping (NAT port-forwards, filter rules, easyrule block-ips, native OpenVPN/IPsec/WireGuard), ranked backend options (REST-API pkg vs stock SSH easyrule/pfSsh.php vs diag_command.php vs config.xml), existing vaulted pfSense creds (Cascades + office), and open decisions. SKILL.md status block notes the proposed layer. Co-Authored-By: Claude Opus 4.8 (1M context) --- .claude/skills/unifi-wifi/SKILL.md | 4 ++ .../skills/unifi-wifi/references/ROADMAP.md | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/.claude/skills/unifi-wifi/SKILL.md b/.claude/skills/unifi-wifi/SKILL.md index 7fa5b9d..4178a19 100644 --- a/.claude/skills/unifi-wifi/SKILL.md +++ b/.claude/skills/unifi-wifi/SKILL.md @@ -39,6 +39,10 @@ path is Cascades — override with the script's vault-path arg per client. an internet-facing exposure (e.g. a brute-forced PPTP). Gated/DRY-RUN, rollback saved. Controller-side. - **[WIP] Client DHCP/DNS policy, deeper VPN (server) config, adoption *remediation* depth** — port-forward + WAN firewall is now covered (gw-control); remaining gateway config (VPN server stand-up, DHCP/DNS) is future. +- **[PROPOSED] pfSense gateway compatibility layer** — the gateway verbs (gw-audit / gw-control / VPN) speak + UniFi REST today; the common "UniFi APs+switches behind a pfSense gateway" topology (Cascades, our office, + several clients) needs the same verbs via a pfSense driver (REST-API pkg or stock `easyrule`/`pfSsh.php`). + Design + backend options + verb-mapping captured in `references/ROADMAP.md` § E. - **Per-client requirement:** `watch-ap`/`neighbor-collect`/`survey-collect`/`dfs-check` default the AP device-auth SSH cred to `clients/cascades-tucson/unifi-ap-ssh`; for another client, vault its own `clients//unifi-ap-ssh` and pass it as the script's vault-path arg. diff --git a/.claude/skills/unifi-wifi/references/ROADMAP.md b/.claude/skills/unifi-wifi/references/ROADMAP.md index 5db958c..c9f387a 100644 --- a/.claude/skills/unifi-wifi/references/ROADMAP.md +++ b/.claude/skills/unifi-wifi/references/ROADMAP.md @@ -74,6 +74,58 @@ side, multi-client enablement, and non-WiFi scope. Build/validate new apply acti - [ ] **Scheduling** — periodic `dfs-check` + neighbor/survey refresh (DFS is time-varying). - [ ] Vault read-only `infrastructure/uos-server-network-api` (least-privilege; RW does double duty now). +## E. pfSense gateway support — gateway "compatibility layer" (NEW, proposed 2026-06-16) +**Why:** a very common ACG topology is **UniFi APs/switches (on the UOS controller) behind a pfSense +gateway** instead of a UniFi gateway (USG/UXG/UCG) — Cascades, **our own office**, and several other +clients. The controller-side WiFi/switch tooling already works at these sites, but the *gateway* verbs +(`gw-audit` health, `gw-control` port-forwards / WAN firewall / block-ips, VPN) only speak the UniFi +controller REST. Goal: make the **same verbs** work against a pfSense gateway via a thin driver, so one +skill covers WiFi+switch+gateway regardless of who makes the gateway. + +**Design — a `gw` driver interface (backend behind the existing verbs), not a parallel skill.** +Detection is already in hand: `gw-audit` reports `num_gw=0` → "no UniFi gateway (third-party firewall, +e.g. pfSense)". That signal selects the **pfsense** backend instead of the **unifi** backend. The verbs +stay identical; only the driver differs: + +| verb (UniFi backend) | pfSense equivalent | +|---|---| +| `gw-audit` (WAN/health/uptime) | `pfctl -si`, gateway status, `get_interface_*`; CPU/mem/uptime via shell | +| `pf-list` / `pf-set-ports` / `pf-disable` | NAT port-forward objects (`` in config.xml / REST `firewall/nat/port_forward`) | +| `fw-disable` / `fw-enable` | filter rules (`` / REST `firewall/rule`) | +| `block-ips` | **`easyrule block wan `** (cleanest map) or an address **alias** + WAN block rule | +| VPN server stand-up (Deeper VPN)| pfSense is the *better* VPN host — OpenVPN / IPsec / **WireGuard** native (relevant to moving clients off Windows RRAS PPTP, cf. Grabb) | + +**Backend options for pfSense (ranked):** +1. **pfSense REST API package** (`pfSense-pkg-API` / built-in API on Plus) — cleanest 1:1 object mapping + (NAT, rules, aliases, interfaces, services). Cost: must standardize on installing/enabling it fleet-wide. +2. **SSH + stock CLI** — `easyrule block/unblock` (perfect for `block-ips`), `pfSsh.php playback` and + `php -r` for config reads/writes + `filter_configure`/`rc.reload_all` to apply. No package needed. +3. **`diag_command.php` php-exec over the web GUI** — the fleet's *existing* ad-hoc pfSense pattern + (Howard). Works but fragile (curl quoting; CSRF; see errorlog 2026-06-16). Good stopgap, poor primitive. +4. **`config.xml` read/edit + reload** — most powerful, highest blast radius; backup-first, atomic reload. + +**Already have:** vaulted pfSense creds for **Cascades** (`clients/cascades-tucson/pfsense-firewall`, +`…/pfsense-openvpn-howard`) and **our office** (`infrastructure/pfsense-firewall`) — i.e. the auth side +exists for at least two sites; per-client pfSense cred vaulting mirrors the AP-SSH-cred pattern. + +**Open decisions (resolve before building):** +- [ ] **Primary backend:** standardize on the REST API package (clean, an install step per box) vs. + stock SSH `easyrule`/`pfSsh.php` (no install, messier, but works on every pfSense today)? +- [ ] **Where the abstraction lives:** dispatch *inside* `gw-audit.sh`/`gw-control.sh` on detected gw type, + vs. sibling `pf-gw-audit.sh`/`pf-gw-control.sh` with a shared verb contract. (Lean: dispatch inside, so + callers/SKILL docs don't fork.) +- [ ] **Reach + rollback:** many pfSense gws are behind the site (need Tailscale/site-VPN reach, like the + AP collectors); every write backs up config.xml first and reloads atomically (`filter_configure`). +- [ ] **Site→gateway map:** record per-site gateway type + access (UOS site_id ↔ pfSense host/cred) so the + driver auto-selects. Could live alongside `sites.sh` output. +- [ ] **VPN convergence:** the "Deeper VPN — gateway-hosted VPN server" item (C) is *easier and better* on + pfSense (WireGuard/OpenVPN) than on a USG — fold the Grabb-style "retire Windows RRAS PPTP → gateway VPN" + play into the pfSense driver from the start. + +**First validation targets:** our office + Cascades (creds already vaulted; `gw-audit` already classifies +them as pfSense). Start read-only (`gw-audit` parity: WAN/health via `easyrule`/`pfctl`), then `block-ips` +via `easyrule` (lowest-risk write, directly useful for the same brute-force containment as the UniFi side). + ## Cross-platform notes (baked into the scripts; keep for any new ones) - Pass temp paths to python via **ARGV** (MSYS translates POSIX→Windows for python.exe); `$TMP` inside a `python -c` string is NOT translated → fails on Windows.