Hacktricks-skills suricata-iptables-forensics

Configure and use Suricata IDS/IPS and iptables for network security forensics. Use this skill whenever you need to set up network intrusion detection, create firewall rules, write Suricata signatures, block suspicious traffic, analyze network packets, or configure network security monitoring. Trigger this skill for any task involving iptables chains, Suricata rules, network filtering, packet inspection, or security rule creation.

install
source · Clone the upstream repo
git clone https://github.com/abelrguezr/hacktricks-skills
manifest: skills/generic-methodologies-and-resources/basic-forensic-methodology/pcap-inspection/suricata-and-iptables-cheatsheet/SKILL.MD
source content

Suricata & Iptables Forensics Skill

This skill helps you configure and use Suricata (IDS/IPS) and iptables for network security forensics and monitoring.

Quick Start

Iptables Basics

Iptables uses chains to process rules sequentially. Three primary chains are always present:

  • INPUT: Incoming connections to the local system
  • FORWARD: Traffic passing through (routers, NAT)
  • OUTPUT: Outgoing connections from the system

Common Iptables Commands

# Delete all rules
iptables -F

# List all rules
iptables -L
iptables -S

# Block IP addresses
iptables -I INPUT -s 192.168.1.100 -j DROP
iptables -I INPUT -s 10.0.0.5,10.0.0.6 -j DROP

# Block ports
iptables -I INPUT -p tcp --dport 443 -j DROP
iptables -I INPUT -p tcp --dport 8000 -j DROP

# Block specific IP on specific port
iptables -I INPUT -s 192.168.1.100 -p tcp --dport 443 -j DROP

# String-based drop (case sensitive)
iptables -I INPUT -p tcp --dport 80 -m string --algo bm --string 'CTF{' -j DROP
iptables -I OUTPUT -p tcp --sport 80 -m string --algo bm --string 'CTF{' -j DROP

# Default drop, allow specific ports
iptables -P INPUT DROP
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
iptables -I INPUT -p tcp --dport 443 -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -j ACCEPT

Persist Iptables Rules

Debian/Ubuntu:

apt-get install iptables-persistent
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
iptables-restore < /etc/iptables/rules.v4

RHEL/CentOS:

iptables-save > /etc/sysconfig/iptables
ip6tables-save > /etc/sysconfig/ip6tables
iptables-restore < /etc/sysconfig/iptables

Suricata Setup

Installation

Ubuntu:

add-apt-repository ppa:oisf/suricata-stable
apt-get update
apt-get install suricata

Debian:

echo "deb http://http.debian.net/debian buster-backports main" > /etc/apt/sources.list.d/backports.list
apt-get update
apt-get install suricata -t buster-backports

CentOS:

yum install epel-release
yum install suricata

Get and Configure Rules

# Get rules
suricata-update
suricata-update list-sources
suricata-update enable-source et/open
suricata-update

# Update /etc/suricata/suricata.yaml:
default-rule-path: /var/lib/suricata/rules
rule-files:
  - suricata.rules

Run Suricata

# Start service
systemctl suricata start

# Run manually on interface
suricata -c /etc/suricata/suricata.yaml -i eth0

# Validate config
suricata -T -c /etc/suricata/suricata.yaml -v

# Reload rules
suricatasc -c ruleset-reload-nonblocking

Configure as IPS (Inline Mode)

  1. Edit
    /etc/suricata/suricata.yaml
    - find and uncomment:
drop:
  alerts: yes
  flows: all
  1. Forward packets to Suricata queue:
iptables -I INPUT -j NFQUEUE
iptables -I OUTPUT -j NFQUEUE
  1. Start Suricata in IPS mode:
suricata -c /etc/suricata/suricata.yaml -q 0

Or edit the service:

systemctl edit suricata.service

Add:

[Service]
ExecStart=
ExecStart=/usr/bin/suricata -c /etc/suricata/suricata.yaml --pidfile /run/suricata.pid -q 0 -vvv
Type=simple

Then:

systemctl daemon-reload
systemctl restart suricata

Writing Suricata Rules

Rule Structure

A Suricata rule has three parts:

  1. Action: What to do when matched (alert, drop, pass, reject)
  2. Header: Protocol, IPs, ports, direction
  3. Options: Specific matching criteria

Valid Actions

ActionDescription
alert
Generate an alert
pass
Stop further inspection
drop
Drop packet and generate alert
reject
Send RST/ICMP error to sender
rejectsrc
Same as reject
rejectdst
Send error to receiver
rejectboth
Send errors to both sides

