Development of l7-filter has moved to the Clear Foundation. These pages are out of date, but will remain as a historical record.

Back to the main page

Last updated 9 Dec 2006

Technical Details of l7-filter

The basic idea of l7-filter is quite simple: Use regular expression matching of connections' application layer data to determine what protocol is being used. Of course, it wouldn't make sense to run a regular expression matcher on every packet. Not only would that be a huge waste of clock cycles, but it would be useless for matching most packets, which are likely to consist of the middle of some file or whatnot. Instead, l7-filter just looks at the first few packets of a connection for "hello" messages such as "220 ftp server ready", "* ok", or "HTTP/1.1 200 ok".

Instead of having the user provide regular expressions on the command line, l7-filter provides a set of pattern definition files. To match the protocol "foo", the user types "iptables ... -m layer7 --l7proto foo", and iptables reads the regular expression that defines "foo" out of /etc/l7-protocols/*/foo.pat.

In other words, l7-filter is essentially what you'd get if you added the CONNMARK patch to the string patch, used regexec() instead of strstr(), removed the need to set up the connection tracking manually, added the ability to match patterns across several packets and included a collection of protocol signatures that could be identified by name. :-)

Because only a few packets per connection are examined, l7-filter is reasonably efficient despite using a much more involved matching algorithm than most packet classifiers. See performance for more details.

Pseudo-code for our Netfilter kernel module:

/* This is the standard Netfilter match function, which returns true on
a match and false otherwise.  Obviously, many details are ignored here. */
int match(packet, protocol)
{
	if(regular expression for the protocol is not compiled yet)
		compile it and put it in a list of compiled regexps;
	else
		fetch the compiled pattern from the list;

	if(already classified this connection)
		if(classification matches one we're looking for)
			return true;
		else
			return false;

	if(seen too many packets with no match)
		return false;

	Append application layer data to data buffer;

	if(data buffer matches regexp for the protocol we're looking for)
		Mark the connection as identified;
		return true;
	else
		return false;

}