Attack and defence flow: red team action, pfSense routing, Suricata/Wazuh detection, and the verdict on each row

PEAS SOC: Running Both Sides of the Fight — Attacking My Own Blue Team's Detection Matrix

Before our group’s live attack/defence rounds, I ran three untested rows of our Blue Team Playbook’s detection matrix solo — playing attacker and defender at once to find real detection gaps before they’d cost us marks.

6 November 2026 · 5 min
pfSense console with all nine zones assigned and addressed

TAFE SOC Network Group Project

The 9 zones behind the firewall pfSense sits at the centre as firewall and router. WAN, LAN, CORP (VLAN 10), Blue Team / SOC (VLAN 20), MGMT (VLAN 99), DMZ (VLAN 30), Red Team / Guest (VLAN 40), WiFi-CORP (VLAN 50), WiFi-Guest (VLAN 60). Red Team to Blue Team direct access is denied both ways and logged. Each box opens a panel below the map with what the zone does and what changed on it during the project. Remote access — Remote access runs through OpenVPN on pfSense with FreeRADIUS authentication against Active Directory, tunnelling clients onto a dedicated 10.200.0.0/24 network that reaches the SOC segment only, not CORP, not DMZ, with the option to layer TOTP or privacyIDEA for MFA. RADIUS group membership, not just a valid login, determines which internal segments a VPN client can actually reach. 🔐 Remote access OpenVPN · 10.200.0.0/24 reaches SOC only, not CORP or DMZ Detection — Two independent views of the same activity: Suricata IDS on the GUEST, DMZ and CORP segments, correlated against Wazuh on the SOC segment. 🛰 Detection Suricata on 3 zones · Wazuh two independent views of one round WAN — The firewall's uplink, taking its address by DHCP from the campus NetLab pod. WAN the uplink to the campus network vtnet0 · DHCP from NetLab POD pfSense — pfSense sits at the centre as firewall and router, segmenting nine zones: router-on-a-stick, with Proxmox's VLAN-aware bridge handling trunking. Explicit deny rules enforce isolation between zones that should never touch, and every block is logged. Segmentation was designed around aliases, not one-off rules, so the deny policy could be reasoned about and audited as a whole. 🧱 pfSense fw01 · router-on-a-stick routing · NAT · Suricata IDS/IPS OpenVPN · Squid proxy alias-based deny · every block logged 802.1Q trunk on vtnet1 SW-CORE (conceptual) — the Proxmox bridge vmbr1, VLAN-aware, no IP address; every VLAN is trunked through it. 🔀 SW-CORE (conceptual) the Proxmox bridge vmbr1 802.1Q · VLAN-aware · no IP Red Team to Blue Team direct access: denied both ways and logged. The rule the whole design hangs off. ⛔ Red ↔ Blue no direct traffic, either way: denied both ways and logged THE RULE LAN — The firewall's base internal interface on vtnet1, the 802.1Q trunk into the Proxmox bridge vmbr1, which is VLAN-aware and has no IP address. The seven VLANs from CORP to MGMT are tagged on it. LAN base interface · the 802.1Q trunk 192.168.1.1/24 · vtnet1 CORP — The corporate LAN: Active Directory, DNS and the certificate authority on DC01, plus domain workstations. CORP VLAN 10IDS internal users and directory services 10.10.10.0/24 DC01-AD-DS-CA·AD · DNS · CA PC-CORP2·domain workstation comms01·InspIRCd chat Blue Team / SOC — The Blue Team SOC segment, which receives logs, alerts and detection evidence. Red Team to Blue Team direct access is denied both ways and logged, and GUEST can never reach it. Blue Team / SOC VLAN 20BLUE blue team · detect and respond 10.20.20.0/24 · SOC soc01·Ubuntu VM SIEM-Wazuh·+ EDR agents SYSLOG-ng·log collection RADIUS-FreeRADIUS·AAA via AD MGMT — A locked-down management plane reserved purely for firewall administration during the build. GUEST can never reach it. MGMT VLAN 99LOCKED firewall administration only 10.99.99.0/24 Admin workstation·during build only DMZ — The public-facing DMZ, reachable only per firewall policy and published services, and where the targets of the exercise lived. DMZ VLAN 30IDS public-facing, and the target 172.16.30.0/24 dmz01·Debian VM WEB-Apache·+ Flask app DB-MariaDB·least privilege VM 100·Metasploitable target Red Team / Guest — Red Team operates from VLAN 40 in a controlled, lab-safe manner. Red Team to Blue Team direct access is denied both ways and logged, and GUEST can never reach SOC or MGMT. Red Team / Guest VLAN 40RED · IDS red team · lab-safe only 10.40.40.0/24 · GUEST KALI-RED·attack box WiFi-CORP — Corporate wifi, in the design as its own segment. A design placeholder, with no devices configured. WiFi-CORP VLAN 50 corporate wifi · placeholder 10.50.50.0/24 · WIFICORP WiFi-Guest — Guest wifi, in the design as its own segment. A design placeholder, with no devices configured. WiFi-Guest VLAN 60 guest wifi · placeholder 10.60.60.0/24 · WIFIGUEST 9 zones, 7 of them VLANs on one 802.1Q trunk · Red ↔ Blue: no direct traffic, denied both ways and logged · click any box for what it does and what changed Click a zone, the firewall, or either corner box. Its panel opens below with what it does, what runs there, and what changed during the project, with links to the pages that cover it. The project also has its own page, with more of the evidence, kept up to date. Click a box on the map. Each panel says what that part of the network does, what runs there, and what changed on it during the project. The URL updates, so a panel can be linked to. ...

