ProXy_ Posted October 9, 2009 Share Posted October 9, 2009 Hello, I'm trying to figure out how i can ban an IP if they're flooding me For example: if i had api http://blah.com/api.php?url=http://url And someone makes a script to open 2000 iframes and flood it. is there any way i can detect it with PHP? i've already got a good idea how to auto add their ip to .htaccess i just have been looking trying to find different ways of blocking floods and i havn't gotten anywhere, appreciate any help. thanks Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/ Share on other sites More sharing options...
newbtophp Posted October 9, 2009 Share Posted October 9, 2009 <?php $flood = $_SERVER['HTTP_REFERER']; //Replace blah with the website url (without extension) if (preg_match("/blah/i", "$flood")) { die('Your banned, you flooder!'); } ?> Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-933962 Share on other sites More sharing options...
corbin Posted October 9, 2009 Share Posted October 9, 2009 I would do it with iptables personally.... (Assuming it's a linux box.) That way the request never reaches Apache and you avoid the overhead of the request. Just drop all packets from that IP address. iptables -I INPUT -s 0.0.0.0 -j DROP (Where 0.0.0.0 is a real IP address) If the IP address changes, you'll need to make rules based on requests per second. (Don't know if that's possible or not with iptables since I've never looked into it.) (P.S. if the server is running Windows, Windows Firewall should work fine.) If the problem is going to be long term and especially if you expect it to become more of an issue (for example if someone starts a decent size DDOS attack), you might want to look into blocking on a router level. (Probably not worth the effort unless it becomes a big problem or if it's easy to do with your router.) Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-933964 Share on other sites More sharing options...
Daniel0 Posted October 9, 2009 Share Posted October 9, 2009 If the IP address changes, you'll need to make rules based on requests per second. (Don't know if that's possible or not with iptables since I've never looked into it.) You could write a service that runs in the background and analyzes the access log. Not exactly a simple solution. Easiest thing would be to have a counter using sessions that blocks if they've made X requests within the last Y time units. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-933965 Share on other sites More sharing options...
ProXy_ Posted October 9, 2009 Author Share Posted October 9, 2009 <?php $flood = $_SERVER['HTTP_REFERER']; //Replace blah with the website url (without extension) if (preg_match("/blah/i", "$flood")) { die('Your banned, you flooder!'); } ?> This kinda helps a little bit, but the person randomly switches his host to another free host and does it again. so i'm trying to just stop an ip instead of a website. And to the others, i'm on a paid shared server, thats why i am trying to make a php script to auto ban anyone that abuses my API. i had a few ideas, but after a while of creating the ideas, i don't see a future that would resolve my problem. But, if one IP adds 40 urls in under a minute, Add IP to .htaccess. Would be a simple way of explaining what i am trying to figure out :/ Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934031 Share on other sites More sharing options...
corbin Posted October 9, 2009 Share Posted October 9, 2009 This is a pretty ugly way to do it, but it would work assuming the person is dumb enough to leave cookies enabled or let the session ID be appended to the URL: <?php session_start(); if(!isset($_SESSION['visits'])) { $_SESSION['visits'] = array(); } $timeframe = 3; //3 seconds $requests_per = 50; //50 requests $visits &= $_SESSION['visits']; $now = microtime(true); foreach($visits as $key => $visit_utime) { if($visit_utime < $now-$timeframe) { unset($visits[$key]); } } //1 since the current visit isn't in the array yet if(count($visits) + 1 > $requests_per) { //add IP to ban list exit; } $visits[] = $now; Really doing it by IP would be better though... That's a bit more complicated though since $_SESSION acts as a convenient container for the data. With IPs you would have to store it somewhere like a file or a database. Cleaning out old data would become an issue, and things like locking could be an issue in both a DB and flat files. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934047 Share on other sites More sharing options...
ProXy_ Posted October 9, 2009 Author Share Posted October 9, 2009 Thank you for the idea, i really think i can go somewhere with this. i really appreciate all your help. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934051 Share on other sites More sharing options...
Daniel0 Posted October 10, 2009 Share Posted October 10, 2009 With IPs you would have to store it somewhere like a file or a database. Cleaning out old data would become an issue, and things like locking could be an issue in both a DB and flat files. In the case of MySQL, you would then want to use InnoDB because it has got row level locking. It only locks a row you are currently using and not the entire table like MyISAM does. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934154 Share on other sites More sharing options...
ProXy_ Posted October 10, 2009 Author Share Posted October 10, 2009 I've tried a few things above, and i couldn't really seem to get anywhere. The main part i'm trying to figure out is how to Allow x amount of visits per ip in x minutes Is this possible at all, i've searched everywhere and i'm just getting nowhere. I Appreciate all help. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934478 Share on other sites More sharing options...
corbin Posted October 10, 2009 Share Posted October 10, 2009 In that case, the easiest solution is a MySQL database. As Daniel mentioned, InnoDB does row level locking and MyISAM does table level locking, so you'll want to use InnoDB as the engine. Anyway, then the concept is basically the same as earlier just with a different data storage method. Do you have any SQL experience? Also, is MySQL even an option? If it's not, do you have access to any kind of database/ Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934494 Share on other sites More sharing options...
ProXy_ Posted October 11, 2009 Author Share Posted October 11, 2009 I have the access to mysql & all that. I'm not very experienced with mysql & innodb I'm a pretty quick learner. so if i need to study these languages. i can do so. I just needed to find some way to make this possible just can't risk getting exploited again :/ so, thank you again for your time. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934646 Share on other sites More sharing options...
corbin Posted October 11, 2009 Share Posted October 11, 2009 Normally I don't give people code since it defeats the purpose of a helping forum, but I went ahead and made this since it would be kind of lame to link you to a couple of tutorials and be like "have fun!" when you obviously have a problem. Anyway: CREATE DATABASE iplimit; USE iplimit; CREATE TABLE visits ( ip_addr int unsigned NOT NULL, visit_time float ) ENGINE=InnoDB; CREATE INDEX idx_ip_addr ON visits(ip_addr); CREATE INDEX idx_visit_time ON visits(visit_time); CREATE TABLE banned ( ip_addr INT UNSIGNED UNIQUE ); CREATE DATABASE iplimit; USE iplimit; CREATE TABLE visits ( ip_addr int unsigned NOT NULL, visit_time float ) ENGINE=InnoDB; CREATE INDEX idx_ip_addr ON visits(ip_addr); CREATE INDEX idx_visit_time ON visits(visit_time); CREATE TABLE banned ( ip_addr INT UNSIGNED UNIQUE ); It basically does the same thing as the session thing from earlier, but it stores it in a database and does it by IP. It's worth noting that you could replace the banned table with writing the IP to a htaccess file (which would save parsing the PHP page/connecting to the database), but then you would have to worry about file locking. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934736 Share on other sites More sharing options...
ProXy_ Posted October 11, 2009 Author Share Posted October 11, 2009 i Appreciate your help. This is exactly what i have been looking for all over the place. And thank you for the code, it saves me a little time so i can just throw this in here and get our api system back up in little time. Thank you again. i really do appreciate this Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934868 Share on other sites More sharing options...
corbin Posted October 11, 2009 Share Posted October 11, 2009 No problem. Quote Link to comment https://forums.phpfreaks.com/topic/177132-solved-php-bans/#findComment-934974 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.