iptables’ string match extension lets you inspect packet payloads for specific byte sequences.

Let’s see it in action. Imagine you want to block all HTTP requests containing the forbidden GET /admin path. Here’s how you’d do it:

iptables -A INPUT -p tcp --dport 80 -m string --algo kmp --string "GET /admin" -j DROP

This command inserts a new rule into the INPUT chain. It targets TCP packets destined for port 80 (--dport 80). The crucial part is -m string --algo kmp --string "GET /admin". This tells iptables to load the string module, use the Knuth-Morris-Pratt (KMP) algorithm (--algo kmp) for efficient pattern matching, and look for the exact byte sequence "GET /admin" within the packet’s payload. If a match is found, the packet is unceremoniously dropped (-j DROP).

The problem this solves is simple: sometimes, you need to inspect the actual data flowing through the network, not just the headers (like source/destination IP, port, or protocol). Traditional iptables rules are great for network-level filtering, but they can’t see inside the packets. The string match extension bridges this gap, enabling application-layer-aware filtering directly at the firewall.

Internally, the string module works by iterating through the packet’s payload, byte by byte, comparing it against the specified pattern. The KMP algorithm is particularly efficient because it pre-processes the search string to avoid redundant comparisons when a mismatch occurs. It uses a "failure function" (or "LPS array") that tells it how many characters to shift the pattern forward based on the characters that did match before the mismatch. This significantly speeds up the search compared to a naive, brute-force comparison.

You can also use this for more than just blocking. For example, to log all outgoing requests to a specific malicious domain, you might use:

iptables -A OUTPUT -p tcp --dport 80 -m string --algo bm --string "Host: evil.com" -j LOG --log-prefix "EVIL_HOST: "
iptables -A OUTPUT -p tcp --dport 80 -m string --algo bm --string "Host: evil.com" -j ACCEPT

Here, we’re using the Boyer-Moore (bm) algorithm, which is often faster for longer patterns. The first rule logs the packet with a specific prefix, and the second rule accepts it (assuming you don’t want to block it, just monitor it). Notice we have two rules: one for logging and one for the final action. iptables processes rules sequentially, so the log happens first, then the packet is accepted. If you wanted to block after logging, the second rule would be -j DROP.

The --algo option lets you choose between kmp and bm. kmp is generally good for shorter strings and has predictable performance. bm can be faster for longer strings but might have slightly higher setup overhead. For most common use cases, the difference is negligible, and kmp is often the default choice.

You can also match case-insensitively using the -i flag:

iptables -A INPUT -p tcp --dport 80 -m string -i --algo kmp --string "GET /admin" -j DROP

This would also catch get /admin or GeT /AdMiN.

The string match extension is powerful, but it’s not a silver bullet. Inspecting packet payloads adds overhead. For high-throughput systems, excessive or complex string matching can become a performance bottleneck. It’s also important to remember that payloads can be fragmented across multiple packets, and iptables’ string match, by default, only inspects individual packets. For matching across fragments, you’d typically need to reassemble the stream, which is outside the scope of basic iptables and often handled by more advanced tools like IDS/IPS systems.

One aspect often overlooked is the interaction with TLS/SSL. If traffic is encrypted (HTTPS), the string match extension will only be able to see unencrypted parts of the handshake or, if you’re doing SSL interception (which is complex and has security implications), the decrypted payload. For typical HTTPS traffic, string matching on the payload won’t work.

The next challenge you’ll likely face is how to handle matching patterns that span across multiple TCP segments.

Want structured learning?

Take the full Iptables course →