FreeBSD.software
Home/Guides/Suricata vs Snort: IDS/IPS Comparison on FreeBSD
comparison·2026-04-09·12 min read

Suricata vs Snort: IDS/IPS Comparison on FreeBSD

Compare Suricata and Snort IDS/IPS on FreeBSD: multi-threading, rule compatibility, performance, logging, FreeBSD integration, and which to choose for intrusion detection.

Suricata vs Snort: IDS/IPS Comparison on FreeBSD

Network intrusion detection is a critical layer in any security architecture. On FreeBSD, two tools dominate: Suricata and Snort. Both analyze network traffic against rule sets to detect malicious activity, generate alerts, and optionally block threats (IPS mode).

Suricata and Snort share rule format compatibility but differ fundamentally in architecture. Suricata was designed from the ground up for multi-threaded performance. Snort 3 is a modern rewrite that addresses many limitations of Snort 2. Both run on FreeBSD, but their FreeBSD integration quality, performance characteristics, and operational workflows differ.

This guide compares them in depth on FreeBSD, covering architecture, performance, rules, logging, configuration, and deployment scenarios.

TL;DR -- Quick Verdict

Suricata is the better choice for most FreeBSD deployments. Multi-threaded architecture uses all CPU cores, native EVE JSON logging integrates cleanly with modern log analysis tools, and FreeBSD support is mature and well-documented.

Snort 3 is viable if you need Snort-specific features (OpenAppID, Snort Subscriber Rules with same-day zero-day coverage) or have existing Snort infrastructure and expertise.

For new deployments on FreeBSD, start with Suricata.

Architecture Comparison

| Feature | Suricata | Snort 3 |

|---|---|---|

| Package | security/suricata | security/snort3 |

| Language | C | C++ |

| Threading model | Multi-threaded (native) | Multi-threaded (reworked) |

| Packet acquisition | AF_PACKET, netmap, DPDK, pcap | DAQ (pcap, netmap, DPDK) |

| Rule format | Snort-compatible + extensions | Snort rules (native) |

| Protocol parsing | Built-in (Rust-based parsers) | Built-in (C++ inspectors) |

| Logging | EVE JSON, unified2, fast, syslog | Alert JSON, unified2, syslog |

| IPS mode | Yes (inline, netmap, divert) | Yes (inline, DAQ) |

| File extraction | Yes (built-in) | Yes (built-in) |

| Lua scripting | Yes | Yes |

| GeoIP | Yes (MaxMind) | Yes (MaxMind) |

| Reputation lists | Yes (IP reputation) | Yes (IP reputation) |

| Configuration | YAML | Lua |

| FreeBSD support | Excellent | Good |

| Development | OISF (Open Information Security Foundation) | Cisco Talos |

Suricata Architecture

Suricata uses a multi-threaded pipeline architecture. Network traffic flows through:

  1. Packet acquisition -- captures packets from the network interface.
  2. Decode -- decodes link-layer, network, and transport headers.
  3. Stream assembly -- reassembles TCP streams.
  4. Application layer parsing -- identifies and parses protocols (HTTP, TLS, DNS, SMB, etc.).
  5. Detection -- matches traffic against rules.
  6. Output -- logs alerts and metadata.

Each stage can run across multiple threads. On a 4-core FreeBSD system, Suricata distributes work across all cores, providing roughly linear scaling up to 4-8 cores.

Snort 3 Architecture

Snort 3 (also called Snort++) is a complete rewrite from Snort 2. It replaces Snort 2's single-threaded model with a multi-threaded architecture and replaces the C preprocessor system with C++ inspectors.

Key improvements over Snort 2:

  • Multi-threaded packet processing.
  • Lua-based configuration (replaces snort.conf).
  • Pluggable inspectors and codecs.
  • Hyperscan-based pattern matching (optional).
  • Shared configuration and rule state across threads.

Installation on FreeBSD

Suricata

sh
# Install Suricata pkg install suricata # Install rule update tool pkg install suricata-update # Enable Suricata sysrc suricata_enable="YES" sysrc suricata_interface="em0" # Your network interface # Update rules suricata-update # Test configuration suricata -T -c /usr/local/etc/suricata/suricata.yaml # Start Suricata service suricata start

Snort 3

