# Cascades — Voice VLAN (VLAN 30) Cutover Runbook + Recon

- **Created:** 2026-06-16 (Howard-Home / claude-main)
- **Status:** PLANNED — not yet executed. Vendor email sent 2026-06-16; awaiting Richard's confirm + maintenance window.
- **Driver:** Vertical (VoIP vendor, Richard Turner <RTurner@vertical.com>) cannot reach the phones from the remote-management desktop, and phone IPs drift. Root cause: when the network was segmented into VLANs, the Vertical remote desktop and the wired phones were left on the original LAN while the wireless phones landed on VLAN 20 — so the desktop has no path to the wireless phones (main-LAN -> VLAN 20 is blocked at pfSense).

## Goal
Consolidate ALL voice gear (Poly WiFi phones + AudioCodes wired phones + Vertical-Remote desktop) onto a dedicated, isolated voice network. Voice reaches the internet; blocked from main LAN / VLAN 20 / PHI. Vertical's pfSense OpenVPN scoped to the voice subnet only.

```
VOICE network:   VLAN 30
Subnet/gateway:  10.0.30.0/24   gw 10.0.30.1   (pfSense igc1.30)
DHCP pool:       10.0.30.100 - 10.0.30.250
Reservations:    below .100 (out of pool -> safe on both ISC and Kea)
Desktop:         10.0.30.10  (Vertical-Remote, e4:e7:49:52:3a:06) -> set NIC to DHCP
```

## Systems
pfSense `192.168.0.1` does ALL routing + DHCP. UniFi (UOS controller `172.16.3.29`, Cascades site `685f39068e65331c46ef6dd2`) is L2 only here — every UniFi network is `purpose: vlan-only` (no subnets in UniFi). So building VLAN 30 touches BOTH systems.

---

## Confirmed architecture (UOS controller, 2026-06-16)

| Device class | Count | Attach | Currently lands on |
|---|---|---|---|
| Poly phones | 22 active (~29 historical) | **WiFi**, SSID **CSCNet**, APs building-wide | VLAN 20 "Internal" (`10.0.20.x`) |
| AudioCodes phones | 8 | **Wired**, USW-16-PoE **ports 1-8** | "Default" / main LAN (`192.168.2/3.x`) |
| Vertical-Remote desktop | 1 | **Wired**, USW-16-PoE **port 16** | "Default" / main LAN (`192.168.2.180`, static) |

