๐ก Netfilter Regex
July 23, 2026 ยท View on GitHub
Netfilter Regex (nfregex) filters network traffic by matching regular expressions directly against packet content, entirely inside a C++ binary (no embedded interpreter, no user-supplied code). It's the fastest filtering module Firegex offers, at the cost of flexibility: if you need custom logic (parsing structured data, stateful decisions, mangling packets), use Netfilter Proxy instead.
How to use it
- Create a service: pick a protocol (
tcporudp), the targetip:port(or attach it to a TLS Decrypt stream, to see decrypted traffic,tcponly), and a name. - Add one or more regexes to the service.
- Start the service. Matching traffic is dropped/rejected according to each regex's direction; everything else passes through unmodified โ nfregex has no mangling capability (only Netfilter Proxy can mangle traffic).
Each regex has:
- Pattern: a PCRE2-compatible regular expression, matched as raw bytes (not text) against the traffic.
- Direction (
mode):Sโ match only client โ server traffic (to the server);Cโ match only server โ client traffic (to the client);Bโ match both directions. - Case sensitivity: matching can be case-sensitive or case-insensitive per regex.
- Active/inactive: a regex can be disabled without deleting it โ inactive regexes are kept (and still shown with their stats) but never evaluated against traffic.
The service page shows, per regex, how many packets it has blocked so far, and whether it's currently active.
fail_open (an advanced per-service option, shared with nfproxy) controls what happens if the underlying nfqueue/binary can't be reached: if enabled, traffic is allowed through unfiltered rather than blocked.
TCP vs UDP matching
- TCP: nfregex reassembles and reorders the stream before matching, so a regex can match a pattern that's split across multiple packets. Out-of-order packets are handled transparently.
- UDP: there's no stream to reassemble โ each datagram is matched independently, and only the match context (not the full payload) is retained afterwards.
How it works
The packet filtering process is implemented in C++ and involves several key steps:
- Packet interception: the nfqueue kernel module intercepts network packets (a netfilter module) ๐. The rules attaching nfqueue to the traffic are generated via the nftables JSON API by the Python manager.
- Packet reading: a dedicated thread reads packets from nfqueue. ๐งต
- Packet parsing: intercepted packets are parsed by libtins, a C++ library that extracts the payload from each packet. ๐
- Multi-threaded analysis: multiple threads analyze packets concurrently. While the nfqueue module balances load based solely on IP addresses โ resulting in a single thread handling all traffic in NAT environments like CTF networks โ Firegex manages threads at the user level differently: traffic is routed based on IP addresses combined with port hashing, giving a more balanced workload while guaranteeing that a given flow is always analyzed by the same thread. โก๏ธ
- TCP handling: for TCP connections, libtins uses a TCP follower to reorder packets received from the kernel. ๐
- Regex matching: the extracted payload is matched using vectorscan โ a fork of hyperscan that also runs on arm64. ๐ฏ