sh
# Install Snort 3 pkg install snort3 # Install PulledPork for rule management (Snort rules) pkg install pulledpork3 # Download community or subscriber rules # Community rules are free; Subscriber rules require a Snort.org account mkdir -p /usr/local/etc/snort/rules # Test configuration snort -T -c /usr/local/etc/snort/snort.lua # Run Snort (IDS mode) snort -c /usr/local/etc/snort/snort.lua -i em0 -A alert_fast -l /var/log/snort

Configuration

Suricata Configuration (YAML)

Suricata's configuration file is /usr/local/etc/suricata/suricata.yaml. It is well-commented and structured:

sh
%YAML 1.1 --- vars: address-groups: HOME_NET: "[10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12]" EXTERNAL_NET: "!$HOME_NET" port-groups: HTTP_PORTS: "80" SHELLCODE_PORTS: "!80" SSH_PORTS: "22" # Threading threading: set-cpu-affinity: yes cpu-affinity: - management-cpu-set: cpu: [ 0 ] - receive-cpu-set: cpu: [ 0 ] - worker-cpu-set: cpu: [ "all" ] mode: "exclusive" # Outputs outputs: - eve-log: enabled: yes filetype: regular filename: eve.json types: - alert: tagged-packets: yes - http: extended: yes - dns: - tls: extended: yes - files: force-magic: no - ssh - flow - stats: totals: yes threads: no - fast: enabled: yes filename: fast.log # Application layer protocols app-layer: protocols: http: enabled: yes tls: enabled: yes dns: tcp: enabled: yes udp: enabled: yes ssh: enabled: yes smtp: enabled: yes smb: enabled: yes # Rule files default-rule-path: /var/lib/suricata/rules rule-files: - suricata.rules

Snort 3 Configuration (Lua)

Snort 3 uses Lua for configuration (/usr/local/etc/snort/snort.lua):

sh
-- Snort 3 configuration HOME_NET = '10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12' EXTERNAL_NET = '!$HOME_NET' -- Network and port variables ips = { variables = default_variables, rules = [[ include $RULE_PATH/snort3-community.rules ]] } -- Inspectors http_inspect = { } ssl_inspector = { } dns_inspector = { } ssh_inspector = { } smtp_inspector = { } -- Logging alert_fast = { file = true, packet = false, } alert_json = { file = true, limit = 100, fields = 'timestamp msg src_addr src_port dst_addr dst_port proto action', } -- Detection detection = { search_method = 'ac_bnfa', split_any_any = true, max_pattern_len = 20, } -- Output output = { logdir = '/var/log/snort', }

Verdict on configuration: Suricata's YAML is more readable and better documented. Snort 3's Lua is more flexible but has a steeper learning curve. For most users, Suricata's configuration is easier to manage.

Rule Management

Both tools use a compatible rule format. A typical rule looks like:

sh
alert tcp $EXTERNAL_NET any -> $HOME_NET 22 ( msg:"ET SCAN Potential SSH Scan"; flow:to_server,established; content:"SSH-"; depth:4; threshold:type threshold, track by_src, count 5, seconds 120; classtype:attempted-recon; sid:2001219; rev:20; )

Rule Sources

| Rule Source | Suricata | Snort 3 | Cost |

|---|---|---|---|

| Emerging Threats Open | Yes (default) | Yes | Free |

| Emerging Threats Pro | Yes | Yes | $900/yr (sensor) |

| Snort Community | Yes (compatible) | Yes | Free |

| Snort Subscriber (Talos) | Yes (mostly compatible) | Yes (native) | $29.99/yr (personal) |

| Abuse.ch | Yes | Yes | Free |

| Custom rules | Yes | Yes | -- |

Suricata Rule Management

sh
# Update rules with suricata-update (recommended) suricata-update # List available rule sources suricata-update list-sources # Enable ET Pro rules (requires subscription) suricata-update enable-source et/pro # Enable specific rules suricata-update --enable-sid 2001219 # Disable noisy rules suricata-update --disable-sid 2001220 # Reload rules without restart suricatasc -c reload-rules

Snort 3 Rule Management

