Install Suricata IDS/IPS on VPS — Intrusion Detection
Suricata is an open-source Intrusion Detection and Prevention System (IDS/IPS) maintained by the OISF (Open Information Security Foundation). It analyzes network traffic in real-time, detecting port scans, exploit attempts, malware C2 traffic, SQL injection over HTTP, and thousands of other threats using Emerging Threats rules. Suricata supports multi-threading (fast even on single-core VPS), operates in both IDS mode (logging only) and IPS mode (blocking via NFQueue), and can natively parse protocols like HTTP, TLS/SSL, DNS, FTP, and SMB without external tools. This guide covers installation through viewing real alerts.
IDS vs IPS — Which Mode to Use?
| Mode | How It Works | Best For |
|---|---|---|
| IDS (af-packet) | Copies traffic via kernel ring buffers — logs only, never blocks | Production VPS where you want visibility first and need to tune rules |
| IPS (NFQueue) | Routes packets through kernel queue — Suricata can drop in real-time | VPS with tuned rules ready for active blocking |
Start with IDS mode for 1–2 weeks to identify false positives before enabling IPS.
Install Suricata on Ubuntu/Debian
# Add the OISF PPA (Ubuntu) — gets a newer version than the default repo
sudo add-apt-repository ppa:oisf/suricata-stable -y
sudo apt update
sudo apt install suricata -y
# Verify the version
suricata --build-info | head -5
# Enable and start the service
sudo systemctl enable suricata
sudo systemctl start suricata
sudo systemctl status suricata
echo "deb http://deb.debian.org/debian bookworm-backports main" | sudo tee /etc/apt/sources.list.d/backports.list && sudo apt install -t bookworm-backports suricataIdentify Your Network Interface
# List active interfaces
ip a
# Find the interface carrying your traffic (usually eth0 or ens3)
ip route get 8.8.8.8 | grep dev
Note the interface name (e.g., eth0 or ens3) — you'll use it in the configuration below.
Configure suricata.yaml
sudo nano /etc/suricata/suricata.yaml
Find and update these key settings:
# 1. Set HOME_NET to your VPS IP/subnet
vars:
address-groups:
HOME_NET: "[YOUR_VPS_IP/32]"
# Example: "[203.0.113.50/32]"
# 2. Set your interface (find the af-packet section)
af-packet:
- interface: eth0 # Replace with your interface name
cluster-id: 99
cluster-type: cluster_flow
defrag: yes
# 3. Enable JSON logging (eve-log)
outputs:
- eve-log:
enabled: yes
filetype: regular
filename: eve.json
types:
- alert:
payload: yes
payload-printable: yes
http-body: yes
- http:
extended: yes
- dns:
query: yes
answer: yes
- tls:
extended: yes
Update Rules with suricata-update
# Download Emerging Threats Open rules (free, no subscription needed)
sudo suricata-update
# List available rule sources
sudo suricata-update list-sources
# Enable ET Pro if you have a subscription
# sudo suricata-update enable-source et/pro --secret-code YOUR_CODE
# Reload rules into the running Suricata process
sudo suricata-update
sudo suricatasc -c reload-rules
echo "0 3 * * * root suricata-update && suricatasc -c reload-rules" | sudo tee /etc/cron.d/suricata-updateRun Suricata in IDS Mode
# Test the configuration before starting
sudo suricata -T -c /etc/suricata/suricata.yaml -v
# Start via systemd (IDS mode — af-packet)
sudo systemctl restart suricata
# Or run manually for debugging
sudo suricata -c /etc/suricata/suricata.yaml -i eth0
# Check stats
sudo suricatasc -c dump-counters | grep -E "decoder|detect|alert"
Switch to IPS Mode with NFQueue
# Install NFQueue kernel support
sudo apt install libnetfilter-queue-dev -y
# Route all traffic through NFQueue queue 0
sudo iptables -I INPUT -j NFQUEUE --queue-num 0 --queue-bypass
sudo iptables -I OUTPUT -j NFQUEUE --queue-num 0 --queue-bypass
sudo iptables -I FORWARD -j NFQUEUE --queue-num 0 --queue-bypass
# Edit suricata.yaml to use NFQueue instead of af-packet:
# nfq:
# mode: accept
# fail-open: yes
# Start Suricata in IPS mode
sudo suricata -c /etc/suricata/suricata.yaml -q 0
# Persist iptables rules across reboots
sudo apt install iptables-persistent -y
sudo netfilter-persistent save
--queue-bypass with NFQueue iptables rules. If Suricata crashes, traffic continues to flow — your VPS won't disconnect.View Alerts and Logs
# Stream alerts in real-time
sudo tail -f /var/log/suricata/eve.json | python3 -c "
import sys, json
for line in sys.stdin:
try:
e = json.loads(line)
if e.get('event_type') == 'alert':
print(f\"{e['timestamp']} [{e['alert']['severity']}] {e['alert']['signature']} {e.get('src_ip','')} -> {e.get('dest_ip','')}\")
except: pass
"
# Read the human-readable fast.log
sudo tail -f /var/log/suricata/fast.log
# Count and rank top alerts today
sudo jq -r 'select(.event_type=="alert") | .alert.signature' /var/log/suricata/eve.json | sort | uniq -c | sort -rn | head -20
Write Custom Detection Rules
# Create a local rules file
sudo nano /etc/suricata/rules/local.rules
# Alert on SSH brute-force attempts from external hosts
alert tcp any any -> $HOME_NET 22 (msg:"SSH Brute Force Attempt"; flags:S; threshold: type both, track by_src, count 5, seconds 60; classtype:attempted-admin; sid:9000001; rev:1;)
# Detect SQL injection patterns in HTTP URIs
alert http any any -> $HOME_NET any (msg:"SQL Injection Attempt"; content:"union select"; nocase; http.uri; classtype:web-application-attack; sid:9000002; rev:1;)
# Add the custom rule file to suricata.yaml under rule-files:
# rule-files:
# - /etc/suricata/rules/local.rules
# Reload rules
sudo suricatasc -c reload-rules
Verify Suricata Is Working Correctly
# 1. Check daemon stats
sudo suricatasc -c dump-counters | grep -E "uptime|alert|decoder"
# 2. Trigger a test alert using a known User-Agent string
curl -sA "BlackSun" http://localhost/ 2>/dev/null
sudo grep "User-Agent" /var/log/suricata/fast.log | tail -5
# 3. Confirm eve.json contains event data
sudo jq '.event_type' /var/log/suricata/eve.json | sort | uniq -c
# 4. View interface capture statistics
sudo suricatasc -c iface-stat eth0
# 5. Confirm the process is running
ps aux | grep suricata
sudo systemctl status suricata --no-pager
sudo suricatasc -c iface-list.Troubleshooting Common Issues
Error: "PCAP packet drop" or unexpectedly low alert counts
Suricata can't keep up with traffic at high throughput. Increase worker threads in suricata.yaml:
# Under threading: in suricata.yaml
threading:
set-cpu-affinity: no
detect-thread-ratio: 1.5
# For af-packet, increase threads per interface
af-packet:
- interface: eth0
threads: 2
cluster-id: 99
cluster-type: cluster_flow
Error: "suricata.service: Start request repeated too quickly"
Suricata is crashing due to a configuration error. Check the logs before restarting:
# View recent error output
sudo journalctl -u suricata -n 50 --no-pager
# Validate config syntax
sudo suricata -T -c /etc/suricata/suricata.yaml -v 2>&1 | grep -E "Error|Warning"
# If you see "Failed to open" — check that rule files exist
ls -la /var/lib/suricata/rules/
sudo suricata-update # Re-download rules
Error: "NFQ queue 0: recv failed" in IPS mode
The NFQueue iptables rule isn't in place, or the required kernel modules aren't loaded:
# Confirm the iptables NFQUEUE rule exists
sudo iptables -L -n | grep NFQUEUE
# Load kernel modules
sudo modprobe nfnetlink_queue
sudo modprobe nf_conntrack
# Run Suricata as root in IPS mode
sudo suricata -c /etc/suricata/suricata.yaml -q 0 --user root
# Enable fail-open to prevent lockout on crash
# In suricata.yaml:
# nfq:
# fail-open: yes
Too many false positives flooding your logs
Suppress specific rules without removing the entire rule set using a threshold config:
# Create or edit the threshold file
sudo nano /etc/suricata/threshold.conf
# Suppress a specific rule by SID
suppress gen_id 1, sig_id 2010935
suppress gen_id 1, sig_id 2010935, track by_src, ip 192.168.1.0/24
# Reload
sudo suricatasc -c reload-rules
# Or disable an entire category via disable.conf
sudo nano /etc/suricata/disable.conf
# Add: re:emerging-scan
Suricata consuming too much RAM on a small VPS
Reduce memory caps for flow tracking and defragmentation:
# In suricata.yaml
flow:
memcap: 64mb # Reduced from default 128mb
hash-size: 65536
prealloc: 10000
stream:
memcap: 64mb
defrag:
memcap: 32mb
# Apply changes
sudo systemctl restart suricata
Frequently Asked Questions
How resource-intensive is Suricata on a budget VPS?
In IDS mode (af-packet), Suricata typically uses 5–15% CPU on a 1–2 vCore VPS and 200–400 MB RAM depending on traffic volume and the number of enabled rules. On a 1 GB RAM VPS, enable only the rule groups relevant to your workload — for example, emerging-web-server and emerging-exploit — and disable unrelated sets with suricata-update disable-source to keep memory usage low.
How does Suricata compare to CrowdSec, and can they work together?
Suricata operates at the network level, inspecting raw packet payloads and protocol fields — ideal for catching exploits and malware C2 traffic that log-based systems miss. CrowdSec is a log-based behavioral analyzer using crowdsourced threat intelligence to block suspicious IPs. They complement each other well: Suricata detects network-level threats and writes to eve.json, while CrowdSec reads Suricata's fast.log and automatically blocks offending IPs.
Can a misconfigured Suricata lock me out of my VPS?
Yes — in NFQueue IPS mode, a misconfigured drop rule or a Suricata crash without --queue-bypass can cut off all traffic. Protect yourself: (1) always add --queue-bypass to your iptables NFQueue rules, (2) set fail-open: yes in suricata.yaml, and (3) always start in IDS mode and test for 1–2 weeks to confirm there are no false positives against your normal traffic before switching to IPS mode.