Skip to content
Learni
View all tutorials
Sécurité Informatique

How to Configure Advanced Snort 3 IDS in 2026

Lire en français

Introduction

Snort 3, the major evolution of the renowned open-source intrusion detection system, provides real-time network attack detection using signature-based rules and stateful analysis. In 2026, with rising zero-day and IoT threats, setting up an advanced Snort 3 is essential for SecOps teams. This tutorial walks you through every step: source installation on Ubuntu, tuning preprocessors (stream5, http_inspect), custom rules for APTs, JSON outputs for SIEM, and performance optimization (multithreading). Think of Snort as a vigilant guardian sifting traffic like a fine mesh to catch subtle anomalies. By the end, you'll have a production-ready, scalable IDS handling 10Gbps+—bookmark for reference.

Prerequisites

  • Ubuntu 22.04 LTS or 24.04 server with at least 4 cores, 8GB RAM, and a dedicated network interface (e.g., eth1).
  • Root access (sudo).
  • Advanced knowledge of Linux, TCP/IP, regex, and Lua (for Snort 3).
  • Tools: git, cmake, flex, bison, libpcap-dev.
  • Test interface: traffic generator like Scapy or nmap installed.

Installing Dependencies and Snort 3 from Source

install-snort3.sh
#!/bin/bash
apt update && apt upgrade -y
apt install -y build-essential cmake cpputest libpcap-dev libpcre2-dev libnet1-dev zlib1g-dev luajit hwloc libdnet-dev libdumbnet-dev bison flex liblzma-dev openssl libssl-dev pkg-config libhwloc-dev libluajit-5.1-dev libunwind-dev libcmocka-dev
cd /opt
git clone https://github.com/snort3/snort3.git
cd snort3
./configure_cmake.sh --prefix=/usr/local --enable-tsc-clock
git clone https://github.com/snort3/extra.git
cd extra
./configure_cmake.sh --prefix=/usr/local --with-snort3
cd ../src
cmake -B build -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release
cmake --build build --target snort3 --parallel
cmake --install build
cd ../extra
cmake -B build -DCMAKE_INSTALL_PREFIX=/usr/local -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel
cmake --install build

This script installs all critical dependencies for Snort 3 (LuaJIT for scripting, hwloc for CPU affinity) and compiles from source for the latest 2026 features. Use --enable-tsc-clock for precise high-performance timestamps. Avoid outdated APT packages; building from source ensures recent kernel compatibility and optimizations.

Verification and Initial Configuration

