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.

Comments:

You shouldn't need to unplumb/plumb the interface after adding a rule. The reason you probably had to do it was that ipfilter had not started when the machine booted. So you could have moved the unplumb/plumb higher up, then any rule you add will automatically be applied. But if you do any more than one rule I would suggest placing it in a file. Probably also want to do a "block in quick ..." instead of just a block in. If you had other rules, it would not stop on the block in and would flow through the rest of the rules and something later may actually allow the packet through

Posted by jason on May 05, 2009 at 12:25 PM PDT #

With OpenSolaris, starting from b113, Host-based Firewall makes it much simpler to configure IPFilter rules. See http://blogs.sun.com/tonyn

Plumbing/unplumbing shouldn't be necessary.

Posted by Tony Nguyen on May 06, 2009 at 04:40 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
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
« April 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
   
       
Today