**CSCNet is a shared PPSK SSID** (`wlanconf 685f39078e65331c46ef7ee5`, `private_preshared_keys_enabled:true`, base networkconf = Default, `vlan_enabled:false`). ~230 per-key->network mappings: most keys map to per-room resident VLANs (101-631), a few to Default, and one phone key maps to "Internal"/VLAN 20 (`networkconf 69405ba36db796548c947130`). Historical CSCNet clients: 1,190 (residents' IoT/TVs/phones/laptops + staff + the phones). **=> Do NOT repoint the CSCNet SSID itself** — that would move every resident/staff device. Move the phones at the PPSK level instead.

Networks of interest:
- Default (main LAN): `685f39078e65331c46ef8ac4`, `192.168.0.0/22`
- Internal (VLAN 20): `69405ba36db796548c947130`, `10.0.20.0/24`
- Guest (VLAN 50): `10.0.50.0/24`
- OpenVPN Server: `192.168.8.1/24` (purpose remote-user-vpn) — Vertical comes in here.

---

## PBX recon (CS-SERVER via GuruRMM, 2026-06-16)

Probed from CS-SERVER (`192.168.2.254`, same LAN segment) — read-only.

| Target | TCP open | SIP UDP 5060 | Conclusion |
|---|---|---|---|
| `192.168.2.180` (desktop) | 3389 (RDP) only | no reply | **Not a PBX** — RDP management/jump box |
| `192.168.2.228` (CS-QB, labeled "VoIP server") | 445 (SMB) only | no reply | **Not a live SIP PBX** — behaves like an SMB box despite the label |

**Implication:** no on-prem SIP PBX detected -> phones almost certainly register to a **cloud/hosted PBX** (Vertical). If confirmed, the voice VLAN only needs internet egress and the on-prem PBX pinhole (Part A step 5b) is **NOT needed**. Caveat: external port view only — a non-standard port / known-peer-only / host-firewalled PBX can't be 100% excluded, so Richard's confirm is the authority.

---

## PART A — pfSense (`https://192.168.0.1`)

1. **VLAN interface:** Interfaces -> VLANs -> Add: Parent `igc1`, Tag `30`, Desc `VOICE`.
2. **Assign + IP:** Interfaces -> Assignments -> add `igc1.30` -> Enable, Static `10.0.30.1/24`.
3. **DHCP:** Services -> DHCP Server -> VOICE: enable, range `10.0.30.100-.250`, DNS `10.0.30.1`.
4. **Reservation (desktop):** Static Mappings -> `e4:e7:49:52:3a:06` = `10.0.30.10`, hostname `Vertical-Remote`. (Phones optional — see Appendix; they stay reachable from the desktop on-subnet regardless.)
5. **Firewall (VOICE tab), top-to-bottom:**
   - Alias `RFC1918` = `10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16`.
   - (a) PASS: VOICE net -> This Firewall (10.0.30.1) ports 53, 123.
   - (b) **CONDITIONAL** PASS: VOICE net -> `<on-prem PBX IP>` SIP/RTP/provisioning. **Recon says SKIP (cloud PBX); add only if Richard confirms an on-prem PBX.**
   - (c) BLOCK: VOICE net -> `RFC1918`. (isolation)
   - (d) PASS: VOICE net -> any. (internet)
6. **OpenVPN — reach desktop on VOICE, scoped to voice only:**
   - His `.ovpn` does NOT need re-export (routes are server-pushed; same host/port/cert) — he just reconnects.
   - Preferred: VPN -> OpenVPN -> **Client Specific Overrides** for **Richard's CN**: IPv4 Local Network/s = `10.0.30.0/24` only; give him a fixed tunnel IP.
   - Firewall -> Rules -> OpenVPN: PASS `<Richard tunnel IP>` -> `10.0.30.0/24`; BLOCK `<Richard tunnel IP>` -> `RFC1918`.
   - If the VPN server is shared, use the CSO + per-tunnel-IP rules (do NOT widen the server's global Local Networks). If Vertical-only, may edit the server in place.

## PART B — UniFi (UOS controller)

7. **Network:** Settings -> Networks -> Add: `VOICE`, purpose `VLAN Only`, VLAN `30`.
8. **Wired ports (USW-16-PoE):** set Native Network = VOICE (untagged) on **ports 1-8** (AudioCodes) and **port 16** (desktop). AudioCodes re-DHCP automatically; desktop needs Vertical's NIC change.
9. **Wireless Poly (PPSK):** Settings -> Profiles -> Private Pre-Shared Keys (CSCNet) -> **add a new key -> Network VOICE** (vault the key). Re-point each Poly phone's WiFi to the voice key (by hand / Vertical provisioning). Also fixes the 2 currently mis-keyed phones (one on VLAN 422, one on Default). [Alt zero-touch: remap the existing phone key VLAN 20 -> VOICE, ONLY if that key is confirmed phone-exclusive — ~70 non-phone devices also showed on VLAN 20, so default to the dedicated key.]
   - Confirm inter-switch / AP uplinks + the pfSense trunk carry VLAN 30 (default "All" port profile auto-includes it).

---

## Cutover sequence (avoid stranding anything)
1. Build everything with no live impact: pfSense VLAN/DHCP/firewall, OpenVPN CSO+rules, UniFi network, create the voice PPSK.
2. **AudioCodes:** flip USW-16-PoE ports 1-8 -> VOICE. Re-DHCP + re-register (brief blip).
3. **Poly:** re-key to voice PPSK. Roam onto VOICE.
4. **Desktop (coordinated with Vertical — static, no login):**
   - Confirm OpenVPN pushes `10.0.30.0/24` to Richard.
   - Remote path: Vertical sets NIC -> DHCP FIRST (pulls a temp main-LAN lease, stays reachable) -> confirm reconnect -> THEN flip port 16 -> VOICE -> desktop renews to `10.0.30.10` -> Vertical reconnects via VPN.
   - Onsite path (cleaner): set DHCP + flip port together at the keyboard.
5. Hand Richard `10.0.30.10`; confirm VPN reach + phone reach from the desktop.

## Validation
- VOICE DHCP leases show phones on `10.0.30.x`; desktop on `10.0.30.10`.
- From desktop: reach several phones (Poly + AudioCodes).
- Isolation negative test: from VOICE, CANNOT reach CS-SERVER `192.168.2.254` or `10.0.20.x`.
- Phones registered / dial tone on a sample handset.
- Richard: VPN -> `10.0.30.10` -> phone web UI.

## Rollback
Revert UniFi port native VLAN (1-8, 16) + the PPSK key to prior networks; AudioCodes/desktop re-DHCP onto old segments. pfSense VOICE iface/DHCP/rules + OpenVPN CSO can stay inert or be removed. Desktop: Vertical reverts NIC to static `192.168.2.180` if needed.

---

## Open items (pending Richard)
- Confirm phones register to **cloud/hosted PBX** (recon says yes) -> if so, Part A step 5b pinhole is skipped.
- Confirm desktop is **static** (asked in the email) and arrange NIC change or temp access at cutover.
- Get **Richard's VPN certificate CN** for the scoped Client-Specific-Override.
- Confirm pfSense **DHCP backend** (ISC vs Kea) when connected (reservations placed out-of-pool either way).
- Schedule the maintenance window.

## Appendix — device inventory (MACs)
**AudioCodes (wired, USW-16-PoE):**
```
port1 00:90:8f:da:98:05   port5 00:90:8f:e1:3d:90
port2 00:90:8f:e2:40:5e   port6 00:90:8f:e1:3d:5e
port3 00:90:8f:e2:d2:a4   port7 00:90:8f:e1:3d:a9
port4 00:90:8f:e1:3d:de   port8 00:90:8f:e1:3e:17
```
**Poly (wireless, CSCNet -> voice PPSK):**
```
48:25:67:d0:af:10  48:25:67:64:8a:88  48:25:67:64:95:6b
48:25:67:d0:b4:26  48:25:67:64:93:34  48:25:67:64:8e:ae
48:25:67:64:81:8e  48:25:67:64:93:25  48:25:67:64:92:6b
48:25:67:d0:ae:3e  48:25:67:64:95:62  48:25:67:64:93:d3
48:25:67:d0:b8:ac  48:25:67:64:94:84  48:25:67:64:94:ba
48:25:67:64:8f:14  48:25:67:64:95:74  48:25:67:64:8f:0b
48:25:67:d0:b1:83  48:25:67:64:92:89  48:25:67:64:8f:1d
48:25:67:a3:f8:3b
(22 total — source: Richard's 2026-06-16 scan list)
```
**Desktop:** `e4:e7:49:52:3a:06` (Vertical-Remote) -> reserve `10.0.30.10`.