4 November 2026 · 16 min

A SOC for the homelab, built in the right order

My homelab keeps growing — more containers, more services, a multi-LLM setup on top. Security is the priority for all of it: guard rails, hooks, and strict policies everywhere, to the point that my main Claude agent is audited by Codex, with Kimi as a third read-only reviewer I invoke manually through the council dashboard. What it didn’t have was a place to see any of that. So: a SOC. A centralised security view for the lab, and a genuinely useful thing to have built. ...

6 September 2026 · 10 min
Grafana Explore showing pfSense firewall logs flowing through Loki, with a log-volume chart above

Building a Homelab SIEM with Loki — Reading My Logs Instead of Hoping

I had dashboards showing me numbers — CPU, memory, network throughput. What I didn’t have was any way to answer “what actually happened?” When did someone try to log in? What did the firewall block? Those answers live in logs, and my logs were scattered across machines, unread. This post is how I pulled them into one searchable place. That’s a SIEM — Security Information and Event Management — and you can build a simple one at home. ...

19 July 2026 · 7 min
Logged into pfSense as an identity-provider account over LDAP

Making the Firewall Authenticate Against My Identity Provider — and Proving the Bug Wasn't Mine

Bringing pfSense’s admin login into Authentik with MFA — via RADIUS, which turned out to be broken upstream, and then via LDAP, which wasn’t. This is as much about how you prove a bug isn’t yours as it is about the build. Stack: Authentik · pfSense · Docker · LDAP · RADIUS 1. Purpose With an identity provider already running and Grafana logging in through it, the obvious next question was: how far does this go? ...

16 July 2026 · 13 min
The self-hosted Vaultwarden vault, logged in and showing its security reports

Self-Hosting a Password Manager the Hard Way: Vaultwarden, Caddy, and Three Firewalls Fighting

Building a self-hosted password vault with a genuinely trusted TLS certificate and zero inbound ports open to the internet — and the four-layer debugging session that stood between me and a working container. Stack: Debian 13 · Docker · Caddy (custom build) · Vaultwarden · pfSense · WireGuard · DuckDNS 1. Purpose Self-hosted services are easy to do badly. It’s trivial to run a container, forward a port, click through a certificate warning, and call it done — and end up with something less secure than the cloud service you replaced. ...

