Realizing that I shouldn’t be content with just sending out 403 codes to link spammers, I decided to get a little more devious. I’ve now hooked up a CGI to handle the 403 errors. What’s even better, it hooks into pfctl on OpenBSD to dynamically ban the people as they hit the site. You can’t ask for much better than that. Well, we could be talking about integrating some layer 7 stuff here, but I digress.
So, first there is some work that needs to be done in the httpd.conf file that configures the server. This is shown below:
:::apache
ErrorDocument 403 /cgi-bin/403.cgi
# provide a method to test the blocker
RewriteCond %{QUERY_STRING} ^deny=true$
RewriteRule !^/cgi-bin/403.cgi$ - [F]
# all the referrers we don't like
RewriteCond %{HTTP_REFERER} ^http://(www\.)?.*(-.*)+\.info/.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(www\.)?adminshop.com/.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(www\.)?webdevboard.com/.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(www\.)?devaddict.com/.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(www\.)?whiteguysgroup.com/.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(www\.)?guestbookz.com/.*$ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(www\.)?xopy.com/.*$ [NC]
RewriteRule !^/cgi-bin/.*$ - [F]
# Ban comment spammers
# This stops people who try to write scripts to comment spam me
RewriteCond %{HTTP_REFERER} ^-?$
RewriteRule ^/mt/mt-comments.cgi$ - [F,L]
In a nutshell, I’ve done a cople of things. First, I’ve sent all 403 error statements through the CGI. Next, I’ve modified it so I can test the system by allowing me to append “?deny=yes” to any URL and get the 403 error page (and thus blocked). After that, we’ve got a section blocking all the referrers that I don’t like. Finally, I’ve decided to stop people who are still trying to hit my MovableType system that’s been dead for well over a year now.
The next step is to modify your /etc/pf.conf
file to allow for the
blocking. The new rules are shown below:
table <http_always_allowed> { 192.168.1.0/24 }
table <http_banned> persist
web_ports = "{ 80 }"
pass in quick proto tcp from <http_always_allowed> to any port $web_ports keep state
block in quick proto tcp from <http_banned> to any port $web_ports
This creates two tables. One contains a list of all hosts that are allowed no matter what to hit the web server. Put your testing host in here or you’ll get blocked. The second tells the system to create a table called http_banned that contains banned ip addresses. Next, we set up web_ports as a listing of ports the web server runs on. Finally, we create a rule to allow the people in the http_always_allowed table to always connect and the final rule blocks all connects from http_banned hosts.
If you’ve gotten this far, you’re doing well. Now we need to create
the CGI to make sure it can ban people. Here is my version of
/cgi-bin/403.cgi
that I use on my site:
:::python
#!/usr/local/bin/python
import os
import datetime
try:
f = os.popen("sudo pfctl -t http_banned -T add %s" % os.getenv("REMOTE_ADDR"))
body = f.read()
f.close()
except:
body = ""
print """Content-Type: text/html
<body><body><h1>403 Forbidden</h1><p>You suck</p><pre>%s</pre></body></html>""" % body
try:
f = open("/tmp/ipaddr","a")
f.write("Host=[%s] URI=[%s] Agent=[%s] Time=[%s]\n" % (os.getenv("REMOTE_ADDR"),
os.getenv("REDIRECT_URL"),
os.getenv("HTTP_USER_AGENT"),
datetime.datetime.now()))
f.close()
except:
pass
You’ll notice one little problem, this guy calls sudo in order to block the port. That means we need to allow the web user to call pfctl. This is probably not a good idea for a multi user system. A better idea is to write a wrapper program which ONLY adds entries to the list of banned clients. If you’ve gotten this far, you can probably figure out how to do that on your own.
The very last step is to allow the web server to call sudo for pfctl.
Here are the lines that I have in my /etc/sudoers
to allow this to
happen.
Cmnd_Alias WEB = /sbin/pfctl
www ALL=(ALL) NOPASSWD: WEB
Putting all of these things together should get your system up and going. Now you can come back in a little while and look and see who has been banned from your server. It’s oh so delicious! Have fun and enjoy banning bastards. This method could be easily extended to ban bots that hit unauthorized pages or whatever you want. Just remember, autobanning like this is a sure fire way to lock yourself out of your system. Don’t blame me for your problems.
[patrick@scissors] sudo pfctl -t http_banned -T show 80.58.11.107 196.20.31.121