Skip to main content
Project HomeLab Advanced

Network Security Monitoring with Suricata

Jason J. Boderebe
12 min tutorial
#homelab #ids #network-security #monitoring

If you want to see what is happening on your lab network — exploit attempts, scans, suspicious traffic — you need an IDS. Suricata is fast, flexible, and free. I run it on a dedicated Ubuntu VM that sits between my attack machines and my vulnerable targets.

This is not a comprehensive Suricata deployment guide. This is how I set it up in my lab to learn how network-based detection works.

What Suricata does

Suricata inspects network traffic in real time and matches it against rules. When it sees something that matches a rule (like an Nmap scan or a Metasploit payload), it logs an alert. You can run it in IDS mode (just log) or IPS mode (block the traffic). I run IDS mode because I want to see everything, not block it.

VM requirements

  • 4GB RAM — Suricata can use more if you have it, but 4GB works fine for a lab
  • 2 vCPUs
  • Ubuntu 22.04 LTS (or 24.04 if you are reading this later)
  • Two network interfaces — one for management (SSH), one for monitoring

The monitoring interface should be on the same network as your vulnerable VMs. Set it to promiscuous mode so it can see all traffic, not just traffic addressed to it.

Installing Suricata

SSH into your Ubuntu VM and run:

sudo apt update
sudo apt install software-properties-common -y
sudo add-apt-repository ppa:oisf/suricata-stable -y
sudo apt update
sudo apt install suricata jq -y

Check the version:

suricata --version

As of November 2024, the stable PPA has Suricata 7.0.x. That is what I am running.

Configuration

Suricata’s main config is at /etc/suricata/suricata.yaml. It is huge. Most of it you can leave alone.

Set your HOME_NET

Open /etc/suricata/suricata.yaml and find the address-groups section. Set HOME_NET to match your lab network:

vars:
  address-groups:
    HOME_NET: "[192.168.100.0/24]"
    EXTERNAL_NET: "!$HOME_NET"

Replace 192.168.100.0/24 with your actual lab subnet.

Pick your monitoring interface

Find the af-packet section and set the interface to the one you want to monitor:

af-packet:
  - interface: ens19
    cluster-id: 99
    cluster-type: cluster_flow
    defrag: yes

Replace ens19 with your monitoring interface name (check with ip link show).

Disable hardware offloading

This tripped me up the first time. Network interface offloading features (TSO, GRO, etc.) can cause Suricata to miss packets. Turn them off:

sudo ethtool -K ens19 gro off lro off

Replace ens19 with your interface. To make it persistent, add the command to /etc/rc.local or create a systemd service.

Rule management

Suricata uses rules to detect threats. The rules are in /etc/suricata/rules/. By default, you get a basic set. To get the Emerging Threats (ET) Open ruleset:

sudo suricata-update

This downloads the latest rules and reloads Suricata. Run it weekly or whenever you want fresh rules.

To enable all the rules (not just the recommended ones), edit /etc/suricata/suricata.yaml and find the rule-files section. Make sure it includes:

rule-files:
  - suricata.rules

Then:

sudo suricata-update enable-source et/open
sudo suricata-update
sudo systemctl restart suricata

Running Suricata

Start it:

sudo systemctl start suricata
sudo systemctl enable suricata

Check the logs:

sudo tail -f /var/log/suricata/suricata.log

If you see errors about the interface not being in promiscuous mode, set it manually:

sudo ip link set ens19 promisc on

Testing it

From your Kali box, run an Nmap scan against one of your vulnerable VMs:

nmap -sV 192.168.100.50

Then check Suricata’s alerts:

sudo tail -f /var/log/suricata/fast.log

You should see alerts for the scan. If not, check that:

  • Your monitoring interface is on the same network
  • Promiscuous mode is enabled
  • The rules are loaded (sudo suricata-update list-enabled-sources)

Viewing alerts with jq

The EVE JSON log (/var/log/suricata/eve.json) is easier to parse than the fast log. Use jq to filter it:

sudo tail -f /var/log/suricata/eve.json | jq 'select(.event_type=="alert")'

This shows only alerts in real time.

What I use Suricata for

  • Seeing how attacks look on the wire — run an exploit from Metasploit, then check what Suricata logged
  • Testing evasion techniques — if I modify a payload or use fragmentation, does Suricata still catch it?
  • Learning rule syntax — I write custom rules and test them against known-bad traffic

What I do not do

  • Run it in IPS mode in my lab (I want to see everything, not block it)
  • Forward logs to a SIEM (I just read the local logs for now)
  • Tune it heavily (default rules are fine for learning)

Resources

If you want to go deeper, set up log forwarding to a SIEM (ELK, Splunk, Wazuh) and build dashboards. For now, watching the logs locally is enough to understand how network detection works.

Previous: Deploying Vulnerable Applications ENIP_CLIENT: “$HOME_NET” ENIP_SERVER: “$HOME_NET”

