Welcome to RogueOps: My SOC Learning Journey ๐๐
Welcome to RogueOps, my personal Security Operations Center (SOC) learning journal. This site documents my hands-on journey into cybersecurity, where I explore threat hunting, incident response, and SOC toolsโall curated to sharpen my skills and share knowledge.
Current Focus
I have reviewed several SOC analyst job descriptions and identified the key technical skills employers are seeking. My goal is to gain hands-on experience with these skills and document my learning process thoroughly.
Why RogueOps?
- To organize and track my growth as a SOC analyst.
- To demonstrate my technical expertise for recruiters and industry peers.
- To create engaging content that helps me connect and build my presence on LinkedIn and beyond.
What You'll Find Here
- In-depth notes and practical exercises on real-world SOC topics.
- Step-by-step guides for popular SOC tools and workflows.
- Clear, easy-to-navigate documentation powered by mdBook.
#0. Overview of the Lab
VMs
- pfSense
- kali
- SecurityOnion
- Windows
- Linux (optional)
Network subnets
Network Name | Machine | Subnet |
---|---|---|
Green | Windows, Linux | 10.10.10.100/24 |
Blue | Security Onion | 10.10.20.100/24 |
Red | Kali | 10.10.30.100/24 |
VPN | Host machine | 10.10.3.2/24 |
System resources
VM | RAM (GB) | CPU Cores | ROM (GB) |
---|---|---|---|
SecurityOnion | 8 | 4 | 90 |
Kali | 2 | 2 | VM image (80) |
Windows LTSC | 2 | 2 | 25 |
pfSense | 1 | 1 | 20 |
My setup
- Host machine OS: ArchCraft
- RAM: 14 Gigs
- Processor: Ryzen 5 (8 cores)
- Hypervisor: virt-manager/KVM
- ROM: 256 SSD
โ ๏ธ Notes from my side
I suggest you to go through the full setup notes before proceeding, it could clear any doubts when setting it up.
Sometimes, all configuration looks good, but things don't work as they should be, just restart the VMs (literally)
I enabled ssh on all VMs for easy troubleshooting.
#1 Networking
Assign these bridges to your VMs
Use the bridge setup script
The order of bridging interfaces doesnโt matter, but hereโs a recommended setup.
-
pfSense VM interfaces:
- WAN โ
NAT
to host machine - LAN โ
br-green
- OPT1 โ
br-blue
- OPT2 โ
br-red
- OPT3 โ
VPN
- OPT4 โ
br-mon
(SPAN port)
- WAN โ
Configure pfSense
- DHCP : To assign IPs automatically to the connected VMs
- OpenVPN : To access VMs without NAT-ing to host machine.
- DNS
- Firewall : To allow VPN clients
Interfaces
- OPT5, OPT3 are assigned but not enabled.
Example
- I chose same mac address as Network port above in configuring GREEN interface
Configure Mirroring/SPAN port on pfSense
- Rename one of the interfaces as Mirror and connect it to bridge
br-mon
. - We're using pfSense to perform software-based port mirroring (SPAN), duplicating traffic from specific interfaces (GREEN) to a monitoring interface (OPT4 โ br-mon) for analysis.
- Go to : Interfaces โ Bridges.
- Click on Advanced Options.
Firewall Rules
- I gave VPN access to all subnets, so I can ssh and troubleshoot easily.
GREEN
BLUE
RED
Mirror
VPN
- When setting up your VPN make sure you have a setting to access internal network subnets. Configure it in VPN servers.
- Go to : VPN โ OpenVPN โ Servers
#2 Security Onion
- There are a few caveats to be addressed in our setup.
- Make sure you have network mirroring working.
Iptables
- This one took me literally 2 days, I think, to get it right, because I tried messing with iptables manually from cli. It was a pain.
- Stop iptables:
sudo systemctl stop iptables
- Now you can access the soc platform on the host machine:
10.10.20.100
(I also reserved static ip on the pfsense via DHCP Static Mappings) - Follow this guide: https://docs.securityonion.net/en/2.4/firewall.html#configuring-host-firewall
- For some reason after starting iptables, if you still don't access, restart the VM.
Test suricata alert
- Create ICMP test alert
- ping from a red machine to green machine. It can take few mins before it shows up in alerts.
ping -c4 -4 10.10.10.100 # from kali
#3 Scripts to make life easy
I have these script in ~/.custom-scripts-bin
. I also added that path to $PATH
in .zshrc
- pfsense_vm : start pfsense vm from cli
- setup_bridges_soc : creates and runs bridges
- kali_vm : start kali vm from cli
- SecurityOnion : runs setup_bridges_soc, pfsense_vm, start securityonion from cli
- connect_VPN : simple script to connect to vpn
setup_bridges_soc
#!/bin/bash
# List of bridge names
BRIDGES=("br-green" "br-blue" "br-red" "br-mon")
for BR in "${BRIDGES[@]}"; do
# Check if bridge already exists
if ip link show "$BR" &>/dev/null; then
echo " $BR already exists, skipping."
continue
fi
# Create the bridge
sudo ip link add name "$BR" type bridge
# Bring the bridge up
sudo ip link set "$BR" up
done
kali_vm
- vm name should be
kali
#!/usr/bin/bash
virsh --connect qemu:///system start kali
pfsense_vm
- vm name should be
pfsense
#!/usr/bin/bash
setup_bridges_soc
virsh --connect qemu:///system start pfSense
SecurityOnion
- vm name should be
SecurityOnion
#!/usr/bin/bash
setup_bridges_soc
pfsense_vm
virsh --connect qemu:///system start SecurityOnion
PATH
export PATH=$PATH:$HOME/.custom-scripts-bin/
pfSense is an open-source firewall and router software based on FreeBSD. It provides powerful network security features such as stateful packet filtering, VPN support, traffic shaping, and intrusion detection, all accessible through an easy-to-use web interface.
Objectives
- Learn to utilize pfSense to protect internal network.
- Services configuration: DHCP, DNS, SSH, VPN
- Firewall rules
- PFBlockerNG: GeoBlocking, DNSBL
- IDPS: snort testing
Setup
- Download & install
pfSense
on your hypervisor (I use Virt-Manager) from this video or any other but watch videos from 2025: https://www.youtube.com/watch?v=Y-Dj8lHmXy8 - pfSense requires a WAN interface to be configured. The LAN interface can be skipped and configured later.
Access Admin interface from WAN interface
- By default you cannot access admin interface from WAN subnet like from your host machine, for that quickest way is to disable firewall temporarily.
- I ssh-ed here, we will see later how to enable that.
- Command to disable firewall.
pfctl -d
- Then go to that WAN IP of the pfSense on the browser to access it.
Enabling SSH Access
To manage pfSense remotely via SSH, you need to enable and configure the SSH service.
Steps to Enable SSH
-
Log in to the Web GUI
- Default : Username:
admin
, Password:pfsense
- Default : Username:
-
Navigate to SSH Settings
- Go to: System โ Advanced โ Admin Access
- Scroll down to the Secure Shell section
- Check the box: "Enable Secure Shell"
- Scroll all the way and click "Save"
Configure pfSense Firewall to Allow SSH
- Go to: Firewall โ Rules โ WAN
- Click on "Add"
- Do as image suggests and click "Save", change WAN to LAN as per your preference.
- Click on "Apply Changes". Most important one, I was troubleshooting without applying changes for some time :)
- Access via Terminal
- Type your admin password when prompted.
ssh admin@<pfSense-IP>
SSH via Key
If you want to configure ssh key then follow this, mind you, you still need to enable SSH in firewall as shown above. Video suggested: https://www.youtube.com/watch?v=oakOE2iDkhU
Create SSH keys in Linux
ssh-keygen -t ed25519 -C "admin@pfSense.local"
Configure pfSense with SSH key
- Go to: 1. System โ User Manager โ Users
- Click on "Pencil" icon
- Scroll down to : Keys
- Paste your Public Key here
Access via terminal
ssh -i .ssh/id_ed25519 admin@$IP
DHCP Configuration
- Go to: Services โ DHCP Server
- Choose which interface you want to configure DHCP, below image is showing LAN config.
- Specify Address Pool Range excluding the IP which the pfSense configured on.
- Scroll down and click "Save".
- You can check DHCP leases here: Status โ DHCP Leases
DNS
Set DNS Servers
- Go to: System > General Setup
- Scroll to the DNS Server Settings section.
- Enter your preferred DNS servers (
1.1.1.1
,8.8.8.8
). - Also change DNS Resolution Behaivor as you need.
- Default: Uses local DNS server on the pfSense and fallback to remote servers.
- Check the box "Allow DNS server list to be overridden by DHCP/PPP on WAN ..." if you want WAN-provided DNS. Otherwise, uncheck it to use your own configured DNS servers.
- Click Save.
DNS Forwarderยถ
- The DNS Forwarder in pfSenseยฎ software utilizes the
dnsmasq
daemon, which is a caching DNS forwarder. - Unlike the DNS Resolver, the DNS Forwarder can only act in a forwarding role as it does not support acting as a resolver.
- The DNS Forwarder uses DNS Servers configured at System > General Setup and those obtained automatically from an ISP for dynamically configured WAN interfaces (DHCP, PPPoE, etc).
- This service is disabled by default. The DNS Resolver (
unbound
) is the default DNS service. - Use DNS Resolver -- it supports both forwarding and resolving.
DNS Resolverยถ
The DNS Resolver in pfSenseยฎ software utilizes unbound
, which is a validating, recursive, caching DNS resolver that supports DNSSEC, DNS over TLS, and a wide variety of options. It can act in either a DNS resolver or forwarder role.
- Go to: Services โ DNS Resolver โ General Settings
- Enable options are seen in the below image.
- Enable SSL/TLS for encrypted DNS queries from local clients like LAN.
- Use appropriate Outgoing Network Interfaces like WAN to resolve DNS quires rather than sending request to all the interfaces.
- Imagine Unbound (not restricted) sends a DNS query out through LAN, where clients also use pfSense as their DNS.
- The request could circle back into Unbound โ a loop.
- This can cause: Timeouts, Failed resolutions, High CPU usage
- Sending DNS out through the organization's
GUEST
network (public Wi-Fi) could:- Leak DNS into untrusted networks
- Be sniffed or redirected
- Allow MITM attacks if DNSSEC isnโt used
- Imagine Unbound (not restricted) sends a DNS query out through LAN, where clients also use pfSense as their DNS.
DNS over TLS (DoT)
- DoT requires Forwarding Mode and SSL/TLS outgoing enabled on DNS Resolver.
pfSense (Unbound) encrypts DNS queries to an upstream DNS provider like Cloudflare, Google, or Quad9 โ over port 853.
- But Unbound's native recursive resolution (non-forwarding mode) means:
pfSense contacts root DNS servers directly (e.g:
.
,.com
,google.com
servers) โ and they do not support DNS over TLS.
DNS over HTTPS (DoH)
- DNS over HTTPS (DoH) is a protocol that encrypts DNS queries using HTTPS (port 443) instead of plain DNS (port 53) or DNS over TLS (DoT).
- pfSense does not natively support DoH in the DNS Resolver (Unbound) or DNS Forwarder (dnsmasq).
- To use DoH on pfSense, you need to run a local DoH proxy that talks to an upstream DoH provider (like Cloudflare or Google).
Domain Name System Security Extensions (DNSSEC)
DNSSEC adds authentication to DNS. It does not encrypt DNS queries (like DoT or DoH) โ instead, it ensures that the DNS response:
- โ Was not tampered with
- โ Came from the legitimate DNS source
- โ Does not provide privacy
How it works
- DNS records are digitally signed by domain owners.
- DNS resolvers (like pfSenseโs Unbound) validate the signature.
- If the signature is invalid or missing, the DNS query fails, protecting you from forged or poisoned responses. Prevents spoofing.
Testing configurations
Testing DNSSEC
- Run this command from one of the LAN machines set up with pfSense.
10.10.10.1
- is my pfSense LAN IP/interface.
dig @10.10.10.1 +dnssec dnssec-failed.org
- Output should be like this. Notice
status: SERVFAIL
. - Check with a domain that has DNSSEC enabled like: cloudflare.com
; <<>> DiG 9.18.37 <<>> dnssec-failed.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 3270
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1432
;; QUESTION SECTION:
;dnssec-failed.org. IN A
;; Query time: 2520 msec
;; SERVER: 10.10.10.1#53(10.10.10.1) (UDP)
;; WHEN: Fri May 23 11:37:55 IST 2025
;; MSG SIZE rcvd: 46
Testing DoT ยถ
From the docs: ยถ
DNSSEC is not generally compatible with forwarding mode, with or without DNS over TLS.
- Change DNS Resolution Behavior to "Use local DNS, fallback to DNS Servers". This seems to work in my rigorous testing.
- Test via Diagnostics โ DNS Lookup
- Check for states using port
853
going in Diagnostics โ States โ States - Refer to the image below, you should be good.
PFBlockerNG: GeoBlocking, DNSBL
How does it work
IP-Based Blocking
- Downloads lists of IP addresses known for malicious activity (malware, bots, spam, etc.), or from specific countries (GeoIP).
- Creates aliases (groups of IPs).
- Uses pfSense firewall rules to block or reject traffic to/from those IPs.
DNSBL
- Runs a local DNS resolver with unbound (built into pfSense).
- Intercepts DNS queries for known ad/tracker/malware domains.
- Returns a fake IP (like 10.10.2.1, the IP you configured for Virtual IP) instead of the real IP.
- This "blackholes" the domain โ no connection can be made.
- Example
- our device asks: โWhatโs the IP of
ads.evilsite.com
?โ - pfBlockerNG responds: โIt's
10.10.10.1
.โ (a dead end) - So the ad never loads, and no malicious content gets through.
- our device asks: โWhatโs the IP of
Configuration
DNSBL (DNS Blackhole List โ blocks ads, malware, trackers)
- Go to : Firewall โ pfBlockerNG โ DNSBL
- Check Enable DNSBL.
- Set Listen Interfaces for outbound and inbound on PFBlockerNG โ IP : IP Interface/Rules Configuration section
- Check Permit Firewall Rules (to auto-create rules to access DNSBL Webserver (block page).).
- Global Logging/Blocking Mode:
- No Global mode: Logging & blocking depends per
block list
settings - DNSBL mode: Domains are sinkholed to the DNSBL VIP(Virtual IP) and logged.
- Null blocking (no logging): '0.0.0.0' will be used instead of the DNSBL VIP and not logged.
- No Global mode: Logging & blocking depends per
- Save settings and reload in Update tab.
IP Blocking
- Go to : pfBlockerNG โ IP
- ASN Configuration: Enable ASN Reporting for ASN of the logged IP and populate ASN IPinfo Token with it's token.
- MaxMind GeoIP configuration: Populate its fields for GeoBlocking
- Kill States: After each update, this removes any active connections involving blocked IPs.
GeoBlocking Video suggested: https://www.youtube.com/watch?v=q1X0K-wzlTg&t=106s
- Go to : IP โ GeoIP
- Configure action of the preferred continent.
- Click pencil icon on one of the listed continent like: Asia.
- Select countries with
ctrl + click
. Example: China, Pakistan, Turkiye. - Configure the List Action, and "Save" and reload.
Here pakistan.gov.pk website is blocked.
โ ๏ธ Note: Requires MaxMind GeoIP key (free with account).
Threat Intel Feeds
- Go to Feeds tab.
- Check feeds like:
easylist
,adaway
,malwaredomains
, etc.
- Click plus icon to add, then go to Update tab and run Force Reload - All
- ping/curl an IP from one of the IPs from feeds that are active.
- And check alerts generated in Reports โ Alerts
- We can see ASN info as well that I configured in pfBlockerNG โ IP with https://ipinfo.io/ API.
VPN: OpenVPN
Video suggested: https://www.youtube.com/watch?v=I61t7aoGC2Q&t=148s
We need to configure these: Certificate Authority to sign certificates, Server Certificate (used by OpenVPN) to prove its identity, and the client certificate. It's better to view walk-through videos to configure these than step by step instructions.
๐ How OpenVPN Works
- Startup
- Server starts and listens on port 1194.
- Client starts and connects to server.
- (Optional) TLS Auth Check
- Before any TLS handshake is accepted, server checks HMAC on packet using
ta.key
.
- Before any TLS handshake is accepted, server checks HMAC on packet using
- TLS Handshake
- Client and server exchange certificates.
- Each verifies the other's certificate via the CA.
- TLS keys are negotiated.
- Key Exchange
- A secure session is established using TLS with DH or ECDH.
- A shared symmetric key is derived for encryption.
- VPN Tunnel Created
- A virtual interface (
tun0
) is created on both ends. - All traffic is encrypted and routed through this interface.
- A virtual interface (
- Data Encryption
- All traffic between client and server is encrypted with the symmetric key.
- Client Receives IP
- Server assigns an internal VPN IP to the client (e.g., 10.10.3.2).
- Client can access internal services or route internet traffic via VPN.
OpenVPN Client Export Utility
- Install this from Syatem โ Package Manager โ Available Packages โ Search for
openvpn-client-export
- Configure Host Name Resolution to public IP for remote access over public network.
- Create a VPN user here: System โ User Manager โ Users
- Add user certificate: Create Certificate for User section. And "Save".
- Go to: VPN โ OpenVPN โ Client Export Utility
- The user you created should be visible here. Export the desired option.
The exported .ovpn
config includes:
- The client certificate
- The client private key
- The CA certificate (so the client can verify the server)
- Optionally, the TLS key (if used)
Test VPN
- Image should be self explanatory.
Security Tips
- Use 4096-bit keys for long-term security
- Disable compression (can lead to VORACLE attacks)
- Use TLS-Crypt instead of TLS-Auth for additional privacy
- Restrict users with firewall rules or user groups
IDPS: Snort
Video suggested: https://www.youtube.com/watch?v=SapAcfHbQSE&t=192s
Test snort
- Custom rule
alert tcp any any -> any 80 (msg:"TEST ALERT - Visit to example.com"; content:"example.com"; http_header; sid:1000001; rev:1;)
- curl from one of the LAN machines:
curl http://example.com
- Go to: Services โ Snort โ Alerts
Video suggested: elastic agent
Download Elastic Agent on Windows
- Download the elastic agent from securityOnion to host machine.
pipx install uploadserver
uploadserver
- Go to your python server on Edge
10.10.3.2:8000
and download file to windows. - Run the executable as administrator.
Firewall config
- To enable Elastic agent to send logs, please add your subnet to the allowed lists here.
elasticsearch_rest
- rest API endpoint running on port9200
. (We are directly sends logs to elastic search, skippinglogstash
)
Verify
- Go to: Kibana โ Analytics โ Discover
- Add
agent.name
andprocess.name
to Selected Fields
โ ๏ธ Note
Make sure your windows can resolve the SecurityOnion host name. Check with
elastic-agent status
to view any errors.elastic-agent
- should be inC:\Program Files\elastic\agent\
Edit hosts file in windows to include:10.10.20.100 soc-server
.soc-server
is your SecurityOnion host name.
UseCases
#1 Failed Logon Attempts
Create few user accounts
- Run this PS script on the windows
$users = @(
@{Name="IronMan"; Password="Stark@123"},
@{Name="CaptainAmerica"; Password="Shield@123"},
@{Name="Thor"; Password="Mjolnir@123"},
@{Name="Hulk"; Password="Smash@123"},
@{Name="BlackWidow"; Password="Spy@123"}
)
foreach ($user in $users) {
$name = $user.Name
$password = $user.Password
# Create user with net user command, password & no password change at next login
net user $name $password /add /expires:never /passwordchg:no /fullname:"$name"
Write-Host "Created user: $name"
}
Simulate Failed Logins
- We are using SMB here, it is enabled by default.
- I ran this script from my host machine, you can do it from attacker machine as well.
- Check with windows firewall for any network issues, I currently disabled it.
TARGET="10.10.10.103"
WRONG_PASS="WrongPassword123"
USERS=("BlackWidow" "CaptainAmerica" "Hulk" "IronMan" "Thor")
for user in "${USERS[@]}"; do
echo -e "\n[*] Trying $user..."
smbclient -L "//$TARGET/C$" -U "$user%$WRONG_PASS" -m SMB3 -d 1 2>&1
sleep 1
done
[*] Trying BlackWidow...
Can't load /etc/samba/smb.conf - run testparm to debug it
session setup failed: NT_STATUS_LOGON_FAILURE
[*] Trying CaptainAmerica...
Can't load /etc/samba/smb.conf - run testparm to debug it
session setup failed: NT_STATUS_LOGON_FAILURE
[*] Trying Hulk...
Can't load /etc/samba/smb.conf - run testparm to debug it
session setup failed: NT_STATUS_LOGON_FAILURE
[*] Trying IronMan...
Can't load /etc/samba/smb.conf - run testparm to debug it
session setup failed: NT_STATUS_LOGON_FAILURE
[*] Trying Thor...
Can't load /etc/samba/smb.conf - run testparm to debug it
session setup failed: NT_STATUS_LOGON_FAILURE
Verify failed logins logs using PowerShell
# Generated by ChatGPT :) - After few tries ofc
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4625} | ForEach-Object {
$evt = $_
$username = $evt.Properties[5].Value
# Search all properties for an IPv4 address pattern
$ip = ($evt.Properties | ForEach-Object { $_.Value }) `
| Where-Object { $_ -match '\b(?:\d{1,3}\.){3}\d{1,3}\b' } `
| Select-Object -First 1
if (-not $ip) { $ip = "N/A" }
$time = $evt.TimeCreated
[PSCustomObject]@{
TimeCreated = $time
Username = $username
SourceIP = $ip
}
} | Sort-Object TimeCreated -Descending | Format-Table -AutoSize
TimeCreated Username SourceIP
----------- -------- --------
6/9/2025 5:10:20 PM Thor 10.10.3.2
6/9/2025 5:10:19 PM IronMan 10.10.3.2
6/9/2025 5:10:18 PM Hulk 10.10.3.2
6/9/2025 5:10:17 PM CaptainAmerica 10.10.3.2
6/9/2025 5:10:15 PM BlackWidow 10.10.3.2
6/9/2025 5:09:57 PM Thor 10.10.3.2
6/9/2025 5:09:56 PM IronMan 10.10.3.2
6/9/2025 5:09:55 PM Hulk 10.10.3.2
6/9/2025 5:09:53 PM CaptainAmerica 10.10.3.2
6/9/2025 5:06:09 PM Thor 10.10.3.2
6/9/2025 5:01:12 PM marry 127.0.0.1
6/9/2025 5:01:04 PM marry 127.0.0.1
6/9/2025 1:29:41 PM marry 127.0.0.1
Kibana Visualization
event.code: "4625"
- Failed logons.