Custom network exit firewall — Firewalla-class protection (default deny, NAT, device approval, unsolicited blocked) with full customization via dashboard + API.
Target: replace the legacy gateway as the house exit. Now: lab mode on a secondary NIC for safe testing.
See docs/CUTOVER.md for the full gateway cutover procedure (preflight → wiring → cutover → verify → rollback).
./scripts/cutover-preflight.sh # checks only
FORCE_CUTOVER=1 ./scripts/cutover-gateway.sh # go live
./scripts/cutover-rollback.sh # undoSet these in your environment (or a local secrets file — never commit site-specific values):
| Variable | Purpose |
|---|---|
PROXMOX_NODE | Proxmox host (management reachability) |
ARRAY_FW_CTID | LXC ID for array-firewall |
ARRAY_FW_IP | Container management IP on LAN (eth0) |
ARRAY_FW_LAB_CIDR | Lab / bench client subnet on eth1 (e.g. 198.51.100.1/24) |
| Item | Example (RFC 5737 documentation space) |
|---|---|
| Proxmox | ${PROXMOX_NODE} |
| Container | CT ${ARRAY_FW_CTID} |
| Management | ${ARRAY_FW_IP} (eth0) |
| Lab / clients | ${ARRAY_FW_LAB_CIDR} (eth1 → lab bridge) |
| Dashboard | http://${ARRAY_FW_IP}:8090/ |
| Sentinel | http://${ARRAY_FW_IP}:8098/ |
- Forward + input: drop by default; only established/related + explicit allows
- Internet (lab → uplink): only MACs in allowlist (admin laptop pre-approved)
- NAT: masquerade lab CIDR → uplink
- Unsolicited inbound: denied on lab/WAN interface
- New devices: discovered via DHCP/ARP, denied until allowed in dashboard
# Set your laptop MAC (recommended)echo'ADMIN_LAPTOP_MAC=aa:bb:cc:dd:ee:ff'> /root/.secrets/array-firewall.env
export PROXMOX_NODE=pve-primary.example
export ARRAY_FW_CTID=100
export ARRAY_FW_IP=192.0.2.10
cd /path/to/array-firewall
./deploy.shToken after deploy: ssh root@${ARRAY_FW_IP} cat /etc/array-firewall/api.token
When co-hosted with Warzone Lobby Sentinel, array-firewall runs a closed-loop stack: Sentinel telemetry → mitigation → nft shield / blocklists → learning → optional fleet sync.
Session audit cheater counts are network probe attackers targeting your Xbox (tiny-packet floods, VPS mesh, abnormal CoD roles) — not in-game player slots or aimbot/wallhack identification. Infrastructure peers (LAN gateways, mesh APs, CoD backends, private IPs) are excluded from counts.
Central orchestration in api/lib/probe_ops.py, configured under gaming.mitigation.probe_ops in policies.json:
| Feature | What it does |
|---|---|
| Instant sync on block | Every peer block refreshes UDP confusion peers, nft probe rules, and shield peer sets |
| Live cheater counter | Running session tally + spike detection (blocks in last N seconds) |
| Pre-burst shield | Blocks peers with identical bursts ≥4 and fixed size spread before full threshold |
| Adaptive UDP echo | Per-attacker IP modes: mutate-echo, jitter-drop, why-only, silent-drop |
| TCP persona stickiness | Honeypot sink rotates http/ssh/ftp/rdp/generic banners per IP |
| Download desync boost | Auto-applies download buffer assist when probe pressure ≥ threshold (not only jitter) |
| Mesh /24 blocks | Lowered clique thresholds for automatic subnet blocks |
| Auto abuse reports | Generates provider abuse reports for repeat VPS/tiny-packet offenders |
| Fleet push | Exports blocklist bundle after probe blocks (when fleet_sync_enabled) |
| Evidence export | One-click zip/json bundle per session (postmortem, playback, logs) |
Active countermeasure services:
| Unit | Role |
|---|---|
array-firewall-probe-sink | TCP honeypot (port 39217) — fake banners, 12s tarpit, auto-block |
array-firewall-probe-udp-confusion | UDP sink (port 39218) — DNAT’d tiny probes get mutated echoes + why?? |
Post-mortem reports for every gaming session under /var/lib/array-firewall/session-reports/:
- Batch audit all saved sessions for probe source counts
- PROBE HEAVY / MODERATE / LIGHT synthetic lobby verdict when AI verdict data is missing (instead of misleading CLEAN)
- Killcam correlation — links game killcam block events to probe forensics in the report
- Playback — timeline of probe detections and shield actions during the session
CLI helpers (on the appliance):
shield-failsafe.sh audit-all-sessions # batch audit index
shield-failsafe.sh playback-session HEX # session playback text| Method | Path | Description |
|---|---|---|
| GET | /api/v1/gaming/probe-ops/live | Live cheater count, spike flag, recent probe IPs |
| GET | /api/v1/gaming/probe-ops/health | Probe sink services, DNAT rule, UDP sink self-test |
| GET | /api/v1/gaming/probe-ops/metrics | Combined live + health + confusion + abuse stats |
| POST | /api/v1/gaming/probe-ops/export | { "session_hex": "..." } → evidence zip path |
| POST | /api/v1/gaming/probe-ops/fleet-push | Force fleet blocklist export/push |
| GET | /api/v1/gaming/probe-confusion | UDP/TCP confusion countermeasure status |
| POST | /api/v1/gaming/probe-confusion/ensure | Sync peers + restart sink services |
| GET | /api/v1/gaming/session-audit/all | Audit index (all sessions, cheater counts) |
| POST | /api/v1/gaming/session-audit/batch | Batch re-audit up to N sessions |
| GET | /api/v1/gaming/sessions/{hex}/postmortem | Full post-mortem JSON |
| GET | /api/v1/gaming/sessions/{hex}/playback | Session playback JSON or ?format=text |
| GET | /api/v1/gaming/sessions/{hex}/evidence | Evidence bundle (zip + directory) |
| POST | /api/v1/gaming/mitigate | Closed-loop mitigation from Sentinel payload |
Dashboard: Gaming Ops tab → Probe countermeasures panel (live count, health check, fleet push).
See also docs/ARCHITECTURE.md for the full gaming stack topology.
| Method | Path | Description |
|---|---|---|
| GET | /api/health | Service health (no auth) |
| GET | /api/v1/devices | List devices + allow status |
| POST | /api/v1/devices/{mac}/allow | Grant internet |
| POST | /api/v1/devices/{mac}/deny | Revoke internet |
| POST | /api/v1/firewall/discover | Rescan DHCP/ARP + reload rules |
| POST | /api/v1/firewall/reload | Re-apply nft rules |
| GET | /api/v1/firewall/status | NAT, shield, allowlist summary |
| POST | /api/v1/shield/enable | { "level": "normal" } |
| POST | /api/v1/shield/relax | Disable packet shield |
| GET | /api/v1/gaming/match-cockpit | Unified Sentinel + autopilot + probe_ops snapshot |
- Plug a device into the lab NIC — gets a DHCP address on the lab subnet, no internet until allowed
- Open dashboard — allow device with one click
- Admin laptop MAC (from secrets) has internet from first boot
/opt/array-firewall/api/ # Python API + dashboard
/opt/array-firewall/gaming-tools/ # probe-sink-listener, probe-udp-confusion, packet-shield-nft.sh
/var/lib/array-firewall/devices.json
/var/lib/array-firewall/session-reports/ # post-mortem JSON per session
/var/lib/array-firewall/session-evidence/ # exported evidence bundles
/var/lib/array-firewall/probe-live-stats.json
/var/lib/array-firewall/probe-attacker-profiles.json # per-IP persona + echo modes
/var/lib/array-firewall/ruleset.nft
/etc/array-firewall/api.token
/etc/dnsmasq.d/array-firewall.conf