Tuesday May 05, 2009

Blocking HTTP connections from an IP on Solaris 10

Today, I woke up to find that surl, one of the internal web apps I wrote, had stopped working and was returning "Can't open file: 'surl.MYI'. (errno: 145)", which means the database table was corrupted, a quick Google search revealed.

Fortunately, the repair procedure is simple enough:

mysql> REPAIR TABLE surl;
...
mysql> \^D

However, it didn't work. Turned out my / filesystem was full, so I deleted some files under /var/tmp, re-ran the REPAIR command, and surl was back in business.

Later, I began to investigate how / filled up all of a sudden; nothing particular stood out until I looked at the Apache access log, which shows that the web app was being hit by two IP addresses every 5 secs since April 9th! Unable to contact the owner of those systems, I decided to block connection from these IPs. It took a while to figure out the correct syntax to put in httpd.conf:

<VirtualHost 123.45.67.89>
...
<Directory /path/to/htdocs>
Order deny,allow
Deny from ww.xx.yy.zz
</Directory>
...
</VirtualHost>

It is critical to use the proper "Order" and not to put "Allow from all" in the final line as that would negate any previous Deny command. After, refresh Apache with this:

# svcadm refresh apache2

But that only resulted in Apache returning 403 response to every request. I want to block the requests completely, so I need to refuse these connections before they get to Apache. I considered using /etc/hosts.deny, but Apache doesn't support that. Then I found out about ipfilter in Solaris 10. I have used ipchains and ipfwadm on Linux many years ago, but I have no experience with ipfilter. After reading numerous online resources, it is apparent that ipfilter is a very powerful tool, but it wasn't very clear to me how to use it to do a very simple task, which is to block connection by IP. These are the steps that I took:

# svcadm enable ipfilter
# vi /etc/ipf/pfil.ap # and comment out your interface name, e.g. hme
# svcadm restart pfil
# echo "block in from ww.xx.yy.zz to any port = 80" | ipf -f -
# ifconfig hme0 unplumb
# ifconfig hme0 plumb <IP addr> netmask 255.255.254.0 broadcast <bcast addr>

The most tricky part is that the interface must be unplumbed and plumbed (or server must be rebooted which isn't an option for most I'd imagine). Until then, IP filtering is not active! I'm specifying the rule via STDIN instead of /etc/ipf/ipf.conf because I don't intend to make the block persistent across reboot, I'm hoping whoever is hitting my web server every 5 secs will notice and stop doing so.

These are also useful to know:

# ipf -Fa # flush all existing rules
# ipfstat -hio # show hits against all rules

I hope this will save someone else's time.

About

I currently live in San Francisco Bay Area. For the past seven years, I have been designing and building messaging solutions for Sun.

Search

Categories
Archives
« July 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today