The most surprising thing about iptables L7 filtering is that it doesn’t actually do L7 filtering itself; it relies on a separate kernel module and user-space helper.
Let’s see it in action. Imagine you want to block BitTorrent traffic. First, you need the l7-filter module and its userspace helper, xtables-addons.
sudo apt-get update
sudo apt-get install xtables-addons-common
sudo modprobe xt_HTTP
Now, let’s craft a rule. We’ll block HTTP traffic that contains the "BitTorrent" user agent string.
sudo iptables -A FORWARD -p tcp --dport 80 -m l7 --l7proto http --l7dir "BitTorrent" -j DROP
Here’s what’s happening:
-A FORWARD: We’re applying this rule to packets that are being forwarded, meaning they’re coming from one network and going to another (like a router).-p tcp --dport 80: We’re targeting TCP traffic destined for port 80 (HTTP).-m l7: This invokes thel7-filtermatch module.--l7proto http: We’re telling it to use thehttpprotocol definition. This definition is provided by thextables-addonspackage and knows how to inspect HTTP traffic.--l7dir "BitTorrent": This is the core of the L7 filtering. Thehttpprotocol definition looks for specific patterns. In this case, it’s looking for the "BitTorrent" string within the HTTP headers. If it finds it, the rule matches.-j DROP: If the rule matches, the packet is dropped.
The xtables-addons package provides pre-defined protocol definitions for common applications like HTTP, FTP, DNS, and more. These definitions are essentially small programs that run in userspace and are invoked by the l7-filter kernel module. When iptables hits a rule with -m l7, it passes the packet to the relevant kernel module. If the kernel module can’t figure it out on its own, it hands it off to the userspace helper for that protocol (e.g., xt_HTTP for HTTP). The helper then inspects the packet’s payload according to its protocol definition and tells the kernel module whether the pattern was found.
The l7proto option specifies which protocol definition to use. The l7dir option then specifies a directory within that protocol’s definition that contains specific patterns to look for. For HTTP, the http protocol definition has subdirectories like BitTorrent, Facebook, Google, etc., each containing files with the specific strings or patterns to match.
You can even create your own custom protocol definitions by creating new directories and files within /usr/share/xtables-addons/ and referencing them. For example, to block a custom application that always sends "MYAPPv1.0" in its initial handshake, you’d create a directory /usr/share/xtables-addons/customproto/ and a file /usr/share/xtables-addons/customproto/MYAPP_HANDSHAKE containing the text MYAPPv1.0. Then you could use:
sudo iptables -A OUTPUT -p tcp --dport 12345 -m l7 --l7proto customproto --l7dir "MYAPP_HANDSHAKE" -j REJECT
This adds a rule to the OUTPUT chain, targeting TCP traffic on port 12345 and rejecting packets that match the MYAPP_HANDSHAKE pattern within the customproto definition.
The l7-filter module itself is a bit of a hybrid. The xt_l7.ko kernel module does the initial packet inspection and can handle some basic protocol matching. However, for more complex protocols like HTTP, it offloads the deep packet inspection to userspace helper applications. These helpers are invoked by xtables-addons and communicate with the kernel module to determine if a packet matches a specific application signature. This architecture means l7-filter is more flexible than purely kernel-based solutions but can introduce a slight performance overhead due to the userspace interaction.
Once you’ve enabled L7 filtering, the next logical step is to explore more advanced pattern matching, such as using regular expressions within your custom protocol definitions for more granular control.