Using Iptables To Block Bot Scans

Enter the string-match module for iptables. Each hit of a scan usually has some string in common, which is used to identify it to iptables, which drops the connection. For instance each hit from one scan might have "ZmEu" or "setup.php" in common, even if the originating IP changes. Here's an example blocking any hit containing "ZmEu":
iptables -t raw -A PREROUTING -m string --algo bm --string "ZmEu" -j DROP
Here's what it looks like added to iptables, with "ZmEu" and "setup.php" blocked:
*raw
:PREROUTING - [0:0]
-A PREROUTING -m string --algo bm --string "ZmEu" -j DROP
-A PREROUTING -m string --algo bm --string "setup.php" -j DROP
COMMIT
*filter [....]
The module works with the raw table and has an algorithm choice of bm (Boyer-Moore) or kmp (Knuth-Pratt-Morris). From light reading on the two it looks like Boyer-Moore is proven quicker.
It searches incoming and outgoing, so if you block "ZmEu" but wanted to print ZmEu on a page, you'd have to put an empty tag (i or b) between the letters to break the string (and it will show on the page normally). The stronger (longer) you make the string, the less likely a visitor will type it into a comment or search, then sit and clock.
To test, I changed my browser's user-agent to "some-string" then added a rule blocking "some-string". I tried to access the site while tailing the access_log. I was unable to access the site and the visit never touched the web server.
I haven't logged a bot I've blocked since putting it to use... The string-match module could be useful for blocking other unwanted traffic and keeps resources free for the web server by allowing the firewall to do the work.
Comments
Works really well.
what happens if you remove the "string"?
I get this: iptables v1.2.11: Couldn't load match `string':/lib/iptables/libipt_string.so: cannot open shared object file: No such file or directory
Thanks
Well, if you remove the string but keep the rule, you'll get an error... If there was nothing in the string (between the ""), then that would match everything coming or going.
Instead of removing the string in the line, try commenting the line by putting a # in front of it. Uncomment (remove #) to go back to filtering for that string.


Leave a comment?