Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Server is a standard LAMP stack configured via cpanel on CentOS 5.9.

We have one file, call it bad.php, on one of our domains that is mistakenly being accessed about 10 times a second by a service provider. The file no longer exists, and we want to block these requests in the most efficient way possible. Currently we're returning bare-bones 410 responses, but that still involves tying up apache threads, sending headers, etc.

Ideally I want to just drop the requests, not sending any response. Blocking by IP is not an option, because we need to allow these IPs to legitimately access other files. (And no, we can't just ask them to stop.) We also don't have an external firewall to work with (leased server, custom external firewall costs extra).

My thinking is that the best option would be an iptables rule like this:

iptables -I INPUT -p tcp --dport 80 --destination [ip address] -m string \
    --algo kmp --string "bad\.php" -j DROP

Two questions:

First, I tried that rule (with the domain's IP address in place of ip address), but it had no effect. It was the very first rule shown by iptables -L, so it should not be overridden by an earlier rule:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  anywhere             [ip address]       tcp dpt:http STRING match "bad\.php" ALGO name kmp TO 65535

Have I messed up somewhere there? I'm very much an iptables noob.

Second question is, are there any caveats to this? Will there be significant overhead having iptables string match every request (compared to the apache RewriteRule with R=410, as we're using now)? Am I better off just living with it? Or is there a better option? (mod_security perhaps?) The server isn't anywhere close to being strained, so it's not a necessity, just an optimization.

Edit in response to Saurabh Barjatiya:

Here is everything I see from tcpdump when I make a request for the bad.php file:

20:21:09.740217 IP [clientIP].62790 > [serverIP].http: S 3454863895:3454863895(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>
20:21:09.740243 IP [serverIP].http > [clientIP].62790: S 4112555138:4112555138(0) ack 3454863896 win 5840 <mss 1460,nop,nop,sackOK,nop,wscale 7>
20:21:09.838595 IP [clientIP].62790 > [serverIP].http: . ack 1 win 16425
20:21:09.838606 IP [clientIP].62790 > [serverIP].http: . 1:1461(1460) ack 1 win 16425
20:21:09.838622 IP [serverIP].http > [clientIP].62790: . ack 1461 win 69
20:21:09.838632 IP [clientIP].62790 > [serverIP].http: P 1461:1476(15) ack 1 win 16425
20:21:09.838638 IP [serverIP].http > [clientIP].62790: . ack 1476 win 69

Obviously the actual url string is not here. My understanding is that iptables can filter for url strings though, so presumably I'm checking the wrong thing.

share|improve this question

1 Answer 1

Hunch is that iptables rule will use more CPU than apache configuration. But nevertheless it is interesting use of iptables to block incoming requests. As the requests are not gzipped and they are also usually in one single packet I do not see any caveats to your logic.

To understand why current rule is not working I have two suggestions:

  1. Remove -d for a while and see if the rule works. You might have made silly mistake while interpreting destination IP
  2. Capture packets using tcpdump or wireshark and analyse them to see strings that you can match for in requests for bad.php. This will also help in verifying that all bad.php requests actually contain bad.php as expected. Sometimes local rewrite rules may cause requests to go to bad.php while the original request in packet is for good.php making iptables rule fail.
share|improve this answer
    
Tried #1 just in case (but IP address is correct). Am attempting #2, but tcpdump doesn't appear to show anything as far as URL strings. See my edit in the question. Is there a flag I'm missing? I checked the man page but didn't see anything relevant. –  Nathan Stretch Mar 7 '13 at 4:35
    
tcpdump -s0 will dump the entire packet, not just the headers –  Jenny D Mar 7 '13 at 8:24

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.