0

Possible Duplicate:
Prevent PHP script from being flooded

Certain "friends" of mine keep messing around on my site by holding down the refresh key. This makes their content's pageviews unrealistically increase and also it adds server load to points where PHP stops running.

I was hoping if there was a way to prevent such intense refreshes (one of them got 30 thousand requests in 1 1/2 hrs) using PHP or JavaScript?

Community
  • 1
  • 1
user115422
  • 4,662
  • 10
  • 26
  • 38
  • Ha, a mini DoS. May I suggest to your friends that a movie might be a more productive waste of an hour and a half... – kalpaitch Oct 22 '12 at 19:24
  • 5
    _Don't_ use JS for this. – Bojangles Oct 22 '12 at 19:24
  • kalpaitch yes, lol highschool friends like messing around with my sites :) – user115422 Oct 22 '12 at 19:25
  • What software is the server running? – jdstankosky Oct 22 '12 at 19:25
  • @JamWaffles ok, i see how this could be an issue, but what can i do with php? – user115422 Oct 22 '12 at 19:25
  • Use a tool like `fail2ban` for this: block them on network level. – arkascha Oct 22 '12 at 19:25
  • @arkascha well thats an option but i dont want them to be blocked as them using my site is beneficial... i just want a way for them to be controlled... – user115422 Oct 22 '12 at 19:27
  • And for an immediate soluton: read: "right now": enter their address in /etc/hosts.deny. – arkascha Oct 22 '12 at 19:27
  • @arkascha remember, i don't want to block these ppl as they are friends of mine and do use the site but occasionally go haywire. but thanks, ill keep it in mind for more intense attacks – user115422 Oct 22 '12 at 19:29
  • 2
    Why, using fail2ban you can use a configuration to block them for a few minutes. Thats all, afterwards all is fine again. And you can configure rules to only block them when they make more than whatever number of requests in a certain time. You caanot have more flexibility. – arkascha Oct 22 '12 at 19:31
  • @arkascha ok, it makes more sense, right make it an answer so if it works with me i can mark it – user115422 Oct 22 '12 at 19:33
  • 30,000 requests in 90 minutes is about 5 and a half requests per second. This is enough to make your stuff crash? o_O – jdstankosky Oct 22 '12 at 19:39
  • @jdstankosky: certainly, if the request cost is high enough. For example if doing image processing in background or something else cpu intensive. – arkascha Oct 22 '12 at 19:41
  • @arkascha OK yeah I wasn't thinking about that. I was thinking of basic page serving and simple database queries. – jdstankosky Oct 22 '12 at 19:43
  • @jdstankosky lol, well it IS a 128mb server (startup) and also the page is heavy on sql queries.. – user115422 Oct 22 '12 at 20:04
  • @MuqMan Perhaps you should see if you can optimize your scripts as well. If you post some code, I'm sure you'll get some great suggestions that may lighten the burden on your server by quite a bit. – jdstankosky Oct 22 '12 at 20:08
  • @jdstankosky ok, but a lot of my code is developed personally by me... i was wondering if there are any tips you can offer... i.e. what should I unset() or how is the best way to use $pdo-> class – user115422 Oct 22 '12 at 20:09
  • @MuqMan If you can censor any private information from your source code, the easiest way to provide feedback is by looking at what you've got going on. – jdstankosky Oct 22 '12 at 20:12
  • @jdstankosky ok, once i have the private info censored where would be the best place to put it? – user115422 Oct 22 '12 at 20:33

3 Answers3

3

You could always count how many requests a user is making from a certain ip address, and stop returning anything but an Unauthorized after a certain limit is reached.

This is a pretty simple solution, but would probably do the job. You can cut it off by requests/time interval or like no more than 100 page requests in two minutes or something. You could then either ban the IP, or return error codes for a specified amount of time. That specified amount of time could be something hard coded like 5 hours, or you could just wait for their requests/time interval to go down organically.

function isIpBlocked($ip)
{
    //do mysql query to check if column is true
}

function shouldIpBeBlocked($ip)
{
    //do mysql query to check if number of request over a certain interval is too high
}

if(isIpBlocked($ip))
{
    header('HTTP/1.0 401 Unauthorized');
}
else
{
   if(shouldUserBeBlocked($ip))
   {
       //do sql update/insert to indicate user is blocked in ip_block table or something
       header('HTTP/1.0 401 Unauthorized');
   }
   else
   {
      //update number of requests from this ip address INSERT INTO ip_history (ip, ...) VALUE (:ip, ....);
      //do your web site code

      //maybe do a mysql query to clean out ip_history table for requests that happened a long time ago and check to see if you should unban people
   }
}

You put that code on every page of your site, and it will ensure that users have not been breaking your predetermined security rules.

