Skip to main content

Command Palette

Search for a command to run...

06. Integrating Wazuh with pfSense, Suricata, and Zeek: Building a Comprehensive Security Stack

Updated
9 min read

Security operations require a centralized view of logs, alerts, and network activities. That's where Wazuh shines—bringing visibility, correlation, and automation in one place. In this guide, I'll walk through how to integrate Wazuh with pfSense (firewall), Suricata (IDS/IPS), and Zeek (network analysis framework).

After implementing these integrations across multiple enterprise environments, I can tell you that proper integration is what separates good security teams from great ones. The tools are powerful individually, but when properly integrated, they create a security monitoring ecosystem that can detect and respond to threats in real-time.

What makes this guide different:

  • Real production experience with these integrations (not just lab testing)

  • Common pitfalls and how to avoid them (I've made these mistakes so you don't have to)

  • Performance considerations for large-scale deployments (this matters more than you'd think)

  • Troubleshooting techniques for when things go wrong (and they will go wrong)

Let's build a security stack that actually works in the real world.


🔥 pfSense Integration - Your Network Perimeter

Here's why pfSense integration matters: pfSense acts as your gateway firewall, logging every connection attempt, block event, and NAT activity. By sending these logs to Wazuh, you can centralize firewall activity, detect anomalies, and trigger alerts when suspicious patterns emerge.

The reality: Most organizations have a firewall, but they're not getting the full value from their firewall logs. This integration changes that.

Step 1: Configure pfSense to Forward Logs to Wazuh

In the pfSense web interface:

  1. Navigate to: Status → System Logs → Settings

  2. Enable: "Send log messages to remote syslog server"

  3. Set your Wazuh Manager's IP and port:

     YOUR_WAZUH_MANAGER_IP:514
    
  4. Select log categories you want to forward:

    • Firewall logs (essential)

    • System logs (recommended)

    • DHCP logs (optional)

    • VPN logs (if applicable)

Pro tip: Start with firewall logs only. You can expand to other log types as your Wazuh rules mature (and trust me, you'll want to expand once you see the value).

Step 2: Configure Wazuh to Ingest pfSense Logs

On the Wazuh Manager, edit the configuration file:

<!-- Add to /var/ossec/etc/ossec.conf -->
<localfile>
  <log_format>syslog</log_format>
  <location>/var/log/pfsense.log</location>
</localfile>

Step 3: Create Custom Decoders for pfSense

pfSense logs need proper parsing to extract meaningful fields:

<!-- Custom decoder for pfSense -->
<decoder name="pfsense">
  <program_name>^pfsense</program_name>
</decoder>

<decoder name="pfsense-firewall">
  <parent>pfsense</parent>
  <prematch>filterlog:</prematch>
  <regex offset="after_prematch">
    ^(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\S+),(\d+),(\S+),(\S+),(\d+),(\S+),(\d+),(\d+),(\S+),(\S+),(\d+),(\d+),(\d+)
  </regex>
  <order>
    timestamp,rule_number,sub_rule_number,anchor,tracker,interface,reason,action,direction,
    ip_version,tos,ecn,ttl,id,offset,flags,proto_id,proto,length,src_ip,dst_ip,src_port,
    dst_port,data_length,tcp_flags,sequence_number
  </order>
</decoder>

Step 4: Create Custom Rules for pfSense

High-priority firewall events:

<rule id="200001" level="5">
  <decoded_as>pfsense-firewall</decoded_as>
  <field name="action">block</field>
  <description>pfSense: Blocked connection attempt</description>
</rule>

<rule id="200002" level="7">
  <decoded_as>pfsense-firewall</decoded_as>
  <field name="action">block</field>
  <field name="proto">tcp</field>
  <field name="dst_port">22</field>
  <description>pfSense: SSH brute force attempt blocked</description>
</rule>

<rule id="200003" level="10">
  <decoded_as>pfsense-firewall</decoded_as>
  <field name="action">block</field>
  <field name="src_ip">^192\.168\.</field>
  <description>pfSense: Internal IP blocked (possible lateral movement)</description>
</rule>

✅ Once applied, Wazuh can now identify specific firewall actions with detailed metadata.


🛡️ Suricata Integration - Deep Packet Inspection

Here's why Suricata integration is powerful: Suricata provides deep packet inspection and intrusion detection. By sending Suricata alerts to Wazuh, you can correlate IDS events with firewall logs for a full picture of threats.

The value: You get network-level visibility that complements your host-based monitoring, and the correlation between the two is where the real insights happen.

Step 1: Configure Suricata to Output EVE JSON Logs

In /etc/suricata/suricata.yaml:

outputs:
  - eve-log:
      enabled: yes
      filetype: regular
      filename: eve.json
      types:
        - alert:
            payload: yes
            packet: yes
            metadata: yes
        - http:
            extended: yes
        - dns:
            query: yes
            answer: yes
        - tls:
            extended: yes
        - files:
            force-magic: no
        - smtp:
        - ssh
        - stats:
            totals: yes
            threads: no

Step 2: Configure Wazuh to Read Suricata Logs

Edit ossec.conf on the Wazuh Manager:

<!-- Add Suricata logs -->
<localfile>
  <log_format>json</log_format>
  <location>/var/log/suricata/eve.json</location>
  <label key="event_type">suricata</label>
</localfile>

Step 3: Create Suricata Rules in Wazuh

Prioritize high-severity alerts:

<rule id="200100" level="12">
  <decoded_as>json</decoded_as>
  <field name="event_type">alert</field>
  <field name="alert.severity" type="pcre2">^[1-2]$</field>
  <description>Suricata: High severity alert</description>
  <mitre>
    <id>T1055</id>
  </mitre>
</rule>

<rule id="200101" level="8">
  <decoded_as>json</decoded_as>
  <field name="event_type">alert</field>
  <field name="alert.category">Trojan</field>
  <description>Suricata: Trojan detection</description>
</rule>

<rule id="200102" level="10">
  <decoded_as>json</decoded_as>
  <field name="event_type">alert</field>
  <field name="alert.signature">ET MALWARE</field>
  <description>Suricata: Malware signature detected</description>
</rule>

💡 Tip: Adjust severity thresholds based on your network's risk tolerance (and be prepared to tune these as you learn what's normal for your environment).


🔍 Zeek Integration - Network Behavioral Analysis

Here's why Zeek integration is game-changing: Zeek provides behavioral and contextual insights that traditional IDS systems miss. It's like having a network forensics expert watching your traffic 24/7.

The reality: Zeek is incredibly powerful, but it's also complex. The integration with Wazuh makes it much more accessible and actionable.

Prerequisites:

  1. Zeek server with Wazuh agent installed

  2. Understanding of Zeek output (conn.log, http.log, dns.log, etc.)

  3. Proper network configuration for Zeek to monitor traffic

Step 1: Configure Zeek for JSON Output

On the Zeek server, edit the local configuration:

# Edit local.zeek file
sudo nano /opt/zeek/share/zeek/site/local.zeek

Add the following at the bottom:

@load policy/tuning/json-logs

Deploy the changes:

# Apply configuration changes
zeekctl deploy

Verify JSON output:

# Check if logs are in JSON format
head -1 /opt/zeek/logs/current/conn.log
# Should output: {"ts":"2025-01-14T01:23:45Z","uid":"C3lA3m2x","id.orig_h":"192.168.1.5", ...}

Step 2: Configure Wazuh Agent to Read Zeek Logs

Edit the agent configuration:

# Edit ossec.conf on Zeek server
sudo nano /var/ossec/etc/ossec.conf

Add Zeek log collection:

<localfile>
    <location>/opt/zeek/logs/current/*.log</location>
    <log_format>json</log_format>
</localfile>

Restart the agent:

sudo systemctl restart wazuh-agent

Step 3: Create Zeek Decoders on Wazuh Server

Create custom decoder file:

sudo nano /var/ossec/etc/decoders/0550-zeek_decoders.xml

Add Zeek decoder:

<decoder name="zeek-json">
  <prematch>^{\s"ts":\s"\d+.\d+",\s"uid":\s"."\s}$</prematch>
  <plugin_decoder>JSON_Decoder</plugin_decoder>
</decoder>

This decoder does two things:

  1. Filtering: Ensures logs are from Zeek by looking for "ts" (timestamp) and "uid" (unique ID) fields

  2. Parsing: Breaks down JSON logs into separate data fields for Wazuh rules (this is where the magic happens)

Step 4: Create Zeek Rules

Create custom rules file:

sudo nano /var/ossec/etc/rules/local_rules.xml

Add Zeek rules:

<!-- Rule 100200: Main Zeek Filter -->
<rule id="100200" level="3">
  <decoded_as>json</decoded_as>
  <field name="uid">.+</field>
  <description>Zeek: Network activity detected</description>
</rule>

<!-- Rule 100201: Network Connection Detector -->
<rule id="100201" level="5">
  <if_sid>100200</if_sid>
  <field name="id.orig_h">.+</field>
  <field name="proto">.+</field>
  <description>Zeek: Network connection established</description>
</rule>

<!-- Rule 100202: HTTP Activity -->
<rule id="100202" level="3">
  <if_sid>100200</if_sid>
  <field name="method">.+</field>
  <field name="host">.+</field>
  <description>Zeek: HTTP request detected</description>
</rule>

<!-- Rule 100203: DNS Queries -->
<rule id="100203" level="3">
  <if_sid>100200</if_sid>
  <field name="query">.+</field>
  <field name="qtype">.+</field>
  <description>Zeek: DNS query detected</description>
</rule>

<!-- Rule 100204: Suspicious Domain -->
<rule id="100204" level="8">
  <if_sid>100203</if_sid>
  <field name="query" type="pcre2">.*\.(tk|ml|ga|cf)$</field>
  <description>Zeek: Suspicious domain query</description>
</rule>

Restart Wazuh Manager:

sudo systemctl restart wazuh-manager

Step 5: Verify Integration

Check if logs are being processed:

# Check if Zeek logs are being read
tail -f /var/ossec/logs/archives/archives.json | grep Zeek

# Check if alerts are being generated
tail -f /var/ossec/logs/alerts/alerts.json | grep "Zeek:"

# Check Filebeat status
tail -f /var/log/filebeat/filebeat

Common Issues and Solutions:

Issue 1: Logs not appearing in Wazuh

  • Check agent connectivity: sudo systemctl status wazuh-agent

  • Verify log file permissions: ls -la /opt/zeek/logs/current/

  • Check agent configuration: sudo cat /var/ossec/etc/ossec.conf | grep zeek

Issue 2: Alerts not being generated

  • Verify decoder is working: Check /var/ossec/logs/archives/archives.json

  • Test rule syntax: Use Wazuh's rule testing tools

  • Check rule dependencies: Ensure parent rules are working

Issue 3: Filebeat transmission issues

  • Check for nested objects in JSON logs

  • Verify pipeline configuration

  • Restart Filebeat: sudo systemctl restart filebeat


🎯 Advanced Integration Techniques

Log Correlation Rules (the really powerful stuff)

Here's where it gets interesting—correlating events across different sources:

<!-- Rule: Firewall block + Suricata alert -->
<rule id="300001" level="12">
  <if_matched_sid>200001,200100</if_matched_sid>
  <same_source_ip />
  <timeframe>300</timeframe>
  <description>Correlated: Firewall block and IDS alert</description>
</rule>

<!-- Rule: Zeek suspicious domain + DNS query -->
<rule id="300002" level="10">
  <if_matched_sid>100204,100203</if_matched_sid>
  <same_source_ip />
  <timeframe>60</timeframe>
  <description>Correlated: Suspicious domain query detected</description>
</rule>

Custom Dashboards (the visual stuff)

Here's how to create comprehensive security dashboards that actually tell a story:

{
  "title": "Network Security Overview",
  "panels": [
    {
      "title": "Firewall Blocks",
      "type": "stat",
      "targets": [
        {
          "query": "rule.id:200001"
        }
      ]
    },
    {
      "title": "Suricata Alerts",
      "type": "graph",
      "targets": [
        {
          "query": "rule.id:200100"
        }
      ]
    },
    {
      "title": "Zeek Network Activity",
      "type": "table",
      "targets": [
        {
          "query": "rule.id:100201"
        }
      ]
    }
  ]
}

Automated Response (the automation stuff)

Here's how to set up automated responses to threats (this is where it gets really cool):

#!/bin/bash
# Automated response script

# Get high-priority alerts
ALERTS=$(curl -k -s -u admin:password "https://YOUR_WAZUH_IP:55000/events" | jq -r '.data.affected_items[] | select(.rule.level >= 10) | .agent')

# Block IPs in pfSense
for agent in $ALERTS; do
  # Extract source IP
  SRC_IP=$(curl -k -s -u admin:password "https://YOUR_WAZUH_IP:55000/events" | jq -r '.data.affected_items[] | select(.agent == "'$agent'") | .data.srcip')

  # Add firewall rule
  ssh admin@pfSense "pfctl -t blocked_ips -T add $SRC_IP"
done

📊 Performance Optimization

Resource Management

Indexer Performance:

# OpenSearch configuration
opensearch.yml:
  indices.memory.index_buffer_size: 30%
  indices.queries.cache.size: 20%
  indices.fielddata.cache.size: 20%

Manager Performance:

<!-- Wazuh Manager configuration -->
<ossec_config>
  <analysisd>
    <log_alert_level>3</log_alert_level>
    <log_analysis_level>3</log_analysis_level>
  </analysisd>
</ossec_config>

Log Retention Policies

Set appropriate retention periods:

# Index lifecycle management
policy:
  phases:
    hot:
      actions:
        rollover:
          max_size: 50GB
          max_age: 1d
    warm:
      min_age: 1d
      actions:
        forcemerge:
          max_num_segments: 1
    cold:
      min_age: 7d
      actions:
        freeze: {}
    delete:
      min_age: 30d

🚨 Troubleshooting Common Issues

Integration Failures

Issue: pfSense logs not appearing

# Check syslog configuration
grep -r "pfsense" /var/log/

# Verify network connectivity
telnet YOUR_WAZUH_IP 514

# Check Wazuh configuration
sudo cat /var/ossec/etc/ossec.conf | grep pfsense

Issue: Suricata alerts not correlating

# Check JSON format
head -1 /var/log/suricata/eve.json

# Verify Wazuh decoder
sudo /var/ossec/bin/wazuh-logtest

# Check rule syntax
sudo /var/ossec/bin/wazuh-rule-test

Issue: Zeek integration not working

# Check agent status
sudo systemctl status wazuh-agent

# Verify log file permissions
ls -la /opt/zeek/logs/current/

# Check decoder configuration
sudo cat /var/ossec/etc/decoders/0550-zeek_decoders.xml

Performance Issues

Issue: High CPU usage

# Check process usage
top -p $(pgrep wazuh-analysisd)

# Monitor indexer performance
curl -X GET "localhost:9200/_nodes/stats/jvm?pretty"

# Check log volume
du -sh /var/ossec/logs/

Issue: Memory issues

# Check memory usage
free -h

# Monitor JVM heap
curl -X GET "localhost:9200/_nodes/stats/jvm?pretty"

# Check indexer memory
curl -X GET "localhost:9200/_cluster/health?pretty"

🎉 Final Thoughts

By integrating pfSense, Suricata, and Zeek with Wazuh, you're building a layered defense strategy that actually works:

  • pfSense gives you perimeter control and network-level visibility

  • Suricata adds deep packet inspection & IDS alerts for threat detection

  • Zeek provides behavioral and contextual insights for advanced analysis

When all three feed into Wazuh, you gain correlated, actionable intelligence—turning logs into meaningful alerts and responses.

What you've accomplished:

  • Integrated network security tools with Wazuh

  • Created custom decoders and rules for each tool

  • Set up log correlation across different sources

  • Implemented performance optimization techniques

Next steps:

  1. Fine-tune rules - Adjust based on your environment (this takes time)

  2. Create custom dashboards - Visualize your security posture (this is actually fun)

  3. Set up automated responses - Respond to threats automatically (this is where it gets really cool)

  4. Monitor performance - Ensure optimal operation (this is crucial)

Pro tip: Start with basic integration and gradually add complexity. This allows you to identify and resolve issues before they become problems (and trust me, you'll have issues).


🔜 What's Next?

Now that you have a comprehensive security monitoring stack, it's time to put it to work. In the next chapter, we'll explore advanced threat hunting techniques and incident response procedures.

You'll learn:

  • How to hunt for advanced threats

  • Incident response workflows

  • Forensic analysis techniques

  • Building a security operations center

2.0K views

More from this blog

F

FPT Metrodata Indonesia Cyber Security

643 posts

FPT Metrodata Indonesia (FMI) provides news, analysis & guides on cybersecurity and threat intelligence for Indonesia & Vietnam. Visit https://news.fmisec.com. FMI: https://fmisec.com