Post

Adding an OPNsense Firewall to My Homelab (and Sending Logs to Wazuh)

Adding an OPNsense Firewall to My Homelab (and Sending Logs to Wazuh)

Note: This setup was originally built on Unraid, I’ve since migrated my homelab to Proxmox, but the concepts still apply.

Why I Added a Firewall to My Homelab

My homelab had already grown into a pretty capable security environment:

  • Unraid server hosting containers and VMs
  • Wazuh SIEM running on a Raspberry Pi
  • multiple Windows and Linux test machines
  • attack simulation tools like Nmap and Hydra

But something was missing.

I didn’t have network visibility.

Endpoint logs are useful, but a firewall shows an entirely different side of the story:

  • who is scanning your network
  • what ports attackers are targeting
  • what traffic is being blocked
  • suspicious outbound connections

So I decided to add a dedicated firewall to the lab and feed its logs directly into my SIEM.


Installing OPNsense on Unraid

I deployed OPNsense as a virtual machine inside Unraid.

First I downloaded the OPNsense installer ISO from the official site.

Then I created a new VM in the Unraid VM manager.

Important configuration:

  • Machine Type: Q35
  • CPU Mode: Host passthrough
  • Network: bridged adapter
  • Disk Bus: VirtIO
  • Boot ISO: OPNsense installer

Once the VM booted, the installer walked through the typical steps:

  • disk partitioning
  • root password setup
  • network interface assignment

After installation completed, I removed the ISO and rebooted the VM.

Now the firewall was running.


My First Mistake

My first mistake was not assigning the interfaces correctly.

OPNsense requires two interfaces:

  • WAN
  • LAN

Initially I accidentally assigned them backwards.

This caused a bunch of confusing issues:

  • the firewall couldn’t reach the internet
  • DHCP wasn’t working
  • machines couldn’t route traffic

Once I swapped the interfaces correctly, everything started working.


Setting Up Basic Firewall Rules

After getting the firewall running, I started configuring rules.

The goal was simple:

  • allow internal lab traffic
  • block unnecessary external connections
  • generate useful logs

Every firewall rule had logging enabled so the SIEM could capture the events.

This is important because without logging, blocked traffic never shows up in the monitoring system.


Connecting the Firewall to My SIEM

Once the firewall was working, I wanted to send the logs into Wazuh.

The pipeline ended up looking like this:

OPNsense > Syslog > Wazuh Manager > Wazuh Indexer > Wazuh Dashboard


Configuring OPNsense Syslog

Inside the OPNsense dashboard I enabled remote logging.

Settings I used:

  • Target server: Wazuh manager IP
  • Transport: UDP
  • Port: 514
  • Log type: Firewall
  • Program: filterlog

That filterlog field matters because it’s what OPNsense uses for firewall events.

A typical firewall log looks like this:

1
OPNsense.lan filterlog[98982]: ...,match,block,in,...

Verifying Logs Were Arriving

Before worrying about the dashboard, I wanted proof the logs were actually reaching the Wazuh manager.

I used tcpdump to watch the syslog port.

1
sudo tcpdump -i any port 514

Immediately I could see OPNsense sending logs.

That confirmed the first part of the pipeline worked.


Another Problem

When I opened the Wazuh dashboard, the logs were there but they weren’t triggering alerts.

Searching worked:

1
predecoder.program_name:filterlog

But I wanted actual detection rules for blocked traffic.


Creating a Custom Detection Rule

At first I tried building a completely custom decoder and rule.

The Wazuh web editor kept throwing XML syntax errors even though the XML looked correct.

After fighting with the UI for a while, I switched to editing the files directly on the Wazuh manager.

That ended up being much easier.

Decoder file:

1
/var/ossec/etc/decoders/opnsense_decoders.xml
1
2
3
<decoder name="opnsense-filterlog">
  <prematch>filterlog</prematch>
</decoder>

Discovering Wazuh Having Detection Events

While testing rules I noticed something interesting.

Wazuh was already detecting the firewall logs using its built-in pfSense ruleset.

Example alert:

1
2
rule.id: 87702
description: Multiple pfSense firewall blocks events from same source

Instead of replacing that rule, I decided to build on top of it.

Final Rule That Worked

This was the final rule.

Rule file:

1
/var/ossec/etc/rules/opnsense_rules.xml
1
2
3
4
5
6
7
8
9
<group name="opnsense,firewall,local">

  <rule id="100102" level="7">
    <if_sid>87702</if_sid>
    <description>OPNsense firewall blocked traffic</description>
    <group>opnsense,firewall,block</group>
  </rule>