Protocols

  • tcp
    ,
    udp
    ,
    icmp
    ,
    ip
    (any/all)
  • Layer 7:
    http
    ,
    ftp
    ,
    tls
    ,
    smb
    ,
    dns
    ,
    ssh

IP Address Syntax

ExampleMeaning
!1.1.1.1
Every IP except 1.1.1.1
![1.1.1.1, 1.1.1.2]
Every IP except these two
$HOME_NET
Defined in yaml config
[$EXTERNAL_NET, !$HOME_NET]
External but not home
[10.0.0.0/24, !10.0.0.5]
Subnet except one IP

Port Syntax

ExampleMeaning
any
Any port
[80, 81, 82]
Ports 80, 81, 82
[80:82]
Range 80-82
[1024:]
1024 and above
!80
Every port except 80
[80:100,!99]
80-100 except 99

Direction

source -> destination  (one way)
source <> destination  (both ways)

Common Keywords

Meta Keywords:

msg: "description"           # Rule description
sid: 123                     # Unique rule ID
rev: 1                       # Revision number
classtype: bad-unknown       # Classification
reference: url, www.info.com # Reference URL
priority: 1                  # Priority level

Content Matching:

content: "something"         # String match
content: |61 61 61|          # Hex: AAA
content: "http|3A|//"        # Mixed string/hex
content: "abc"; nocase;      # Case insensitive

Replace (IPS mode):

content: "abc"; replace: "def"  # Must be same length

Regex:

pcre: "/<regex>/opts"
pcre: "/NICK .*USA.*[0-9]{3,}/i"

Geolocation:

geoip: src,RU  # Match source from Russia

ICMP:

itype: <10    # ICMP type less than 10
icode: 0      # ICMP code

Rule Examples

Basic Alert

alert http $HOME_NET any -> $EXTERNAL_NET any (
  msg:"HTTP GET Request Containing Rule in URI";
  flow:established,to_server;
  http.method; content:"GET";
  http.uri; content:"rule";
  fast_pattern;
  classtype:bad-unknown;
  sid:123;
  rev:1;
)

Drop by Port

drop tcp any any -> any 8000 (
  msg:"Block port 8000";
  sid:1000;
)

String Detection

alert tcp any any -> any any (
  msg:"PHP RCE Attempt";
  content:"eval";
  nocase;
  metadata: tag php-rce;
  sid:101;
  rev:1;
)

Regex Detection

drop tcp any any -> any any (
  msg:"CTF Flag Pattern";
  pcre:"/CTF\{[\w]{3,}/i";
  sid:10001;
)

Content Replace

alert tcp any any -> any any (
  msg:"Flag Replace";
  content:"CTF{a6st";
  replace:"CTF{u798";
  nocase;
  sid:100;
  rev:1;
)

Common Use Cases

Block CTF Flag Exfiltration

# Iptables
iptables -I OUTPUT -p tcp -m string --algo bm --string 'CTF{' -j DROP

# Suricata
drop tcp any any -> any any (
  msg:"CTF Flag Exfiltration";
  pcre:"/CTF\{[\w\-]{3,}/i";
  sid:20001;
)

Block SQL Injection Attempts

alert http any any -> any any (
  msg:"SQL Injection Attempt";
  http.method; content:"GET";
  http.uri; content:"'"; content:"OR"; nocase;
  classtype:web-application-attack;
  sid:30001;
)

Allowlist Specific IPs

iptables -P INPUT DROP
iptables -I INPUT -s 192.168.1.0/24 -j ACCEPT
iptables -I INPUT -s 10.0.0.0/8 -j ACCEPT
iptables -I INPUT -p tcp --dport 22 -j ACCEPT

Troubleshooting

Suricata

# Check status
systemctl status suricata

# View logs
tail -f /var/log/suricata/eve.json

# Test config
suricata -T -c /etc/suricata/suricata.yaml -v

# Check rule syntax
suricata -T -c /etc/suricata/suricata.yaml

Iptables

# Count matches
iptables -L -v -n

# Save current rules
iptables-save > /tmp/backup.rules

# Restore from backup
iptables-restore < /tmp/backup.rules

# Flush all rules (careful!)
iptables -F

Best Practices

  1. Test rules before deploying - Use
    alert
    before
    drop
    to verify matching
  2. Use descriptive messages - Include context in
    msg:
    field
  3. Set unique SIDs - Avoid conflicts with existing rules
  4. Document rule purpose - Add comments or metadata
  5. Monitor false positives - Review alerts before enabling drop actions
  6. Backup before changes - Save iptables rules before modifying
  7. Use fast_pattern - For performance on frequently matched content
  8. Test in staging - Validate IPS rules before production deployment