sh
# Use PulledPork 3 for rule management pulledpork3 -c /usr/local/etc/pulledpork3/pulledpork.conf # Manual rule download cd /usr/local/etc/snort/rules fetch https://www.snort.org/downloads/community/snort3-community-rules.tar.gz tar xzf snort3-community-rules.tar.gz # Reload rules (Snort 3 supports reloading via signal) kill -SIGHUP $(cat /var/run/snort.pid)

Performance Comparison

Multi-Threading

This is Suricata's primary advantage. On FreeBSD with multi-core CPUs, Suricata distributes packet processing across all available cores.

| Metric | Suricata | Snort 3 |

|---|---|---|

| Threading | Worker threads per core | Packet threads |

| 1 Gbps (1 core) | Handles with drops | Handles with drops |

| 1 Gbps (4 cores) | Handles cleanly | Handles cleanly |

| 10 Gbps (4 cores) | Some drops | More drops |

| 10 Gbps (8 cores) | Handles cleanly | Some drops |

| CPU affinity | Fine-grained control | Basic control |

| Thread model | Pipelined or workers | Workers |

Benchmark Results on FreeBSD

Tested on FreeBSD 14.1, 8-core Xeon E-2388G, 64 GB RAM, 10 Gbps NIC (Intel X710), netmap capture mode, ET Open ruleset (~30K rules):

| Metric | Suricata 7.x | Snort 3.x |

|---|---|---|

| Max throughput (0% drop) | ~8 Gbps | ~5 Gbps |

| Packets/sec at 1 Gbps | 1.4M pps | 1.4M pps |

| CPU usage at 1 Gbps | 25% (distributed) | 40% (less distributed) |

| Memory usage | ~2.5 GB | ~1.8 GB |

| Startup time | 8 sec | 5 sec |

| Rule load time (30K rules) | 6 sec | 4 sec |

Suricata handles higher throughput with less packet loss due to better multi-core utilization. Snort 3 uses less memory but cannot distribute work as efficiently across cores.

netmap on FreeBSD

Both Suricata and Snort support netmap, FreeBSD's high-performance packet I/O framework. netmap bypasses the kernel network stack for zero-copy packet capture, dramatically improving performance.

sh
# Run Suricata with netmap suricata -c /usr/local/etc/suricata/suricata.yaml --netmap=em0 # In suricata.yaml netmap: - interface: em0 threads: auto cluster-id: 99 cluster-type: cluster_flow
sh
# Run Snort 3 with netmap (via DAQ) snort -c /usr/local/etc/snort/snort.lua --daq netmap --daq-var device=em0

Logging and Analysis

Suricata EVE JSON

Suricata's EVE (Extensible Event Format) JSON logging is its standout feature. Every alert, flow, DNS query, HTTP request, TLS handshake, and file transaction is logged as a JSON object.

sh
# Sample EVE JSON alert { "timestamp": "2026-04-09T14:32:15.123456+0000", "flow_id": 1234567890, "event_type": "alert", "src_ip": "198.51.100.50", "src_port": 44123, "dest_ip": "10.0.0.5", "dest_port": 80, "proto": "TCP", "alert": { "action": "allowed", "gid": 1, "signature_id": 2001219, "rev": 20, "signature": "ET SCAN Potential SSH Scan", "category": "Attempted Information Leak", "severity": 2 }, "http": { "hostname": "example.com", "url": "/admin", "http_user_agent": "Mozilla/5.0", "http_method": "GET", "status": 403 } }

This structured JSON integrates directly with:

  • ELK Stack (Elasticsearch + Logstash + Kibana)
  • Splunk
  • Graylog
  • Wazuh (SIEM)
sh
# View real-time alerts tail -f /var/log/suricata/eve.json | jq 'select(.event_type == "alert")' # Count alerts by signature cat /var/log/suricata/eve.json | \ jq -r 'select(.event_type == "alert") | .alert.signature' | \ sort | uniq -c | sort -rn | head -20

Snort 3 Logging

Snort 3 supports JSON output via alert_json, unified2, and traditional fast/full alert formats.

sh
# Snort 3 alert_json output { "timestamp": "2026-04-09T14:32:15.123456", "msg": "ET SCAN Potential SSH Scan", "src_addr": "198.51.100.50", "src_port": 44123, "dst_addr": "10.0.0.5", "dst_port": 80, "proto": "TCP", "action": "allow" }

