A complete hands-on walkthrough of building a real Security Operations Center at home, covering attack simulation, log monitoring, threat detection, incident response, and automated defense.
- Introduction
- Architecture Overview
- Technologies Used
- Part 1 Deploying Wazuh SIEM
- Part 2 Connecting Endpoints
- Part 3 ELK Stack with Docker
- Part 4 Shipping Logs with Filebeat
- Part 5 Kibana Dashboards
- Part 6 Simulating Real-World Attacks
- Part 7 Automated Defense with Fail2Ban
- Part 8 Vulnerability Detection
- Part 9 TheHive for Incident Response
- Key Lessons Learned
- What's Next
Most cybersecurity tutorials show you how to use one tool in isolation. But in a real Security Operations Center, everything works together: agents collecting logs, a SIEM aggregating and correlating them, dashboards visualizing threats, analysts investigating cases, and automated defenses responding in real time.
In this project, I built a complete home SOC lab that simulates both offensive and defensive security operations. The primary goal was to create a realistic environment where I could generate attacks, monitor them in real time, investigate alerts, manage incidents, and automate responses using industry-standard tools.
This isn't just a tutorial, it's a documentation of every decision, failure, and fix I encountered along the way.
The environment consisted of four virtual machines running inside VMware Workstation, all on the same internal network.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HOME SOC LAB β
β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββββββ β
β β Kali Linux β β Windows 10 β β Ubuntu VM 1 β β
β β (Attacker + β β (Endpoint + β β Wazuh Manager + β β
β β Agent) β β Winlogbeat) β β TheHive β β
β ββββββββ¬ββββββββ ββββββββ¬ββββββββ ββββββββββ¬ββββββββββ β
β β β β β
β ββββββββββββββββββββΌβββββββββββββββββββββββ β
β β logs/alerts β
β βΌ β
β ββββββββββββββββββββ β
β β Ubuntu VM 2 β β
β β ELK Stack β β
β β (Elasticsearch β β
β β Logstash Kibana)β β
β ββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
SOC Data Flow:
Kali Linux (Attacker)
β
βΌ SSH Brute Force / Port Scan
Target Systems (Ubuntu + Windows)
β
βΌ
Wazuh Agents (on each endpoint)
β
βΌ
Wazuh Manager (detection + alerting)
β
βΌ
Filebeat (log forwarding)
β
βΌ
Logstash (enrichment + parsing)
β
βΌ
Elasticsearch (storage + indexing)
β
βΌ
Kibana (visualization + dashboards)
β
βΌ
TheHive (case management + incident response)
| Category | Tool | Version |
|---|---|---|
| SIEM / XDR | Wazuh | 4.9.2 |
| Log Storage | Elasticsearch | 8.13.4 |
| Log Enrichment | Logstash | 8.13.4 |
| Visualization | Kibana | 8.13.4 |
| Log Shipping | Filebeat / Winlogbeat | 8.13.4 |
| Incident Response | TheHive | 5.x |
| Automated Defense | Fail2Ban | Latest |
| Attack Simulation | Hydra, Nmap | Kali Rolling |
| OS (Servers) | Ubuntu | 24.04 LTS |
| OS (Endpoint) | Windows | 10 |
Wazuh was the first component deployed. It serves as the central detection engine, collecting logs, generating alerts, and monitoring vulnerabilities across all connected endpoints.
curl -sO https://packages.wazuh.com/4.9/wazuh-install.sh
curl -sO https://packages.wazuh.com/4.9/config.ymlEdit config.yml with your server IP, then run the all-in-one installer:
sudo bash wazuh-install.sh -aThis installs three components in one go:
- Wazuh Indexer β stores alerts
- Wazuh Manager β processes and correlates logs
- Wazuh Dashboard β web interface
Extract the auto-generated credentials immediately:
sudo tar -O -xvf wazuh-install-files.tar wazuh-install-files/wazuh-passwords.txt
β οΈ Save these credentials right away, you'll need them every time you log in.
Once deployed, the Wazuh dashboard immediately provided endpoint visibility, security alerts, compliance monitoring, vulnerability detection, and MITRE ATT&CK mapping.