</group>

After saving the rule I restarted Wazuh.

1
sudo systemctl restart wazuh-manager

Testing the Detection

To generate firewall events I ran a scan against the network.

1
nmap -p 22,23,80,443 192.168.8.109

The firewall blocked the scan and Wazuh generated alerts.

Searching the dashboard for:

1
rule.id:100102

showed the events immediately.

Rule ID 100102

What the Firewall Logs Show

The logs contain a lot of useful data.

Example fields include:

1
2
3
4
5
protocol: udp
action: block
srcip: 1.1.1.1
dstip: 192.168.8.169
dstport: 53

This allows the SIEM to detect things like:

  • port scans
  • brute force attempts
  • suspicious outbound connections
  • external probing

Interesting Network Noise

During testing I saw a lot of blocked traffic like this:

1
239.255.255.250:1900

This is SSDP multicast traffic, usually coming from local devices like smart TVs or consoles.

It’s normal background noise, but it’s interesting seeing it appear in firewall telemetry.


Building a Security Monitoring Dashboard in Grafana

Once the logs and alerts were flowing correctly, I wanted a dedicated monitoring dashboard.

Instead of digging through the Wazuh interface constantly, Grafana lets me visualize security activity in real time.

I built a network security dashboard with several panels.


Wazuh Alerts Timeline

The first panel tracks alert activity over time.

Query configuration

Metric: Count Group By: Date Histogram Field: timestamp


Top Attacking IPs

Next I wanted to see which IP addresses were generating the most firewall events.

Lucene query

1
predecoder.program_name:filterlog

Configuration

Metric: Count Group By: Terms Field: srcip

This shows the most active source IPs hitting the firewall.


Most Targeted Ports

To understand what attackers were probing, I created another panel.

Metric: Count Group By: Terms Field: dstport

This highlights which ports are most frequently targeted.


Firewall Actions

This panel shows how the firewall is handling traffic.

Metric: Count Group By: Terms Field: action

Visualization: Pie Chart

This quickly shows the ratio of:

  • blocked traffic
  • allowed traffic
  • other actions

Live Firewall Logs

Finally, I added a real-time log panel.

Query type

Logs

Lucene query

1
predecoder.program_name:filterlog

This creates a live stream of firewall events, which is extremely useful during testing or attack simulations.

This panel streams firewall events live, which is especially helpful when running attack simulations or troubleshooting network activity.

Panel created in Grafana for easier visibility


Lessons Learned

This project ended up being a really good reminder that security tooling is rarely plug-and-play.

A few things stood out while building this:

Interface Assignment Matters More Than You Think

Assigning the WAN and LAN interfaces backwards completely broke connectivity.

At first it looked like multiple problems at once:

  • no internet access
  • DHCP not working
  • machines unable to route traffic

But it all traced back to a simple interface mistake. Once those were corrected, the firewall immediately behaved as expected.


Always Verify Logs Before Troubleshooting Detection

Before spending time writing detection rules, I verified that the logs were actually arriving at the Wazuh manager using:

1
tcpdump -i any port 514

Seeing the logs in real time confirmed that the network pipeline was working, which meant the issue was on the detection side, not the logging side.

Built-In Rules Can Save Time

Originally I planned to write a full custom decoder and rule set for OPNsense logs.

While testing, I realized that Wazuh was already detecting the firewall activity using its pfSense ruleset. Instead of rebuilding everything from scratch, I simply extended the existing rule to generate the alerts I wanted.

This ended up being much simpler and avoided unnecessary complexity.

Visualization Makes Monitoring Easier

Once the Grafana dashboard was built, patterns became much easier to see.

Instead of digging through raw logs, the panels quickly show things like:

  • spikes in firewall alerts

  • which IPs are scanning the network

  • the most targeted ports

  • how the firewall is handling traffic

Not All Traffic Is Malicious

Once firewall telemetry is enabled, you quickly realize how much normal background traffic appears in logs.

During testing I saw repeated entries like:

1
239.255.255.250:1900

This is SSDP multicast traffic, usually generated by devices like smart TVs, game consoles, and other consumer hardware.

It’s harmless, but it’s a good reminder that not every alert is an attack.


If it’s not broken, fix it til it is.

This post is licensed under CC BY 4.0 by the author.