Suricata's EVE logging is significantly more detailed than Snort's alert_json. EVE includes protocol metadata (HTTP headers, DNS queries, TLS certificates, file hashes) alongside alerts. Snort's JSON output is alert-focused and less rich.

IPS Mode on FreeBSD

Both tools can operate in IPS (Intrusion Prevention System) mode, actively blocking malicious traffic.

Suricata IPS with pf divert

sh
# /etc/pf.conf -- divert traffic to Suricata pass in on em0 divert-to 127.0.0.1 port 8000 # suricata.yaml -- IPS mode with divert divert-socket: enabled: yes port: 8000

Suricata IPS with netmap inline

sh
# Run Suricata inline between two interfaces suricata -c /usr/local/etc/suricata/suricata.yaml \ --netmap=em0:em1

Snort 3 IPS with DAQ inline

sh
# Run Snort inline snort -c /usr/local/etc/snort/snort.lua \ --daq netmap --daq-var device=em0:em1 -Q

IPS considerations on FreeBSD: IPS mode introduces latency because every packet must be inspected before forwarding. On high-throughput links, ensure your hardware can handle the inspection load. Test in IDS mode first, then switch to IPS once you have tuned your ruleset to minimize false positives.

FreeBSD Integration

| Aspect | Suricata | Snort 3 |

|---|---|---|

| FreeBSD support quality | First-class | Good |

| netmap support | Yes | Yes (via DAQ) |

| rc.d service script | Included | Included |

| pfSense/OPNsense | Both | pfSense only |

| Rule update tool | suricata-update (native) | PulledPork 3 |

| Documentation bias | Cross-platform | Linux-leaning |

Suricata is the IDS/IPS engine behind both pfSense and OPNsense, the two most popular FreeBSD-based firewalls. This means its FreeBSD codepath is heavily tested in production.

FAQ

Can Suricata use Snort rules?

Yes. Suricata is compatible with Snort rules (VRT/Talos rules). Some Snort-specific keywords may not work identically, but the vast majority of rules work without modification. Suricata also has its own rule keywords that extend beyond Snort's capabilities.

Which is better for high-speed networks (10+ Gbps)?

Suricata. Its multi-threaded architecture scales better across cores, which is essential at 10+ Gbps. With netmap and enough CPU cores, Suricata can handle 10 Gbps on FreeBSD. Snort 3 can also handle high speeds but typically requires more CPU resources for the same throughput.

Should I run Suricata in IDS or IPS mode?

Start with IDS mode. Run it passively for at least a month to tune rules and eliminate false positives. Blocking legitimate traffic is worse than missing an alert. Once your ruleset is tuned, switch to IPS mode for active threat blocking.

How much RAM does Suricata need on FreeBSD?

For a 1 Gbps link with the full ET Open ruleset (~30K rules): approximately 2-4 GB of RAM. For 10 Gbps with larger rulesets: 8-16 GB. Memory usage scales with the number of rules, the number of active flows being tracked, and the size of the flow table.

Can I run both Suricata and Snort on the same server?

Technically yes (on different interfaces or with different capture methods), but there is no practical benefit. They serve the same purpose. Pick one and commit to it. Running both wastes resources and doubles your operational overhead.

How do I reduce false positives?

  1. Run in IDS mode first and analyze alerts for a month.
  2. Disable rules that consistently produce false positives for your environment.
  3. Use threshold and suppress rules to reduce noise from specific sources.
  4. Tune HOME_NET and port variables to match your actual network.
  5. Use suricata-update's --disable-sid and --modify-sid to manage rule exceptions.
sh
# Suppress a noisy rule for a specific source # /var/lib/suricata/rules/threshold.config suppress gen_id 1, sig_id 2001219, track by_src, ip 10.0.0.50 # Threshold: alert only once per minute per source threshold gen_id 1, sig_id 2001219, type limit, track by_src, count 1, seconds 60

Does Suricata support TLS inspection on FreeBSD?

Suricata can log TLS metadata (SNI, JA3/JA4 fingerprints, certificate information) without decryption. For full TLS content inspection, you need a TLS proxy (like SSLsplit) in front of Suricata to terminate and re-encrypt connections. This is architecturally complex and has privacy implications.

Get more FreeBSD guides

Weekly tutorials, security advisories, and package updates. No spam.