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.