IPTables/Netfilter Recent Module Updated: Fri, 21 Mar 2003 21:53:30 -0500
Wrote myself a module which I called 'recent' to track seen IP addresses and be able to match against them using some criteria. What this lets me do is basically build up a temporary 'bad-guy' list for when people attempt to port scan me and whatnot and then I use the match to drop everything coming from them for a given amount of time. There is also an ipt_recent mailing list and CVSWeb access to the code.

Releases Updated: Mon, 31 Mar 2003 16:13:21 -0500
The Netfilter CVS repository generally has a pretty up-to-date version of my module in the patch-o-matic area. This is the official repository and has the latest releases.

The --rsource/--rdest options have had some pretty odd behaviour in the past that I've finally fixed. They're much more intuitive now and instead of being per-table based they work for the current rule. Makes a heck of alot more sense and is more flexible as well I believe. The current released version is available here, and is currently running on my firewall:

This is a tarball of the current files. A patch against what is currently is: ipt_recent-0.3.1-netfilter_update.patch

If you run into any problems or bugs with this version please let me know so I can take care of them.

Changelog Updated: Fri, 21 Mar 2003 21:55:44 -0500
You can check out the latest version as well as look at older releases by picking the appropriate tag over at the CVS repository.

Examples Updated: Sun, 08 Sep 2002 00:15:12 -0400
Example #1:

# iptables -A FORWARD -m recent --rcheck --seconds 60 -j DROP
# iptables -A FORWARD -i eth0 -d -m recent --set -j DROP

Here we are making a 'bad guy' out of anyone who tries to send data to on our eth0 interface (which should never legitimately happen). The first packet will make it past the first rule and then be caught by the second rule and that address will be put into the recent list and the packet dropped.

Any subsequent packets for the next 60 seconds that show up from that address will be dropped, regardless of destination address, destiation port, etc.

Example #2:

# iptables -A FORWARD -m recent --update --seconds 60 -j DROP
# iptables -A FORWARD -i eth0 -d -m recent --set -j DROP

(The author's favorite method)

This is identical to example #1 except that for every subsequent packet received from this source address the 'last seen' status will be updated in the table. Therefore there must be a 'quiet time' of 60 seconds before another packet from this address will even be considered.

It is the author's intent that all 'DROP' rules be replaced by:

'-m recent --set -j DROP'

and that a:

'-m recent --update --seconds 60 -j DROP'

rule be added very early on in the rule set, though following any:

'--match state --state ! NEW,INVALID -j ACCEPT'

rules. If the '--update' rule is before this check for ! NEW,INVALID packets then ESTABLISHED connection or those in the process of becoming ESTABLISHED could be disrupted by a malicious person who can modify his/her source address.

Example #3:

# iptables -A FORWARD -d -p tcp --dport 25 -m recent --set --rsource --name SMTP_RELAY_IN -j ACCEPT
# iptables -A FORWARD -d -p tcp --dport 113 -m recent --rcheck --rsource --seconds 15 --name SMTP_RELAY_OUT -j ACCEPT
# iptables -A FORWARD -s -p tcp --dport 25 -m recent --set --rdest --name SMTP_RELAY_OUT -j ACCEPT
# iptables -A FORWARD -s -p tcp --dport 113 -m recent --rcheck --rdest --seconds 15 --name SMTP_RELAY_IN -j ACCEPT

This set of rules can be used to allow auth requests to/from your mail server to go through when there is an associated SMTP connection. It's possible someone could write a conntrack module for this too but that seems kind of excessive, especially when there are a number of other places where this kind of a setup could be desirable (ie: for IRC). Unfortunately this won't work all the time because there are some incorrectly configured systems out there where the auth request will actually come from a different IP address than the SMTP connection was made to, not much that can be done there. This example also shows how you can set it up so that people have to, say, send a 'special' packet of some kind to be allowed to connect to some internal machine. Very neat idea.