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.

Instead of describing what's happening I'll post a screenshot of Apache's server-status page:

Screenshot

It is a Nigerian IP.

I'm having this problem for years now and I never found a viable solution except banning the attacker's IP and waiting for the jerk to return via another one.

Here's a bit of further explanation. The site is custom developed and that download page is only accessible if the user is logged into the site, otherwise a redirection to the login page is served. If the user's logged it serves quite a big file. But, after serving it once, the site has sort of a RapidShare like politic, meaning that the user has to wait. So the second time it is accessed it'll only serve an error message telling the user to wait. However it looks like the attacker somehow succeeds in opening a connection and then another one and then yet another one, until MySQL on my server chokes up and starts throwing errors.

If this kind of attack is a known one, has a name and there are known solutions on how to avoid it redirect me. Any feedback or ideas are very welcome because I'm slowly going crazy here.

share|improve this question
    
Is it possible a download manager is causing this? Have you looked at the user-agent? If it is not a browser causing it, you might be able to block based on user-agent. –  Dave Drager Oct 7 '09 at 14:55
    
It is highly unlikely for a download manager to create more than 10 requests from a Nigerian proxy. –  kitsched Oct 7 '09 at 17:08
add comment

4 Answers

up vote 1 down vote accepted

There are afew approaches that you can use:

One specific tool that is setup to help in situations like this is mod_evasive:

You can block along the following criterion:

  • Requesting the same page more than a few times per second
  • Making more than 50 concurrent requests on the same child per second
  • Making any requests while temporarily blacklisted (on a blocking list)

Another alternative would be to roll something on your own that scrapes the apache status from the command line (very easy, I've done it before), and then sorts by IP and URL, then you drop it,

Otherwise I think the only other 'good' solution is similar to the one mentioned above, to log IP activity to that page over say, 5 minutes, and then if you they cross over that threshold, have a script scrape through and drop that in the firewall. You also don't have to block it necessary, you could do something like the following, which would prevent new connections after 30 attempts (adjust as appropriate for the correct eth device):

iptables -I INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --set
iptables -I INPUT -p tcp --dport 80 -i eth0 -m state --state NEW -m recent --update --seconds 60 --hitcount 31 -j DROP
share|improve this answer
add comment

Since this is a custom developed app, would it be correct that you have the ability to change it? If so, maybe the following suggestions would help:

  • Use Captcha - (another link) on your login page to prevent a robotic process from taking down your server.
  • Change the code so that it only allows two connections per IP per user login. Don't redirect the user, just dump any connection greater than 2. If you allow 2 connections, that should help in the case that something happened on the client's end that has killed connection #1.
share|improve this answer
    
1. I have reCAPTCHA at the register step - so I'm pretty sure the process is started manually. 2. The file he's trying to download is a fairly large one with a considerable cool down time. So if he was really downloading it he would be dispalyed an error page telling him to wait. But he somehow still manages to open the connection and keep it open. –  kitsched Oct 7 '09 at 13:46
    
Is your download via HTTP? Are you using URL obfuscation? How are you preventing someone from accessing the link directly, or worse providing SQL injection? –  Scott Lundberg Oct 7 '09 at 14:20
    
Yes the download is via HTTP. But thanks for the idea Scott about download URL obfuscation. I shall try that. The link can't be accessed directly, if the user is not logged in he's redirected to the login page. SQL injection is excluded, the file id number is cast to integer - and in other parts of the site CodeIgniter's XSS clean function is used on all user inputs. –  kitsched Oct 7 '09 at 14:25
add comment

I am a bit confused as to why this "attacker" would want to download the file more than once. However there are a few ways to limit this:

  1. Create a process in your code that adds the IP address to a file or database that marks that it is currently downloading a file, and prevent access if it is currently in download or based on time (eg, one download every 5 minutes).
  2. Install an apache module to limit connections per IP address. Mod_limitipconn seems designed for this.

I think mod_limitipconn seems like it would fix your current issue but since this is a problem to begin with, I think there might be an issue with the code logic you have running on the site.

share|improve this answer
3  
What if several people are behind a NAT firewall? Limiting connections per IP will block anyone behind the same IP once the connection limit is exceeded. –  Scott Lundberg Oct 7 '09 at 13:01
    
I'm actually doing hint 1 - I wrote in the description that if he's trying to download a file before the cool down time an error is display. Nevertheless the attacker somehow still manages to open the connection and keep it open. I'm guessing he somehow limits the data to flow through very slowly. –  kitsched Oct 7 '09 at 13:42
add comment

It sounds like your app may be adding the time delay record after the file completes rather than when starting, allowing parallel downloads. While it may be possible to work around on the server, it'd be better to fix the app. As you indicated it was just a delay rather than a once-per-file, have you considered moving that status recording to before sending the file? The window for opening additional downloads would be reduced (or eliminated depending on how you code it), and as a side benefit you could likely release the database connection back to the pool (or close it if you're not pooling) rather than either keeping it open until after completion for recording the completion.

share|improve this answer
    
I wrote the app and I'm positive it doesn't add the delay before the download. What's even more fun, I can clean up the PHP file and it still loads it and keeps it in the server-status for indefinite time. What's interesting is that these accesses are not even logged in access_log. So it's weirdness all over. I'm guessing it's some sort of exploit. –  kitsched Nov 17 '09 at 11:43
    
That somewhat confirms the problem. Making it add the delay before proceeding with the download should prevent the other downloads. Apache also logs at request completion, thus it not logging the request if the system collapses before they can finish. I'm not sure what you mean by "clean up the PHP file", but server status will show the request even after a request completes until another request is served by that process. If the state is W like in your screenshot it's sending data, where it'll go to _ once it's idle again. –  Jeremy M Nov 18 '09 at 0:00
add comment

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.