1

I'm trying to block some of my website's users. Well I need two things:

  • getting user's IP
  • blocking it

I've searched about them. And I understand I have to get user's IP like this:

$ip = $_SERVER['REMOTE_ADDR'];
// or sometimes $_SERVER['HTTP_X_FORWARDED_FOR']

And I have to block it like this:

$network = ip2long("10.12.0.0");
$mask = ip2long("255.255.0.0");
$ip = ip2long($_SERVER{'REMOTE_HOST'});
if (($network & $mask) == ($ip & $mask)) {
  die("Unauthorized");
}

As you see, for blocking an IP, it uses $_SERVER{'REMOTE_HOST'}. Well that's the different between $_SERVER{'REMOTE_HOST'} and $_SERVER['REMOTE_ADDR']? And which one is containing the IP ?

Community
  • 1
  • 1
stack
  • 10,280
  • 19
  • 65
  • 117
  • You can just write your own php codes to block ips. In your database, have a table like ipBan or something, and then whenever an user visits your website, search their ip in the ipBan table. If found, just redirect them to a page like blank.php or something. Easy. – frosty Jul 01 '16 at 00:18
  • I have no idea what the network/mask stuff, and the ip2long is totally unnecessary. `if($_SERVER['REMOTE_ADDR'] == 'ip you want to block') { die('Unauthorized.'); }` – ceejayoz Jul 01 '16 at 00:18
  • @frosty Well I'm familiar with the algorithm you said .. But actually I'm trying to get user's IP now. – stack Jul 01 '16 at 00:19
  • @stack The user's IP is `$_SERVER['REMOTE_ADDR']`. In some situations a server may be behind a proxy (often a load balancer) and if not properly configured their IP will be in `$_SERVER['HTTP_X_FORWARDED_FOR']`, but that's not massively common - if you're a PHP newbie it's unlikely you're running on that complex a server setup. – ceejayoz Jul 01 '16 at 00:20
  • @ceejayoz Ah ok, Just `REMOTE_ADDR` is enough? see [this](http://stackoverflow.com/questions/15699101/get-the-client-ip-address-using-php#15699240) please. – stack Jul 01 '16 at 00:20
  • `REMOTE_HOST` is the name, `REMOTE_ADDR` is the IP. – Barmar Jul 01 '16 at 00:20
  • @Barmar So using `ip2long()` function for a *name* is wrong, right? – stack Jul 01 '16 at 00:21
  • 2
    @stack Yes, very wrong. – Barmar Jul 01 '16 at 00:21
  • 1
    Correct. Note that per the PHP docs `REMOTE_HOST` is not present unless your Apache server has `HostnameLookups On` turned on (not sure if nginx has something similar). Since that's a bit heavy on the server, chances are it's off and empty. – ceejayoz Jul 01 '16 at 00:21
  • @ceejayoz I see. thank you. – stack Jul 01 '16 at 00:22
  • @Barmar I see. thank you. – stack Jul 01 '16 at 00:22
  • The code you have is for blocking entire subnets, not just individual IPs. So it will block all `10.12.x.x` addresses. – Barmar Jul 01 '16 at 00:25
  • @Barmar Ah good to know. ok this is good? `if(strpos($_SERVER['REMOTE_ADDR'], "/* an specific ip */") === 0))` – stack Jul 01 '16 at 00:28
  • Why not just `if ($_SERVER['REMOTE_ADDR'] == $blocked_ip)`? – Barmar Jul 01 '16 at 00:29
  • 1
    You seem to be making this much more complicated than it needs to be. – Barmar Jul 01 '16 at 00:30
  • @Barmar Well that's just a simple if-statement. What's the complicated part? Also is there any better way? Lemme ask this: *how can I block an specific IP?* – stack Jul 01 '16 at 00:31
  • trivial for most people to get around this type of block –  Jul 01 '16 at 00:31
  • You're making it more complicated by using `strpos` instead of `==`. – Barmar Jul 01 '16 at 00:31
  • @Barmar Ah .. Actually I did that based on what [this professional programmer did](http://stackoverflow.com/questions/2869893/block-specific-ip-block-from-my-website-in-php#2869900) ..! **Edit:** Oh, I get that now, he did that because he wanted to block a range of IPs. Ok I got it. – stack Jul 01 '16 at 00:33
  • @chris85 Yeah I got it. – stack Jul 01 '16 at 00:42
  • hey if you really need to do this - also set a cookie, session, something like that. because for example using mobile wifi hotspot - their ip can change every few minutes without any intervention on their part. – cartalot Jul 01 '16 at 00:42
  • You could block the IP higher up then PHP too. – chris85 Jul 01 '16 at 00:43
  • @chris85 Do you mean *.htaccess* ? – stack Jul 01 '16 at 00:43
  • I was thinking `iptables`. – chris85 Jul 01 '16 at 00:44
  • @cartalot I think you are talking about the client IP which is made by the router *(modem)*. But I'm talking about the IP that user gets from the ISP. – stack Jul 01 '16 at 00:45
  • @chris85 Well what's `iptables`? Is that a code? Or do you mean a table in the database contains all user's IPs ? – stack Jul 01 '16 at 00:46
  • It is probably a part of your server if running linux, https://en.wikipedia.org/wiki/Iptables.. http://serverfault.com/questions/592061/block-range-of-ip-addresses – chris85 Jul 01 '16 at 00:47
  • @chris85 Seems nice ... just how it works? Is that working on the *log.txt* file of the server or .htaccess file ? – stack Jul 01 '16 at 00:52
  • You input addresses/ranges you want to block. – chris85 Jul 01 '16 at 00:52
  • @chris85 Yeah I know, Actually I learned how should I work with it. Now I'm curious how it works? Is it using a database? – stack Jul 01 '16 at 00:54
  • It is using the file with the list of rules. There are docs on it, I'm not well versed on the behind the scenes of it. Might want to try serverfault, more a server mod then coding question. – chris85 Jul 01 '16 at 00:59
  • @chris85 Ah interesting .. Thank you for your explanations. Also if you like, you can write an answer under my question. I will accept it as accepted one `;-)` – stack Jul 01 '16 at 01:00

1 Answers1

2

REMOTE_HOST usually contains the result of a reverse dns lookup and can also be done in PHP using gethostbyaddr in the case, that your server does not fill this environment variable. It gets derived from the $_SERVER['REMOTE_ADDR'] value, which represents the (IP)-address as its name suggests.

Banning IP-Addresses on a shared host is not optimal and I will come to that later. Assuming you are using a shared host I would not let the script die like you did. Instead I would just return a HTTP header in order to (at least) save some bandwidth on that IP, like:

if($_SERVER['REMOTE_ADDR'] == "127.0.0.1")
{ header("HTTP/1.1 403 Forbidden" ); exit; }

and returns something like this to your visitor (using chromium):

enter image description here

A cleaner and more professional approach to block IP addresses is not possible on many shared hosts, but should be mentioned here anyways, because it saves bandwidth, memory and cpu-cycles and can be described as dynamic creation of firewall rules. There are tools like fail2ban helping to overcome compatibility issues between different firewalls keeping your PHP application portable between root servers. Fail2ban can scan all kinds of log files, even custom ones. Your PHP application could just write to a log file and fail2ban would disallow any connection attempt from that IP address to your server. Sounds cool? Root servers ain't expensive nowadays if you would like to try it.

stack
  • 10,280
  • 19
  • 65
  • 117
entwicklerseite
  • 416
  • 4
  • 6
  • Ah I see, upvote. Just what happens when an user uses the proxy? I guess I need to check `$_SERVER['HTTP_X_FORWARDED_FOR']` too. Am I right? – stack Jul 01 '16 at 01:21
  • Yes, but in any case IP addresses ain't so reliable. I assume, that you also have a router at home, but if this router is used by all people of a university and you ban the IP address you would end up blocking the whole university from reaching your site, just because one person 'did something'. The real person behind an IP Address is really hard to identify and could also be using tor for example. – entwicklerseite Jul 01 '16 at 01:26
  • Ok, just I want to know, what happens when an user uses the proxy? A real IP is still into `REMOTE_ADDR`? Or it will be into `HTTP_X_FORWARDED_FOR`? Or both of them are containing two different IPs? – stack Jul 01 '16 at 01:29
  • I would use `HTTP_X_FORWARD_FOR` to supersede the `REMOTE_ADDR` as it -more probably- contains the originating IP. But I would consider using other information you have about the visitor, like when does he/she usually visit, which browser version and so on and I think also google does those kinds of checks to identify users. I have read that google can partially identify users by their typing speed and which words they usually misspell and so on ;) – entwicklerseite Jul 01 '16 at 01:37
  • Ah `:-)` I marked your answer as accepted-answer. thanks again. Just my last question: you said in your explanations that which one is better? Doing that by *PHP* or using something like *fail2ban*? – stack Jul 01 '16 at 01:40
  • The firewall method is much better, because the web server does not have to work at all and the connection gets dropped instantly. This method even comes handy to prevent many denial of service attacks and brute force password attacks. – entwicklerseite Jul 01 '16 at 01:47