Runbook 14 — Validation (full end-to-end test matrix)¶
Goal: prove the firewall + identity/storage/SSO stack works end-to-end. Run the matrix from a test client on each zone (a Proxmox VM with its NIC tagged to the VLAN under test, or a switch access port set to that VLAN — it DHCPs from the firewall).
Prereqs: runbooks 01–13 applied.
✅ CONSOLIDATED PASS — automatable matrix run from the test client (9150, WORKSTATIONS
10.20.40.101) + fleet hosts. Passed: DHCP/DNS + DNSSEC AD; IPv6 affirmatively off (no v6 addr/route,curl -6fails); Proton egress for clients (M247) AND servers (Proton AG); inter-zone default-deny (WS→DMZ blocked, WS→SERVERS-SSH blocked, WS→MGMT-host blocked, DMZ→MGMT blocked) + allow-list (WS→SERVERS NFS:2049 open); identityid operator=640400004 consistent; hidden primary answers internally, recursion REFUSED, anonymous AXFR refused (TSIG); origin Caddy serves; edge mechanism (rb17); SSO redirect →auth.${domain}.⚠️ FINDING — OPNsense web GUI reachable from client zones.
https://10.20.10.1returns "Login | OPNsense" from WORKSTATIONS (the GUI listens on all interfaces; the inter-zone host blocks are otherwise correct — WS→MGMT host and WS→firewall:22 are blocked). FIX: System → Settings → Administration → Listen interfaces = MGMT only CLOSED 2026-07-26: enforced instead via the automation rule seq 91 —WORKSTATIONS → (self):443block (fw-automation-rules.json, like the SERVERS seq-90 rule), asserted by the conformance harness (WS canary = a workstation viaadmin-workstations). GUI reachable from MGMT + wg-admin only; per-zone DNS/NTP self-rules untouched. (the WG admin peer reaches MGMT); also confirm the firewall's SSH is key-only/no-root. Re-test: WS→10.20.10.1:443should become blocked.⏳ Still hands-on (not automatable from the build host): Proton failover + kill-switch (GUI toggle; mechanism is in the config); external port-scan of the Comcast IP = only UDP 51820 on
.69+ no service NAT (the core Phase-1 proof); mDNS cast/print (rb08, physical devices); road-warrior dial-in (admin→MGMT, users→Jellyfin).⊘ Deferred to Phase 2 (by design): real LE certs (origin is on
tls internaluntil the edges make names publicly resolvable), real VPS edges, Authelia MFA.
How to run the matrix¶
- Spin up a test client VM on Proxmox with its NIC on the LAN bridge, tagged
to the VLAN under test (e.g.
tag=40for WORKSTATIONS), or use a switch access port set to that VLAN. It DHCPs from the firewall (the only DHCP server on the VLANs). - Repeat per zone to exercise the inter-zone matrix below.
Test matrix¶
Connectivity & DHCP/DNS¶
- [ ] Client on VLAN 40 gets
10.20.40.10x, gw.1, DNS.1. - [ ]
dig google.comanddig ipa.${ipa_domain}both resolve. - [ ] DNSSEC validating (
dig +dnssecAD flag). - [ ] IPv6 affirmatively off: "Turn off IPv6" is checked (Interfaces →
Settings); a test client has no global IPv6 address and no IPv6
default route (
ip -6 routeshows none);curl -6 https://google.comfails immediately (no usable v6) and plaincurlsucceeds — nothing needs-4.
ProtonVPN egress + failover + bypass + kill-switch¶
- [ ] WORKSTATIONS client and a SERVERS host:
curl ipinfo.ioshows a Proton IP (clients + servers both egress via the group). - [ ]
VPN_BYPASSworks: from a client, a Google "what's my IP" check shows your real WAN IP; YouTube loads. The Roku (IOT) plays YouTube. - [ ] Failover (LB self-heal): disable one Proton instance → its gateway drops from the load-balance pool within the monitor interval and egress continues via the remaining members (egress IP may change); re-enable → it rejoins.
- [ ] Kill-switch: disable all Proton instances → non-bypass internet
stops (no leak);
VPN_BYPASSdestinations + inbound reverse proxy still work; re-enable → restored. - [ ] Inbound reverse proxy still serves while egress is on Proton (confirms WAN
reply-tofor inbound is independent of the Proton default). - [ ] RFC1918 bypass: WS → fileserver NFS is LAN-speed (not tunneled); states show the flow on the normal table, not a PROTON* interface.
Inter-zone policy (default deny)¶
- [ ] WS → SERVERS: IPA + NFS ports OK; other ports blocked.
- [ ] WS → MGMT: blocked. WS → DMZ-internal: blocked. WS → IOT/GUEST: blocked (except WS→IOT cast/print).
- [ ] GUEST → any RFC1918: blocked; internet OK; client isolation on.
- [ ] IOT → anything except DNS/NTP-to-fw, Jellyfin, and 5353-to-WORKSTATIONS: blocked.
- [ ] DMZ → SERVERS only on the one backend port; DMZ → MGMT/clients blocked.
Discovery (mDNS)¶
- [ ] WORKSTATIONS phone discovers Roku → casts Jellyfin; laptop discovers + prints.
Identity / NFS home¶
- [ ]
id operatorconsistent UID across FreeIPA, fileserver, and 2 clients. - [ ] Login on two workstations → same
/home/operatorvia NFS4 (sec=sys); owner=operator.
Remote access (WireGuard)¶
- [ ] From outside: admin peer → reaches MGMT + firewall GUI; user peers → Jellyfin only, MGMT blocked.
Origin services (Phase 1 — internal only; no public inbound)¶
- [ ] Each site serves a valid LE cert auto-issued by the origin Caddy →
backend; HTTP→HTTPS; HTTP/3 (h3) — tested internally
(
--resolve cloud.${domain}:443:10.20.30.10, or a temp Unbound override). - [ ] No service port-forwards exist (Firewall → NAT → Destination NAT has no
80/443/53/22); external scan of the Comcast IP shows ONLY UDP 51820 on.69(WG admin) — nothing else inbound. This is the core Phase-1 proof. - [ ] Certs issued via DNS-01/RFC2136 (origin Caddy → hidden Bind primary).
- [ ] Internal resolution: Unbound answers clients, forwards
${ipa_domain}→ FreeIPA. Hidden primary:dig @10.20.30.40 ${domain} SOAanswers internally, recursion REFUSED, anonymous AXFR refused (TSIG required).
Edge (once a VPS edge exists; see runbook 17)¶
- [ ] From the public internet,
https://<site>hits the edge IP and the presented cert is the home origin's (TLS passthrough — the edge holds no key). - [ ]
dig @<edge-ip> ${domain} SOAanswers from the edge secondary with the primary's serial (AXFR over the tunnel);wg showon home = live edge handshake. Home Comcast scan still shows only WG.
Identity-aware access (Authelia SSO/MFA)¶
- [ ] A protected site redirects to
auth.${domain}, requires FreeIPA login + MFA, then loads the app (forward-auth at the origin Caddy — unchanged by edge/origin; the edge only passes the encrypted stream through). - [ ] User not in the allowed group is denied; SSO is shared across protected apps.
- [ ] Direct hits to a protected backend (bypassing Authelia) are blocked at Caddy.
Management posture¶
- [ ] No zone except the WG admin peer can reach MGMT.
- [ ] SSH to firewall: key-only, no root, MGMT-scoped.
Sign-off¶
When every box is checked, take a fresh config backup (System → Configuration → Backups) and snapshot the FreeIPA/fileserver state. The lab is validated end-to-end.