--- project: name: UniFi Firewall Zone & Policy Cleanup status: planning category: infrastructure source: homelabagentroot created: 2026-02-22 priority: high tags: [firewall, unifi, security, zones, policies] --- # UniFi Firewall Cleanup Plan **Created**: 2026-02-22 **Priority**: High **Risk Level**: Medium (affects network connectivity) ## Executive Summary Current firewall configuration has **223 policies** with significant issues: - Management zone is empty (no networks assigned) - Default VLAN incorrectly placed in Internal zone - Duplicate and redundant policies - Policy names don't match actual source/destination - Missing documented security rules ## Current State Analysis ### Zone Assignment Issues | Zone | Current Networks | Should Be | Issue | |------|-----------------|-----------|-------| | **Management** | EMPTY | Default + WireGuard | Zone exists but no networks | | **Internal** | Default, Guest, Family, WireGuard | Family only | Contains wrong networks | | **Servers** | Production (VLAN 50) | ✅ Correct | - | | **IoT** | IoT (VLAN 30) | ✅ Correct | - | | **Staging** | Staging (VLAN 40) | ✅ Correct | - | ### Host Distribution by Network | Subnet | Network | Hosts | Zone | |--------|---------|-------|------| | 192.168.1.x | Default | truenas, ubuntu, proxmox, UniFi | Management | | 192.168.4.x | WireGuard | VPN clients (remote admin) | Management | | 192.168.10.x | Family | iPhones, Macs, laptops | Internal | | 192.168.20.x | Guest | Visitor devices | Guest (new) | | 192.168.30.x | IoT | Home Assistant, TVs, smart devices | IoT | | 192.168.40.x | Staging | Dev/test environments | Staging | | 192.168.50.x | Production | grizzley, ice | Servers | ### Policy Issues Found 1. **"Allow Management to Servers"** - Source is actually `Internal` zone, not Management 2. **Multiple redundant policies** for Internal → Servers: - "Allow Family to Services (Fixed)" - "Allow Management to Servers" (misnamed) - "Allow Internal to Servers HTTP" - "Allow Internal to Servers HTTPS" - "Allow Internal to Servers" 3. **System-generated catch-alls** at index 2147483647 create confusion ## Target Architecture ### Zone Assignments (Final State) | Zone | Networks | Subnet | VLAN | Purpose | |------|----------|--------|------|---------| | **Management** | Default + WireGuard | 192.168.1.x, 192.168.4.x | 1, VPN | Infrastructure + remote admin | | **Internal** | Family of D. | 192.168.10.x | 10 | Trusted family devices | | **Guest** | Will of D. (Guest) | 192.168.20.x | 20 | Visitor devices (NEW ZONE) | | **IoT** | Will of D. IoT | 192.168.30.x | 30 | Smart devices, isolated | | **Staging** | Staging | 192.168.40.x | 40 | Dev/test environments | | **Servers** | Production | 192.168.50.x | 50 | grizzley, ice | | **VPN** | (system SD-WAN) | - | - | Site-to-site tunnels | | **External** | (system) | - | - | Internet WAN | ### Connectivity Matrix (Target) | From → To | Mgmt | Internal | Guest | IoT | Staging | Servers | External | |-----------|------|----------|-------|-----|---------|---------|----------| | **Management** (infra + VPN) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | **Internal** (family) | ✅ | ✅ | ❌ | ✅ | ✅ | 80/443 | ✅ | | **Guest** (visitors) | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | | **IoT** (smart devices) | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | | **Staging** (dev) | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | | **Servers** | grizzley, ice | Return | Return | ❌ | Return | Return | ✅ | ✅ | ### Homelab Service Access Requirements | Service | Host | IP | Who Needs Access | |---------|------|-----|------------------| | Traefik (ingress) | grizzley, ubuntu | .84, .61 | Management, Internal (via 80/443) | | Home Assistant | panda | .30.196 | Management, Internal, IoT (local) | | Jellyfin | ubuntu | .61 | Management, Internal, IoT (cast) | | Authentik | ubuntu | .61 | Management, Internal | | Gitea | ubuntu | .61 | Management, Internal, Staging | | TrueNAS | truenas | .12 | Management only | | Proxmox | pve | .11 | Management only | | OpenCode | ubuntu, grizzley, ice | .61, .84, .197 | Management, Internal (via Traefik) | | ZeroClaw | zeroclaw | .199 | Management | [decommissioned] | --- ## Phase 1: Zone Restructuring ### Step 1.1: Create Guest Zone **Action**: Create new "Guest" zone for VLAN 20 ``` POST /firewall/zones { "name": "Guest", "networkIds": ["02364634-a782-4b58-a33b-48b48f492210"] } ``` **Network ID**: `02364634-a782-4b58-a33b-48b48f492210` (Will of D. Guest - VLAN 20 - 192.168.20.x) ### Step 1.2: Update Management Zone **Action**: Add Default AND WireGuard networks to Management zone ``` PUT /firewall/zones/ea466cdf-9aa9-4e1a-9c26-7eba945a35c1 { "name": "Management", "networkIds": [ "bcf0598f-9361-4306-9024-9817fd841836", "805af880-cbb5-4b3e-98aa-39bdaf8af4e2" ] } ``` **Network IDs**: - `bcf0598f-9361-4306-9024-9817fd841836` (Default - 192.168.1.x) - truenas, ubuntu, proxmox - `805af880-cbb5-4b3e-98aa-39bdaf8af4e2` (UGC WireGuard - 192.168.4.x) - VPN clients ### Step 1.3: Update Internal Zone **Action**: Remove Default, Guest, and WireGuard; keep only Family ``` PUT /firewall/zones/1c79c8c2-2cb9-4990-ad4d-81b86940941b { "name": "Internal", "networkIds": ["fb44c9bf-1534-4a98-9c7e-6aee4bf4069a"] } ``` **Network ID**: `fb44c9bf-1534-4a98-9c7e-6aee4bf4069a` (Family of D. - VLAN 10 - 192.168.10.x) --- ## Phase 2: Policy Cleanup ### Step 2.1: Delete Redundant/Misnamed Policies **Policies to DELETE** (USER_DEFINED only - keep SYSTEM_DEFINED): | ID | Name | Reason | |----|------|--------| | `435f77c3-dd28-4a33-be4e-3cdd63957404` | Allow Family to Services (Fixed) | Redundant with others | | `ab51e4c2-9675-4044-8847-d7d05fb56782` | Allow Management to Servers | Misnamed, source is Internal | | `41dfd03d-87c9-4f2d-b3f1-1d4d724ff178` | Allow Internal to Servers | Too broad, use HTTP/HTTPS only | | `a94a3d02-d999-4881-886e-517a50732d5e` | Allow Internal to Management | Won't work (empty zone) | | `fdeac414-47da-45c9-aafc-d91b570c21d5` | Internal to DMZ - All Services | DMZ is empty | ### Step 2.2: Keep Essential Policies **Policies to KEEP**: | Name | Source | Dest | Ports | Notes | |------|--------|------|-------|-------| | Internal to Internal - All Services | Internal | Internal | All | Intra-zone | | Allow Internal to IoT | Internal | IoT | All | Home control | | Allow Internal to Servers HTTP | Internal | Servers | 80 | Web access | | Allow Internal to Servers HTTPS | Internal | Servers | 443 | Web access | | Allow Internal to Staging | Internal | Staging | All | Dev access | --- ## Phase 3: New Policy Creation ### Step 3.1: Management Zone Policies **Required new policies after zone population:** 1. **Management → Servers (All)** - Source: Management - Dest: Servers - Action: ALLOW - Ports: All - Purpose: Admin access to infrastructure 2. **Management → Internal (All)** - Source: Management - Dest: Internal - Action: ALLOW - Purpose: Admin device access 3. **Management → IoT (All)** - Source: Management - Dest: IoT - Action: ALLOW - Purpose: Smart home management 4. **Management → Staging (All)** - Source: Management - Dest: Staging - Action: ALLOW - Purpose: Dev/test access ### Step 3.2: Guest Zone Policies **Required for new Guest zone:** 1. **Guest → External (All)** - Source: Guest - Dest: External - Action: ALLOW - Purpose: Internet access only 2. **Guest Intra-Zone** - Source: Guest - Dest: Guest - Action: ALLOW - Purpose: Guest-to-guest (optional, may block) --- ## Phase 4: Verification ### Step 4.1: Connectivity Tests After each phase, verify: | Test | Expected Result | Notes | |------|-----------------|-------| | Management (192.168.1.x) → Servers SSH | ✅ Allowed | Admin access to grizzley | | Management (192.168.4.x VPN) → Servers | ✅ Allowed | Remote admin via WireGuard | | Internal → Servers 80/443 | ✅ Allowed | Web services via Traefik | | Internal → Servers 22 | ❌ Blocked | No SSH from family devices | | Guest → Internal | ❌ Blocked | Visitor isolation | | Guest → Internet | ✅ Allowed | Internet only | | IoT → Internal | ❌ Blocked | Smart device isolation | | IoT → Internet | ✅ Allowed | Firmware updates, cloud | | IoT → Jellyfin (cast) | ✅ Allowed | Need mDNS/cast rules | | Servers → Internal (unsolicited) | ❌ Blocked | Return traffic only | | Staging → Servers | ✅ Allowed | Dev deployments | ### Step 4.2: Rollback Plan If issues occur: 1. Re-add Default VLAN to Internal zone 2. Re-enable deleted policies (requires recreation) 3. Remove Guest zone assignments --- ## Execution Status ### ✅ COMPLETED - Zone Reassignment (2026-02-22) | Step | Action | Status | |------|--------|--------| | 1.1 | Create Guest zone | ✅ Done | | 1.2 | Assign Default (192.168.1.x) to Management | ✅ Done | | 1.3 | Assign WireGuard (192.168.4.x) to Management | ✅ Done | | 1.4 | Verify Family (192.168.10.x) in Internal | ✅ Done | | 1.5 | Verify Guest (192.168.20.x) in Guest zone | ✅ Done | | 1.6 | Verify IoT (192.168.30.x) in IoT zone | ✅ Done | | 1.7 | Verify Production (192.168.50.x) in Servers zone | ✅ Done | ### ⚠️ REQUIRES MANUAL COMPLETION - Policy Cleanup **Issue**: UniFi API `/firewall/policies` GET/DELETE endpoints returning 500 errors. Creating policies (POST) works fine. ### ✅ New Policies Created via API (2026-02-22) | Policy | ID | Status | |--------|-----|--------| | Management → Servers | `88d48838-6e26-4de0-96b6-eaa63a199cc7` | ✅ Created | | Management → Internal | `10f23c06-1c3a-46ad-8e5f-00d641b7d667` | ✅ Created | | Management → IoT | `29dea2b8-75a0-474e-9b43-2df1ef7c1714` | ✅ Created | | Management → Staging | `e1777d7e-34d1-4ee8-8c7d-906104d2ec4a` | ✅ Created | | Management → Guest | `20e35116-a4bf-49be-b6f3-2c3a01ad1ad6` | ✅ Created | ### ✅ Connectivity Verified (2026-02-22) | Test | Result | |------|--------| | Management → Management (192.168.1.1) | ✅ Ping SUCCESS | | Management → Servers (192.168.50.84) | ✅ Ping SUCCESS | | Management → IoT (192.168.30.196) | ✅ Ping SUCCESS | ### Manual Steps Remaining **Step 1**: Access UniFi Console at https://192.168.1.1 **Step 2**: Go to Settings → Firewall → Policies **Step 3**: Delete these redundant/misnamed policies (if still present): | Policy Name | Reason to Delete | |-------------|------------------| | "Allow Family to Services (Fixed)" | Redundant | | "Allow Management to Servers" (old) | Misnamed (actually Internal) | | "Allow Internal to Servers" | Too broad - use HTTP/HTTPS only | | "Allow Internal to Management" | Empty zone, won't work | | "Internal to DMZ - All Services" | DMZ is empty | **Step 4**: Verify Guest zone has internet access: - Guest → External policy should exist - Test by connecting a guest device to Guest WiFi | Step | Action | Risk | Duration | |------|--------|------|----------| | 1 | Create Guest zone | Low | 1 min | | 2 | Add Default to Management | Medium | 1 min | | 3 | Update Internal zone | Medium | 1 min | | 4 | Delete redundant policies | Medium | 5 min | | 5 | Create Management policies | Low | 5 min | | 6 | Create Guest policies | Low | 3 min | | 7 | Verification tests | Low | 10 min | **Total Estimated Time**: 30 minutes --- ## API Commands Reference ### Zone Management ```bash # List zones curl -k -H "X-API-KEY: $UNIFI_API_KEY" \ "https://192.168.1.1/proxy/network/integration/v1/sites/88f7af54-98f8-306a-a1c7-c9349722b1f6/firewall/zones" # Create Guest zone curl -k -X POST -H "X-API-KEY: $UNIFI_API_KEY" -H "Content-Type: application/json" \ -d '{"name":"Guest","networkIds":["02364634-a782-4b58-a33b-48b48f492210"]}' \ "https://192.168.1.1/proxy/network/integration/v1/sites/88f7af54-98f8-306a-a1c7-c9349722b1f6/firewall/zones" # Update Management zone (add Default + WireGuard) curl -k -X PUT -H "X-API-KEY: $UNIFI_API_KEY" -H "Content-Type: application/json" \ -d '{"name":"Management","networkIds":["bcf0598f-9361-4306-9024-9817fd841836","805af880-cbb5-4b3e-98aa-39bdaf8af4e2"]}' \ "https://192.168.1.1/proxy/network/integration/v1/sites/88f7af54-98f8-306a-a1c7-c9349722b1f6/firewall/zones/ea466cdf-9aa9-4e1a-9c26-7eba945a35c1" # Update Internal zone (Family only) curl -k -X PUT -H "X-API-KEY: $UNIFI_API_KEY" -H "Content-Type: application/json" \ -d '{"name":"Internal","networkIds":["fb44c9bf-1534-4a98-9c7e-6aee4bf4069a"]}' \ "https://192.168.1.1/proxy/network/integration/v1/sites/88f7af54-98f8-306a-a1c7-c9349722b1f6/firewall/zones/1c79c8c2-2cb9-4990-ad4d-81b86940941b" ``` ### Policy Management ```bash # List policies curl -k -H "X-API-KEY: $UNIFI_API_KEY" \ "https://192.168.1.1/proxy/network/integration/v1/sites/88f7af54-98f8-306a-a1c7-c9349722b1f6/firewall/policies?limit=500" # Delete policy curl -k -X DELETE -H "X-API-KEY: $UNIFI_API_KEY" \ "https://192.168.1.1/proxy/network/integration/v1/sites/88f7af54-98f8-306a-a1c7-c9349722b1f6/firewall/policies/{policyId}" ``` --- ## Network ID Reference | Network | Subnet | VLAN | External ID | Zone Assignment | |---------|--------|------|-------------|-----------------| | Default | 192.168.1.x | 1 (native) | `bcf0598f-9361-4306-9024-9817fd841836` | Management | | UGC WireGuard | 192.168.4.x | VPN | `805af880-cbb5-4b3e-98aa-39bdaf8af4e2` | Management | | Family of D. | 192.168.10.x | 10 | `fb44c9bf-1534-4a98-9c7e-6aee4bf4069a` | Internal | | Will of D. (Guest) | 192.168.20.x | 20 | `02364634-a782-4b58-a33b-48b48f492210` | Guest (new) | | Will of D. IoT | 192.168.30.x | 30 | `a6ef0c6e-351c-4f50-94ac-83f9e09b6863` | IoT | | Staging | 192.168.40.x | 40 | `9f58e9dc-575a-4f87-88d6-bf5f5eb720a8` | Staging | | Production | 192.168.50.x | 50 | `5b82817c-b37c-43f2-958d-0c4b337943ce` | Servers | ## Homelab Host Reference | Host | IP | Network | Zone | Purpose | |------|-----|---------|------|---------| | truenas | 192.168.1.12 | Default | Management | Storage (NFS, SMB) | | ubuntu-server | 192.168.1.61 | Default | Management | Primary Docker host (59 containers) | | proxmox | 192.168.1.11 | Default | Management | Hypervisor (VMs, LXCs) | | grizzley | 192.168.50.84 | Production | Servers | Edge ingress (Traefik) | | zeroclaw | 192.168.50.199 | Production | Servers | [decommissioned] AI Gateway | | ice | 192.168.50.197 | Production | Servers | Control Plane, OpenCode | | panda (HA) | 192.168.30.196 | IoT | IoT | Home Assistant OS | ## Zone ID Reference | Zone | ID | |------|-----| | External | `8198a422-f151-4c8b-ae0e-0dea9f89b773` | | Internal | `1c79c8c2-2cb9-4990-ad4d-81b86940941b` | | Management | `ea466cdf-9aa9-4e1a-9c26-7eba945a35c1` | | Servers | `ad697443-67f4-4b5a-8156-f5c6ac0aa370` | | IoT | `5b120d3f-492d-4390-9e64-036f5cea8340` | | Staging | `dc406f85-b1e7-4001-a440-f81ff5f7b731` | | VPN | `a1968d20-a6b9-4549-85a4-fba34c01b036` | | Gateway | `bee86b09-a697-419e-9a63-82015abd3d3b` | --- ## Next Steps 1. Review and approve this plan 2. Schedule maintenance window (low-traffic time) 3. Execute Phase 1 (Zone restructuring) 4. Verify connectivity 5. Execute Phase 2 (Policy cleanup) 6. Verify connectivity 7. Execute Phase 3 (New policies) 8. Final verification 9. Document final state **Approval Required**: Christopher **Target Date**: TBD