port-groups: HTTP_PORTS: “80” SHELLCODE_PORTS: “!80” ORACLE_PORTS: 1521 SSH_PORTS: 22 DNP3_PORTS: 20000 MODBUS_PORTS: 502 FILE_DATA_PORTS: ”[$HTTP_PORTS,110,143]” FTP_PORTS: 21 GENEVE_PORTS: 6081 VXLAN_PORTS: 4789 TEREDO_PORTS: 3544

Logging configuration

logging: default-log-level: notice outputs:

  • console: enabled: yes
  • file: enabled: yes level: info filename: /var/log/suricata/suricata.log
  • syslog: enabled: no facility: local5 format: ”[%i] <%d> — “

Output plugins

outputs:

  • fast: enabled: yes filename: fast.log append: yes
  • eve-log: enabled: yes filetype: regular filename: eve.json types: - alert: payload: yes payload-buffer-size: 4kb payload-printable: yes packet: yes metadata: no http-body: yes http-body-printable: yes tagged-packets: yes - http: extended: yes - dns: query: yes answer: yes - tls: extended: yes - files: force-magic: no - smtp: - ssh - stats: totals: yes threads: no deltas: no - flow

### Step 4: Rule Management

#### Download and Install Rules

```bash
# Install suricata-update
sudo pip3 install suricata-update

# Initialize suricata-update
sudo suricata-update

# Update rules
sudo suricata-update update-sources
sudo suricata-update

# Enable specific rule sources
sudo suricata-update enable-source et/open
sudo suricata-update enable-source oisf/trafficid
sudo suricata-update

Custom Rule Creation

# Create custom rules directory
sudo mkdir -p /etc/suricata/rules/custom

# Example custom rule
echo 'alert tcp any any -> $HOME_NET 22 (msg:"SSH Connection Attempt"; flow:to_server; flags:S; sid:1000001; rev:1;)' | sudo tee /etc/suricata/rules/custom/ssh-monitoring.rules

# Include custom rules in main config
echo 'rule-files:' | sudo tee -a /etc/suricata/suricata.yaml
echo '  - /etc/suricata/rules/custom/ssh-monitoring.rules' | sudo tee -a /etc/suricata/suricata.yaml

Step 5: Log Management and Analysis

Logrotate Configuration

# Configure log rotation
sudo tee /etc/logrotate.d/suricata << EOF
/var/log/suricata/*.log /var/log/suricata/*.json {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    sharedscripts
    create 640 suricata suricata
    postrotate
        /bin/kill -HUP \`cat /var/run/suricata.pid 2>/dev/null\` 2>/dev/null || true
    endscript
}
EOF

Real-time Log Monitoring

# Monitor alerts in real-time
sudo tail -f /var/log/suricata/fast.log

# Monitor EVE JSON logs
sudo tail -f /var/log/suricata/eve.json | jq

# Monitor specific event types
sudo tail -f /var/log/suricata/eve.json | jq 'select(.event_type=="alert")'

Integration with SIEM

ELK Stack Integration

Filebeat Configuration

# /etc/filebeat/filebeat.yml
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/suricata/eve.json
  json.keys_under_root: true
  json.add_error_key: true
  fields:
    logtype: suricata
  fields_under_root: true

output.elasticsearch:
  hosts: ["elasticsearch:9200"]
  index: "suricata-%{+yyyy.MM.dd}"

setup.template.name: "suricata"
setup.template.pattern: "suricata-*"

Kibana Dashboard Creation

{
  "dashboard": {
    "id": "suricata-overview",
    "title": "Suricata Security Overview",
    "visualizations": [
      {
        "id": "alerts-over-time",
        "type": "line",
        "query": "event_type:alert"
      },
      {
        "id": "top-signatures",
        "type": "data_table",
        "query": "event_type:alert",
        "aggregation": "terms",
        "field": "alert.signature"
      },
      {
        "id": "protocol-distribution",
        "type": "pie",
        "query": "event_type:flow",
        "aggregation": "terms",
        "field": "proto"
      }
    ]
  }
}

Splunk Integration

Universal Forwarder Configuration

# /opt/splunkforwarder/etc/system/local/inputs.conf
[monitor:///var/log/suricata/eve.json]
disabled = false
index = security
sourcetype = suricata:eve:json
host_segment = 4

[monitor:///var/log/suricata/fast.log]
disabled = false
index = security
sourcetype = suricata:alert
host_segment = 4

Performance Tuning

System Optimization

Kernel Parameters

# /etc/sysctl.conf optimizations
echo 'net.core.rmem_default = 262144' | sudo tee -a /etc/sysctl.conf
echo 'net.core.rmem_max = 16777216' | sudo tee -a /etc/sysctl.conf
echo 'net.core.netdev_max_backlog = 5000' | sudo tee -a /etc/sysctl.conf

# Apply changes
sudo sysctl -p

CPU Affinity

# Pin Suricata to specific CPU cores
echo 'SURICATA_OPTIONS="--cpu-affinity=1-3"' | sudo tee -a /etc/default/suricata

Suricata-Specific Tuning

Worker Thread Configuration

# In suricata.yaml
threading:
  set-cpu-affinity: yes
  cpu-affinity:
    - management-cpu-set:
        cpu: [ 0 ]
    - receive-cpu-set:
        cpu: [ 1 ]
    - worker-cpu-set:
        cpu: [ 2, 3 ]
        mode: "exclusive"

Memory Management

# In suricata.yaml
defrag:
  memcap: 32mb
  hash-size: 65536
  trackers: 65535
  max-frags: 65535
  prealloc: yes
  timeout: 60

flow:
  memcap: 128mb
  hash-size: 65536
  prealloc: 10000
  emergency-recovery: 30

Testing and Validation

Generate Test Traffic

# Install nmap for testing
sudo apt install nmap -y

# Generate various types of traffic
nmap -sS 192.168.1.0/24  # SYN scan
nmap -sU 192.168.1.1     # UDP scan
curl -A "BADBOT" http://192.168.1.100/  # User-agent alert

# Test with EICAR string
echo 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' > eicar.txt
python3 -m http.server 8000  # Serve file for download test

Alert Verification

# Check for generated alerts
sudo grep -i "EICAR" /var/log/suricata/fast.log
sudo grep -i "nmap" /var/log/suricata/fast.log

# Verify JSON events
sudo jq '.event_type' /var/log/suricata/eve.json | sort | uniq -c

Advanced Features

File Extraction

# In suricata.yaml
file-store:
  version: 2
  enabled: yes
  dir: /var/log/suricata/files
  write-fileinfo: yes
  write-meta: yes
  include-pid: yes

Protocol Detection

# Enhanced protocol detection
app-layer:
  protocols:
    tls:
      enabled: yes
      detection-ports:
        dp: 443
    http:
      enabled: yes
      libhtp:
        default-config:
          personality: IDS
          request-body-limit: 100kb
          response-body-limit: 100kb

Lua Scripting

-- /etc/suricata/scripts/custom-detection.lua
function init (args)
    local needs = {}
    needs["http.request_line"] = tostring(true)
    return needs
end

function match(args)
    local request_line = HttpGetRequestLine()
    if request_line then
        if string.find(request_line, "admin") then
            return 1
        end
    end
    return 0
end

Troubleshooting

Common Issues

High CPU Usage

# Check thread distribution
sudo grep "thread" /var/log/suricata/suricata.log

# Monitor CPU usage per core
htop

# Adjust worker threads
sudo systemctl edit suricata
# Add: Environment="SURICATA_OPTIONS=--runmode=workers --cpu-affinity=1-2"

Packet Drops

# Check interface statistics
sudo ethtool -S eth0 | grep drop

# Monitor Suricata stats
sudo tail -f /var/log/suricata/stats.log

# Increase buffer sizes
echo 'net.core.netdev_max_backlog = 10000' | sudo tee -a /etc/sysctl.conf

Memory Issues

# Monitor memory usage
sudo grep -i memcap /var/log/suricata/suricata.log

# Adjust memory caps in suricata.yaml
# Increase flow.memcap and stream.memcap values

Performance Monitoring

#!/bin/bash
# suricata-stats.sh
while true; do
    echo "=== $(date) ==="
    sudo grep "Capture.Kernel" /var/log/suricata/stats.log | tail -1
    sudo grep "Flow.Memuse" /var/log/suricata/stats.log | tail -1
    echo "CPU Usage: $(top -bn1 | grep suricata | awk '{print $9}')%"
    echo "Memory: $(ps aux | grep suricata | grep -v grep | awk '{print $6}') KB"
    echo ""
    sleep 60
done

Security Best Practices

Hardening Guidelines

  • Run Suricata as non-root user
  • Implement proper file permissions
  • Regular rule updates and testing
  • Secure log file access
  • Network segmentation for monitoring traffic

Maintenance Tasks

  • Weekly rule updates
  • Monthly performance reviews
  • Quarterly signature tuning
  • Annual architecture reviews

Conclusion

You now have a fully functional network security monitoring system using Suricata in your home lab. This setup provides:

  • Real-time threat detection across your entire network
  • Comprehensive logging for forensic analysis
  • Flexible rule management for custom detection scenarios
  • Integration capabilities with popular SIEM platforms
  • Performance optimization for high-throughput environments

Next Steps

  1. Tune rules based on your specific environment
  2. Integrate with SIEM for centralized log management
  3. Implement response automation using SOAR platforms
  4. Add network forensics capabilities with full packet capture
  5. Deploy threat hunting workflows and playbooks

This advanced monitoring capability significantly enhances your home lab’s security posture and provides valuable hands-on experience with enterprise-grade security tools.


Continue your home lab journey with Part 4: Incident Response Automation to build automated response capabilities.