DEEP DIVE · PROJECT

SOC Home Lab

How I built a functional SOC on Proxmox VMs to practice detection engineering for AD environments. From problem to implementation, with real Sigma rules and what didn’t work.

// ~6 months of iteration // Proxmox · 8 VMs · 32 GB RAM // research environment only // last updated 2026-05-07

Problem

AD threat hunting requires practice in an environment where you control both attacker and defender. Commercial labs are expensive and rigid; blog-post screenshots are shallow.

I wanted somewhere I could: run a real Kerberoast, watch Event 4769 arrive in Wazuh, write the Sigma rule, validate against false positives, and measure end-to-end MTTD. Fully isolated from my home network, zero recurring cost, and — critically — zero dependency on client data. Everything synthetic, everything fictional, everything RFC5737.

You don’t learn detection engineering by reading blog posts. You learn by watching the detection fail three times and figuring out why.

Architecture

A Proxmox host runs 8 VMs: a full AD domain (DC + workstations), pfSense firewall with Suricata, Wazuh manager + OpenSearch, and a Kali VM for the attacker. All traffic traverses pfSense to guarantee network visibility.

Kali (attacker) 192.0.2.10 pfSense + Suricata IDS // AD zone — 198.51.100.0/24 DC01-LAB DC02-LAB WKSTN-01..04 Sysmon + WEF Wazuh manager OpenSearch Sigma rules (git) Dashboards · Hunts 203.0.113.5 (read-only)

// RFC5737 IPs · fictional hostnames · zero reference to real infrastructure

Implementation

Stack chosen for zero cost and extensibility — each component can be swapped for its corporate equivalent without rewriting rules.

HypervisorProxmox VE 8
Domain ControllersWindows Server 2022
WorkstationsWindows 11 Pro
Firewall · IDSpfSense + Suricata
SIEM · managerWazuh 4.7
Search · storageOpenSearch 2.11
Endpoint telemetrySysmon + WEF
Attacker toolkitKali · Impacket · Rubeus

Sigma rules live in a public Git repo. CI converts YAML Sigma → Wazuh rules via sigma-cli. Each PR runs unit tests against synthetic logs before merging.

Detections

Five notable detections. Each one started by reproducing a real attack with public tooling, capturing the raw events, and writing the rule from scratch.

T1558.003 — Kerberoastingseverity: high
# TGS request with RC4 encryption for a service account
title: Suspicious TGS Request (Kerberoasting)
id: a7f4b8c1-9d2e-4c9f-8a1b-3e5d7f9a2c4d
status: stable
logsource:
  product: windows
  service: security
detection:
  selection:
    EventID: 4769
    TicketEncryption: '0x17'
    ServiceName|endswith: '$'
  condition: selection
level: high
tags: [attack.credential_access, attack.t1558.003]
T1003.006 — DCSyncseverity: critical
# Directory replication rights used from non-DC host
title: DCSync via Replication Rights
logsource: { product: windows, service: security }
detection:
  selection:
    EventID: 4662
    Properties|contains:
      - '1131f6aa-9c07-11d1-f79f-00c04fc2dcd2'  # DS-Replication-Get-Changes
      - '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2'  # DS-Replication-Get-Changes-All
  filter_dc:
    SubjectUserName|endswith: '$'
  condition: selection and not filter_dc
level: critical
tags: [attack.credential_access, attack.t1003.006]
T1558.004 — AS-REP Roastingseverity: high

Users with "Do not require preauth" enabled. Detection via Event 4768 without PreAuth type.

T1059.001 — PS encodedseverity: medium

PowerShell -EncodedCommand with long base64. Sysmon Event 1, high entropy on the commandline.

T1110.001 — SSH bruteseverity: medium

pfSense logs: ≥20 SSH failures in 60s from the same IP. Automatic response: block via pfBlockerNG.

sigma-cli → Wazuhpipeline

CI converts YAML Sigma into Wazuh local_rules.xml. PR → test → merge → deploy via Ansible.

Metrics

Lab metrics over the last 30 days. Research environment — not comparable to a corporate SOC (volume, endpoint variety, attacker skill are all constrained).

Sigma rules

52
+4 this month

Events/day

340K
rolling 7d

MTTD

6m 48s
−22% vs baseline

TTPs covered

37
MITRE ATT&CK

False positive rate

3.2%
rolling 30d

Hunts executed

18
playbook-driven

Rules tested

100%
pre-merge CI

Uptime

99.4%
manager + search

Lessons learned

What worked — and what didn’t. Honestly.

  • Worked: versioning Sigma rules in Git with CI. A rule without tests becomes a false positive in production.
  • Worked: isolating the attack zone in its own pfSense VLAN. Prevents Rubeus from leaking to the home network.
  • Didn’t work (v1): trying to build endpoint telemetry without Sysmon. Native Windows event log is insufficient — Sysmon is only negotiable in environments with paid EDR.
  • Didn’t work (v1): Wazuh agent in "full events" mode — OpenSearch choked at >500k events/day. Fixed by filtering at source via Wazuh ruleset.
  • Lesson: detection engineering is 20% writing rules, 80% FP triage. My first Kerberoast rule broke on any AD backup — a backup-machine filter fixed it.
  • Lesson: write the rule after running the attack, not before. ATT&CK docs are a starting point, not a finish line.