thatidiotguy
  • 8,701
  • 13
  • 60
  • 105
  • yes but this is still giving my server a load, running a database query, then running a refresh. 30 thousand requests in less than 2 hrs would crash my server with only 128 mb ram, i was hoping something to cache or whatever into the user's browser...? – user115422 Oct 22 '12 at 19:26
  • Reading from a mysql table is not going to cost you a ton. You could make this is as simple as reading a boolean column based on IP. If they are banned, return error message. If not banned, make sure they should not be. You are not going to be able to affect their browsers because of browser security. – thatidiotguy Oct 22 '12 at 19:28
  • is there a way to use BOTH PHP and JavaScript? so the JS works first and then if the JS if disabled, the PHP? Yeah its naïve but they dont disable js – user115422 Oct 22 '12 at 19:30
  • If they have made a certain number of requests to your site you could send them back a page, where the form cannot be submitted, but you are not going to be able to mess with the inherent browser functionality. – thatidiotguy Oct 22 '12 at 19:30
  • hmm... ok, this all seems interesting but HOW is the question, I don't pretend to be an expert... PHP is my area, js, not so much and in php im only intermediate. – user115422 Oct 22 '12 at 19:32
  • check here for js, but it's not going to be very effective, you can work around this VERY easily if they are determined.. http://stackoverflow.com/questions/7880974/prevent-refreshing-reloading-a-page-with-javascript – Rym Oct 22 '12 at 19:34
  • @MuqMan edited with some code snippets. You have to write it yourself as you decide what criteria is met for a user to be blocked. – thatidiotguy Oct 22 '12 at 19:36
  • nicely edited! @MuqMan, in the snippet, inside the if(shouldUserBeBlocked($ip)) section, you could also retroactively remove all pageviews from the banned user in the last X minutes if you want to set yourself a fun challenge! :) – Rym Oct 22 '12 at 19:39
  • Thanks! Now ill try out all of these and mark one of them as the answer :) – user115422 Oct 22 '12 at 19:44
  • Also, if you wanted to be really tricky you could send them a Service Unavailable Error (503) which would make them think they brought your site down when they really have not. – thatidiotguy Oct 22 '12 at 20:14
  • 1
    @muqman I still don't get why would've you write all that stuff on your own, while there are solid solutions for web server you use. – vittore Oct 23 '12 at 15:11
  • @vittore, what do you mean? I write everything I need on my own... a friending system doesn't come in with plugin does it? I mean yea it would be stupid if there were PHP packages that I could use but am not... your point of course is a reminder. Yes, I do write things on my own. No, i dont if i dont have to – user115422 Oct 23 '12 at 20:18
  • @thatidiotguy good idea, I guess i will implement this over the weekend but from what i have told you, how long would it take before i remove the ip block? what would be the most reasonable, 5 minutes? – user115422 Oct 23 '12 at 20:20
  • 1
    @muqman That is really up to you. It would depend on how stringent the rules are to be put on the ip block. For instance, if you have them blocked after 5 tries in 1 minute, then you should probably be more lenient, as that is not really definitely bad usage. But if you are doing 100 requests in 5 minutes, that is almost definitely a malicious usage case. I would say lean towards being conservative so you do not block real users, but be punishing for the users who are abusing the site. – thatidiotguy Oct 23 '12 at 20:37
  • ok, so i would say 5 seconds per page, even if they are just skimming over it, unless they have the refresh button held down... That would be 12 reqs per min as a limit. I would say go with 15 reqs per min allowed - being lenient. Of course 100 per 5 minutes i guess is more useful. Also if the server DOES reach 128mb of ram (or 256mb - burst) how would i best handle it... I mean it automatically starts crashing scripts under that much load (my site is still not more than a place for me and friends) – user115422 Oct 23 '12 at 21:21
  • Well how much memory are you giving to each Apache pre-fork process? Take 128mb divided by that and you have how many open processes you can have. I would say with that much RAM you are going to have to be pretty careful. Why not 5/15 seconds to make it respond faster. – thatidiotguy Oct 23 '12 at 21:35
  • @muqman I didn't mean your website functionality. I meant countermeasures to this smal DoS. I pointed you to modules, which you just need to configure. And you seem to be going to write this system to block IPs – vittore Oct 23 '12 at 22:26
  • @Vittore of course you are correct... but i want to be able to change servers if my site is worth it and not have to reinstall everything on apache again and again.. I like to keep mod_ to a minimum :) – user115422 Oct 23 '12 at 22:54
  • One of the reasons for making it up in apache or nginx is to do filtering of requests as early as possible. Also, once you will move to something more serious than you small server, you will be into reconfiguring it anyway, so there is no reason to limit yourself in not using mods. – vittore Oct 24 '12 at 12:12
  • http://pastebin.com/eb8kTVgw does it work well enough? – user115422 Oct 25 '12 at 21:39
  • Looks fine to me. Have you tested it? – thatidiotguy Oct 26 '12 at 13:30
  • I would make sure it works as intended, try doing exactly what you friends were doing and see if it maintains server integrity. – thatidiotguy Oct 26 '12 at 15:21
1

Use a tool like fail2ban for this.

You can create a rule to block the requesters ip address when for example they make too many requests to the same url withing a given time. And you can configure the time span they are blocked.

The advantage is that this way blocking already happens on network level, thus lowering your server load.

arkascha
  • 41,620
  • 7
  • 58
  • 90
1

Read apache/nginx manual on limiting connection attempt from single ip etc.

Some reads:

https://serverfault.com/questions/325317/nginx-prevent-dos-by-limiting-worker-processes-connections

How can I implement rate limiting with Apache? (requests per second)

Community
  • 1
  • 1
vittore
  • 17,449
  • 6
  • 44
  • 82