The Kali machine served a dual purpose as a security monitoring endpoint and attack simulation platform.
sudo WAZUH_MANAGER='<wazuh-server-ip>' apt install wazuh-agent
sudo rm -f /var/ossec/etc/client.keys
sudo /var/ossec/bin/agent-auth -m <wazuh-server-ip> -A KaliLinux
sudo systemctl enable wazuh-agent
sudo systemctl start wazuh-agentThis allowed monitoring of SSH activity, authentication logs, package installations, command execution, and network events on the Kali machine.
On PowerShell (as Administrator):
Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-4.14.5-1.msi -OutFile wazuh-agent.msi
msiexec.exe /i wazuh-agent.msi /q WAZUH_MANAGER="<wazuh-server-ip>" WAZUH_AGENT_NAME="WindowsPC"
NET START WazuhSvcπ‘ Lesson learned: The Wazuh agent version must be equal to or lower than the manager version. A version mismatch causes registration failures. Always verify compatibility before deploying agents.
While Wazuh provided detection capabilities, a separate ELK stack was deployed for additional log analysis flexibility and custom dashboard creation.
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.13.4
container_name: elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- ES_JAVA_OPTS=-Xms2g -Xmx2g
ports:
- "9200:9200"
networks:
- elk
logstash:
image: docker.elastic.co/logstash/logstash:8.13.4
container_name: logstash
ports:
- "0.0.0.0:5044:5044"
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
depends_on:
- elasticsearch
networks:
- elk
kibana:
image: docker.elastic.co/kibana/kibana:8.13.4
container_name: kibana
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
volumes:
- kibana_data:/usr/share/kibana/data
depends_on:
- elasticsearch
networks:
- elk
networks:
elk:
volumes:
kibana_data:input {
beats {
port => 5044
}
}
filter {
if [event][dataset] == "system.auth" {
if [message] =~ "Failed password" {
mutate {
add_tag => ["ssh_brute_force"]
add_field => { "alert_level" => "HIGH" }
}
}
if [message] =~ "Accepted" {
mutate {
add_tag => ["ssh_success"]
add_field => { "alert_level" => "INFO" }
}
}
}
if [winlog][event_id] == 4625 {
mutate {
add_tag => ["windows_failed_login"]
add_field => { "alert_level" => "HIGH" }
}
}
if [winlog][event_id] == 4624 {
mutate {
add_tag => ["windows_successful_login"]
add_field => { "alert_level" => "INFO" }
}
}
}
output {
elasticsearch {
hosts => ["http://elasticsearch:9200"]
index => "logstash-siem-%{+YYYY.MM.dd}"
}
}
Start the stack:
sudo docker compose up -d
sudo docker ps
Filebeat was installed on the Ubuntu host to forward system logs to Logstash, and Winlogbeat on Windows to forward Windows Event Logs.
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-8.13.4-amd64.deb
sudo dpkg -i filebeat-8.13.4-amd64.deb
sudo filebeat modules enable systemKey configuration in /etc/filebeat/filebeat.yml:
output.logstash:
hosts: ["localhost:5044"]sudo systemctl enable filebeat
sudo systemctl start filebeat
sudo filebeat test outputDownload from:
https://artifacts.elastic.co/downloads/beats/winlogbeat/winlogbeat-8.13.4-windows-x86_64.zip
Extract to C:\Winlogbeat and configure winlogbeat.yml:
winlogbeat.event_logs:
- name: Application
- name: System
- name: Security
output.logstash:
hosts: ["<ubuntu-ip>:5044"]Install and start as a Windows service:
cd C:\Winlogbeat
.\install-service-winlogbeat.ps1
Start-Service winlogbeat
| Panel | Query |
|---|---|
| Failed SSH logins over time | message : "Failed password" |
| Total brute force attempts | message : "Failed password" |
| Successful logins | message : "Accepted" |
| All auth events | event.dataset : "system.auth" |
| Panel | Query |
|---|---|
| Windows failed logins | winlog.event_id : 4625 |
| Successful Windows logins | winlog.event_id : 4624 |
| Total Windows events | winlog.channel : * |
| Event ID breakdown | Table β winlog.event_id |
π‘ Lesson learned: Always build dashboards after confirming data is flowing. Run
curl http://localhost:9200/logstash-siem-*/_countto verify document count before spending time on visualizations.
hydra -l root -P /usr/share/wordlists/rockyou.txt ssh://<ubuntu-ip> -t 4Or using a manual loop:
for i in {1..20}; do ssh -o ConnectTimeout=3 fakeuser@<ubuntu-ip>; doneWithin seconds, the Kibana SSH dashboard lit up with failed login spikes. Watching attack activity appear in real time demonstrates the full power of the logging pipeline.
$passwords = @("password", "123456", "admin", "test", "root")
foreach ($pass in $passwords) {
net use \\<windows-ip>\IPC$ $pass /user:administrator 2>&1
net use \\<windows-ip>\IPC$ /delete 2>&1
}Event ID 4625 records immediately appeared in the Windows Security dashboard.
nmap -sV -p 1-1000 <ubuntu-ip>Wazuh detected the scan and generated alerts visible in both the Wazuh dashboard and Kibana.
Detection is only one side of security. Fail2Ban adds automated response monitoring, auth logs and blocking attacking IPs automatically.
sudo apt install fail2ban -ysudo nano /etc/fail2ban/jail.local[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 3sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Check currently banned IPs
sudo fail2ban-client status sshd
# Watch bans in real time
sudo tail -f /var/log/fail2ban.log
# Manually unban an IP
sudo fail2ban-client set sshd unbanip <ip>When Hydra was run again after Fail2Ban was configured, the attacking IP was banned after just 3 attempts. The Kibana dashboard showed a sharp drop in failed login counts the moment the ban kicked in.
Wazuh has built-in vulnerability assessment. Enable it in /var/ossec/etc/ossec.conf:
<vulnerability-detection>
<enabled>yes</enabled>
<index-status>yes</index-status>
<feed-update-interval>60m</feed-update-interval>
</vulnerability-detection>Restart Wazuh manager:
sudo systemctl restart wazuh-managerThe Vulnerability Detection tab in the Wazuh dashboard began populating with CVEs found on connected agents missing patches, vulnerable packages, and known exploits.
While Wazuh and Kibana identified threats, TheHive was deployed to simulate the workflow of a real SOC analyst because security teams don't investigate alerts directly inside a SIEM. They escalate them into trackable cases.
TheHive is an open source Security Incident Response Platform (SIRP) that provides:
- Case management β track investigations from detection to resolution
- Alert triage β prioritize and assign incoming alerts
- Observable tracking β document IPs, domains, hashes, and other IOCs
- Incident documentation β maintain an audit trail of every action taken
- Investigation workflows β assign tasks to analysts and track progress
TheHive was deployed on the same Ubuntu VM as Wazuh using Docker:
mkdir ~/thehive && cd ~/thehive
nano docker-compose.ymlservices:
thehive:
image: strangebee/thehive:5.3
container_name: thehive
ports:
- "9000:9000"
environment:
- JVM_OPTS=-Xms1g -Xmx1g
volumes:
- thehive_data:/opt/thp/thehive/db
- thehive_index:/opt/thp/thehive/index
- thehive_attachments:/opt/thp/thehive/attachments
volumes:
thehive_data:
thehive_index:
thehive_attachments:sudo docker compose up -dAccess TheHive at: http://<server-ip>:9000
Default credentials: admin@thehive.local / secret
The complete workflow from attack to resolution:
1. Attack Generated (Hydra SSH brute force from Kali)
β
βΌ
2. Wazuh Detection (alert generated for excessive failed logins)
β
βΌ
3. Kibana Visualization (spike visible on SSH dashboard)
β
βΌ
4. TheHive Case Created (analyst creates incident case)
β
βΌ
5. Observables Added (attacker IP, username, timestamp documented)
β
βΌ
6. Investigation (log review, timeline reconstruction)
β
βΌ
7. Containment (Fail2Ban ban confirmed, IP blocked)
β
βΌ
8. Case Closed (resolution documented, lessons noted)
- Log in to TheHive at
http://<server-ip>:9000 - Click New Case
- Fill in:
- Title:
SSH Brute Force Attack β Kali Linux - Severity: High
- TLP: Amber
- Description: Detected mass failed SSH logins from
192.168.100.34
- Title:
- Add Observables:
- Type: IP Address β
192.168.100.34(attacker IP) - Type: Username β
fakeuser(targeted account)
- Type: IP Address β
- Add Tasks:
- Investigate source IP
- Review auth.log timeline
- Confirm Fail2Ban ban
- Document IOCs
- Close case
This workflow mirrors exactly what a Tier 1 SOC analyst does when triaging a brute force alert which makes it one of the most valuable parts of the lab for interview demonstrations.
1. Detection is only part of the process Generating alerts is easy. Building an environment capable of collecting, correlating, investigating, and responding to those alerts is far more valuable and far closer to what real SOC work looks like.
2. Version compatibility matters Wazuh agent version must be equal to or lower than the manager version. A mismatch causes silent registration failures. Always check compatibility before deploying.
3. Map your data pipeline first Understanding exactly where logs flow which index they land in, what field names they use determines everything else: your KQL queries, your dashboards, your alerts. Spend time mapping this before building anything.
4. Fail2Ban is underrated Simple, lightweight, and brutally effective. A 3-attempt threshold stops most automated brute force tools instantly. Seeing it kick in during a live Hydra attack is deeply satisfying.
5. Separate your dashboards by data source
Windows logs and Linux logs have completely different field structures. Mixing them in one dashboard creates confusion. Separate by index (logstash-siem-* for Windows, wazuh-alerts-* for Wazuh) and build targeted dashboards.
6. TheHive bridges detection and response Without a structured response process, alerts become noise. TheHive forces you to think like an analyst β triage, assign, investigate, contain, document, close.
Planned enhancements for the lab:
- π Slack/email alerting β Kibana rules that notify when attack thresholds are hit
- πΊοΈ GeoIP enrichment β map attacker IPs to geographic locations
- π€ Shuffle SOAR β automate TheHive case creation when Wazuh fires alerts
- πͺ Active Directory monitoring β add a Windows Server DC for AD log analysis
- π Sigma rules β standardized detection rules mapped to MITRE ATT&CK
- π§ Cortex integration β automated observable analysis within TheHive
- π Threat intelligence feeds β enrich IOCs with external threat data
soc-lab/
βββ elk-stack/
β βββ docker-compose.yml
β βββ logstash.conf
βββ thehive/
β βββ docker-compose.yml
βββ images/
βββ architecture.png
βββ kibana-dashboard.png
βββ wazuh-alerts.png
βββ thehive-case.png
βββ fail2ban-ban.png
| Tool | Version | Purpose |
|---|---|---|
| Ubuntu | 24.04 LTS | Server OS |
| Windows | 10 | Endpoint |
| Kali Linux | Rolling | Attacker |
| Wazuh | 4.9.2 | SIEM/XDR |
| Elasticsearch | 8.13.4 | Log storage |
| Logstash | 8.13.4 | Log enrichment |
| Kibana | 8.13.4 | Visualization |
| Filebeat | 8.13.4 | Linux log shipping |
| Winlogbeat | 8.13.4 | Windows log shipping |
| TheHive | 5.x | Incident response |
| Fail2Ban | Latest | Automated defense |
| Hydra | Kali built-in | Attack simulation |
| Nmap | Kali built-in | Port scanning |
| Docker | 24.x | Container platform |
This project was built entirely in an isolated lab environment for educational purposes. All attack simulations were performed on virtual machines owned and controlled by the author. Never run brute-force tools, port scanners, or attack simulations against systems you do not own or have explicit written permission to test.
This project transformed a collection of security tools into a fully functioning SOC laboratory. By combining Wazuh, ELK Stack, Kibana, TheHive, Fail2Ban, and attack simulation tools, I created an environment capable of monitoring endpoints, detecting threats, visualizing attacks, managing incidents, and automating defensive actions.
More importantly, the project provided practical experience with the complete security operations lifecycle from log generation to incident response.
Two things this project has taught me are to be patient and that the best way to learn cybersecurity is to build, break, troubleshoot, and improve your own environments. Every installation issue, failed integration, and alert investigated becomes another lesson that strengthens your understanding of how security operations actually work.
If this helped you, consider starring the repo β and following for more SOC lab content.
Built with: Wazuh 4.9.2 | ELK Stack 8.13.4 | TheHive 5.x | Kali Linux | Windows 10 | Ubuntu 24.04