15 July 2026 · 11 min
All three VLAN interfaces online at their gateway IPs on pfSense

Virtual VLAN Segmentation on pfSense — Three Isolated Zones, No Managed Switch

A flat network trusts every device on it equally. A smart plug, a guest’s phone, and the machine holding my important data all share one space — so if any one of them is compromised, the attacker can reach the rest. Network segmentation breaks that flat space into separate zones and controls what may cross between them, shrinking the blast radius of any single compromise. I wanted to build that properly — VLANs and a firewall — on VMware Workstation with pfSense CE, and design three zones at deliberately different trust levels: ...

12 July 2026 · 8 min
WireGuard handshake established over mobile data

Self-Hosted WireGuard Through a Nested Firewall — and the Four-Layer Debug to Make It Work

My lab is deliberately isolated — an automation VM (CLAUDDEB) sits behind a virtual pfSense firewall on a segment (10.10.0.0/24) that my home network can’t reach. That isolation is great until you’re out of the house and want to check your Grafana dashboards, which only listen inside that segment. I already use Tailscale for casual remote access, and I’ll be honest up front: for pure convenience, Tailscale wins — it punches through NAT automatically with zero firewall work. But this project wasn’t about convenience. It was about building the thing Tailscale is made of. Tailscale is WireGuard under the hood; hand-rolling raw WireGuard on pfSense teaches you how VPNs actually work — keys, peers, routing, firewall rules, NAT — at a level the managed tool deliberately hides. So I built it from scratch, kept Tailscale as my daily driver, and got a genuinely brutal debugging lesson in the process. ...

11 July 2026 · 7 min
Grafana Node Exporter dashboard for the Debian VM

Building a Prometheus and Grafana Observability Stack for My Home Lab

My LaMetric display gives an at-a-glance read on the lab, but it’s a spot reading with no history — good for “is something on fire right now,” useless for “what happened overnight.” This project adds the layer underneath: a Prometheus + Grafana stack that scrapes my hosts continuously, stores the history, and draws real dashboards. Two targets: CLAUDDEB (my Debian automation VM) and my pfSense firewall, reusing the exact SNMP setup from the pfSense post — just pointed at something far more capable than a 37-pixel display. ...

6 July 2026 · 6 min
pfSense WAN byte counter climbing under SNMP polling

Implementing LaMetric TIME to Network Part 2

In part 1 I got a LaMetric Time showing live health from my home lab over MQTT, so it worked across my network isolation — CPU, memory, disk, uptime, and the automation VM’s own traffic, all from a single Debian box. Useful, but those were really that box’s stats. The frame the display was named for is my network’s throughput — the traffic crossing my firewall — and that data lives on pfSense, not the Debian box. This is the follow-up: pulling real WAN in/out rates off pfSense over SNMP and putting them on the display. It’s shorter than the MQTT build, because the pipeline already exists; all I’m adding is a new data source. Getting numbers out of pfSense is the part worth writing down. ...

6 July 2026 · 8 min
A LaMetric Time smart display

Implementing LaMetric TIME to Network

I picked up a LaMetric Time — an 8x37 pixel smart display — and after locking it down on an isolated guest network, the next move was to make it useful: live health from my home lab. CPU, memory, network throughput — the numbers worth a glance. The interesting part is that a constraint I’d deliberately built into my network dictated the whole architecture. This is the write-up: the design decision, the pipeline, and the gotchas — because the gotchas are the useful part. ...

5 July 2026 · 7 min
pfSense dashboard after the rebuild

Debugging a Dead VMware NAT and Hardening My pfSense Containment Lab

I run my Claude Code work inside a Debian 13 VM (CLAUDDEB) on VMware Workstation Pro 17.6.4, with a pfSense 2.8.1 VM in front of it as a virtual router and firewall. pfSense exists in this setup for containment: if something on the Debian VM misbehaves — a prompt injection, a compromised dependency — it must not be able to reach my PC, my router’s admin page, or anything else on the home network. ...

2 July 2026 · 7 min