After installation, verify with snort -V (should show 3.1+). Copy configs: cp /usr/local/etc/snort/*.lua /etc/snort/. Edit /etc/snort/snort.lua to set HOME_NET (your subnet, e.g., "192.168.1.0/24"), EXTERNAL_NET ("any"). Enable multithreading with cpu = { priority = 1 }. This foundation sets up a stateful IDS.

Main Configuration: snort.lua

/etc/snort/snort.lua
ips = {
  mode = inline,
  variables = default_variables,
  include = 'lua/snort_defaults.lua',
}
HOME_NET = '192.168.1.0/24'
EXTERNAL_NET = '!$HOME_NET'
ports = {
  http = 80,
  http2 = 8080,
  mysql = 3306,
  ssh = 22,
}
ipvar dns_servers [8.8.8.8,8.8.4.4]
ips =
{
  rules = [[ include /etc/snort/rules ]],
  enable_builtin_rules = true,
}
stream =
{
  variables =
    default_variables,
  tcp = { memcap = 4194304 },
}
appid =
{
  app_detector_dir = '/usr/local/lib',
  categories =
  {
    default = 1,
  },
}
http_inspect =
{
  global =
  {
    max_concurrent_sessions = 8388608,
  },
}
packet_tracer = { enable = true }
process =
{
  trace_level = 1,
  trace_log = '/var/log/snort/packet_trace.log',
}

This central Lua file configures Snort 3: defines networks, enables inline IPS (blocks vs. alerts), stream for TCP reassembly, appid for L7 inspection, and http_inspect for HTTP anomalies. memcap limits memory; adjust for >1Gbps. Pitfall: forgetting appid throttles protocol detection.

Custom Local Rules

/etc/snort/rules/local.rules
alert tcp $EXTERNAL_NET any -> $HOME_NET 22 (msg:"SSH Brute Force Attempt"; flow:to_server,established; content:"SSH-"; threshold:type both, track by_src, count 5, seconds 60; sid:1000001; rev:1;)

alert http $EXTERNAL_NET any -> $HOME_NET any (msg:"SQL Injection Attempt"; flow:to_server,established; http.uri; content:"union select"; nocase; http.method; content:"GET|20|"; sid:1000002; rev:1; metadata:service http;)

drop tcp $EXTERNAL_NET any -> $HOME_NET 445 (msg:"SMB Exploit EternalBlue"; content:"|FF|SMB|25|`; flow:to_server,established; sid:1000003; rev:1;)

alert icmp $EXTERNAL_NET any -> $HOME_NET any (msg:"ICMP Ping Flood"; itype:8; threshold:type threshold, track by_dst, count 100, seconds 10; sid:1000004; rev:1;)

Custom rules for common threats: SSH brute-force (threshold), SQLi over HTTP, EternalBlue SMB, ICMP flood. Use drop for IPS blocking. Unique SIDs >1000000 avoid conflicts. Test with snort -R local.rules -r test.pcap; nocase regex ignores case.

Enabling Advanced Preprocessors

stream_tcp preprocessor reassembles TCP to detect evasion via fragmentation, like piecing together a puzzle. appid identifies apps (e.g., Tor), http_inspect parses headers for anomalies (oversize POSTs). In snort.lua, link them via binder for zone-specific policies. This elevates Snort from a basic sniffer to a contextual IDS.

Binder Configuration for Policies

/etc/snort/binds.lua
binder =
{
  { when = { proto = 'http' }, use = { type = 'policy', policy_id = 0 } },
  { when = { service = 'ssh' }, use = { type = 'policy', policy_id = 1 } },
  { when = { nets = '$HOME_NET' }, use = { type = 'policy', policy_id = 0 } },
  { when = { role = 'server' }, use = { type = 'policy', policy_id = 1 } },
}
policy_0 =
{
  ips = { rules = '/etc/snort/rules/policy0.rules' },
}
policy_1 =
{
  ips = { rules = '/etc/snort/rules/policy1.rules' },
  stream = { tcp = { memcap = 10485760 } },
}

Binder applies dynamic policies by proto/service/net/role, optimizing resources (policy1 for high-mem servers). Create policy0.rules/policy1.rules. Benefit: multi-tenant scalability. Pitfall: non-suppressive policies cause false positives; suppress via suppress.gen.

JSON Outputs for SIEM and Alerts

/etc/snort/alerts.lua
alert_json =
{
  limit = 1000,
  pkt_num = true,
  src_addr = true,
  dst_addr = true,
  src_port = true,
  dst_port = true,
  proto = true,
  action = true,
  details = true,
  msg = true,
  class = true,
  priority = true,
  rev = true,
  rule = true,
  time_stamp = true,
  file = true,
}
alert_full = { log = true, packet = true }
logfile = { file = true, limit_size = '10 MB', pkt_num = true }
packet_log = { file = '/var/log/snort/pkts.log', link_type = 'pcap' }

Configures structured JSON outputs for ELK/Splunk ingestion, with RFC3339 timestamps and full packet capture. limit_size auto-rotates logs. Integrate with ELK via Filebeat. Avoid obsolete unified2; JSON is native to Snort 3.

Running in Daemonized IDS Mode

start-snort.sh
#!/bin/bash
mkdir -p /var/log/snort
chown snort:snort /var/log/snort
snort -c /etc/snort/snort.lua -i eth1 -A alert_json:alert.json -l /var/log/snort --daq afpacket -daq-mode read-file -daq-var buffer_size=65536 --daq-dir /usr/local/lib/daq --lua "ips.rules = '/etc/snort/rules/*.rules'" --enable-inline -Q --daq afpacket -i eth1:eth1 -q &
echo $! > /var/run/snort.pid
systemctl daemon-reload
cat <<EOF > /etc/systemd/system/snort.service
[Unit]
Description=Snort 3 IDS
After=network.target
[Service]
ExecStart=/usr/local/bin/snort -c /etc/snort/snort.lua -i eth1 -A alert_json -l /var/log/snort --daq afpacket --enable-inline -Q
Restart=always
User=snort
[Install]
WantedBy=multi-user.target
EOF
systemctl enable snort
systemctl start snort

Launches Snort as a daemon on eth1 with DAQ afpacket (zero-copy high-perf), inline queue (-Q) for IPS. Creates persistent systemd service. --lua overrides rules at runtime. Test: tail -f /var/log/snort/alert.json. Pitfall: wrong DAQ causes drops; monitor with snort -T.

Testing and Validation

Generate malicious traffic: nmap -sS -p22 192.168.1.10 (5x for threshold). Check JSON alerts: jq . /var/log/snort/alert.json. Use snort -r capture.pcap -c snort.lua -A cmg for offline analysis. Perf: snort_stats shows drops/Mbps.

Best Practices

  • Performance tuning: Use hwloc for CPU pinning (e.g., cores 4-7), DAQ afpacket with RSS hash for 10G+.
  • Hierarchical rules: Use include + SIDs for staging (test -> prod).
  • FP suppression: suppress.gen by IP/proto instead of disabling rules.
  • State backup: Rotate pcap/logs with logrotate, integrate with ELK for correlation.
  • Updates: Cron script to pull Snort rules via Oinkcode Talos.

Common Errors to Avoid

  • Forgetting DAQ compilation: Snort crashes on afpacket; always use ./configure_cmake.sh --enable-large-pcap.
  • Misdefined HOME_NET: Alerts on legit traffic; use dynamic ipvar.
  • No stream reassembly: Frag evasion; force stream_tcp.invalidate = fragments.
  • Unrotated logs: Fills /var/log causing Snort crash; set max_file_size.

Next Steps

Dive into Snort 3 Lua plugins for ML-based anomaly detection. Resources: Official Snort Docs, Snort3 GitHub. Benchmark with Suricata. Check out our advanced cybersecurity training at Learni for SANS/GCIH certs.