11

I'm building a site that is designed to be administered from localhost, but contains pages that expose data to internet or local network users. Can I rely on PHP's $_SERVER['REMOTE_ADDR'] as a secure/reliable way of identifying the user as localhost? Thanks!

Edit: To clarify, I am only concerned with determining whether or not the request originates from localhost (perhaps there is a better way).

leo
  • 2,022
  • 2
  • 17
  • 18

3 Answers3

12

That variable is filled with data provided by Apache (or another web server daemon) and should be reliable in identifying the IP address on the other end of the connection, yes. Check for 127.x.x.x (almost always 127.0.0.1) and ::1 (for IPv6). As Senica says, it may not always exist (for example, when running from the command line rather than through the web server). But if it is filled, it should be reliable.

To be able to fake it, somebody already needs pretty extensive access to your network and system in a way that you can't protect against with PHP anyway.

Steven Don
  • 2,436
  • 15
  • 14
  • Thanks for the response. This site is intended for deployment to customers for use on their own servers. I am concerned that this approach may cause customers to experience inconsistent behavior across server configurations (since I cannot guarantee that anything will even be returned) – leo Jul 16 '11 at 04:14
  • 1
    Then you should do the checks as defined above. If REMOTE_ADDR is not set, it is not coming in as an HTTP request. The chances of that are slim to none (and anybody capable of running your script that way should be competent enough to be aware that IP checks exist). Don't worry about the edge cases. If you check for 127.x.x.x and ::1 you'll have covered all sane setups. – Steven Don Jul 16 '11 at 04:21
-1

This may not typically apply to connections from localhost but you should take proxies into account. If the remote end is using a HTTP proxy, $_SERVER['REMOTE_ADDR'] will contain the IP address of that proxy rather than the IP address of the client itself.

However, if it is a proxy which has privacy settings disabled, then you may have a chance to obtain client IP using the following snippet:

// will be set by the proxy if no privacy is enabled:
if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    return $_SERVER['HTTP_X_FORWARDED_FOR'];
} else if(isset($_SERVER['REMOTE_ADDR'])) {
    return $_SERVER['REMOTE_ADDR'];
}

But if your client is using a HTTP proxy with privacy enabled, then you won't have a chance to get the clients IP.


Security Hint (thanks @deceze) Note that if you rely on the HTTP_X_FORWARDED_FOR header, it will be easy for attackers to spoof their IP. Although this is possible using other techniques as well, it will be very easy using the HTTP_X_FORWARDED_FOR header. You have been warned. But anyway an web application should never use IP information for security, therefore it's just a side-note

hek2mgl
  • 152,036
  • 28
  • 249
  • 266
  • 1) By using X-Forwarded-For headers *instead of* `REMOTE_ADDR` you give anyone a great way to spoof their IP address very easily; if at all use it *in addition to* `REMOTE_ADDR` as meta information 2) `isset && !empty` is redundant, just `!empty` will do just fine. – deceze Jun 01 '13 at 07:29
  • @deceze Many, thanks for the spoofing hint! I never thought about this.... To 2.), that's not correct, they are not the same: check [this fiddle](http://phpfiddle.org/lite/code/6c9-8zz) – hek2mgl Jun 01 '13 at 08:46
  • I said `isset && !empty` is pointless, not that they're the same. – deceze Jun 01 '13 at 10:06
  • @deceze `isset && !empty` is not pointless. It checks if an array index exists and it's value is not an empty string. – hek2mgl Jun 01 '13 at 11:53
  • Please read [The definitive guide to isset and empty](http://kunststube.net/isset). – deceze Jun 01 '13 at 12:04
  • @deceze ? Please read the PHP manual. I'm unsure what you don't understand with this. isset will return true if an array index exists and its value is not equal to NULL. an empty string is not == NULL. Therefore the !empty check, as empty will return true on empty strings – hek2mgl Jun 01 '13 at 12:10
  • Btw the article is nice, but tells the same as the PHP documentation – hek2mgl Jun 01 '13 at 12:23
  • Again: `isset && !empty` is **redundant**. You do not need `isset` if you're checking for `!empty`. `isset` checks that a variable *is set* and is not `null`. `!empty` checks that a variable *is set* and is not `null` and is not `false` and is not `''` and all the other things that match `== false`. Just `!empty` is fine, no `isset` needed. – deceze Jun 01 '13 at 12:29
  • See [Why check both isset() and !empty()](http://stackoverflow.com/questions/4559925/why-check-both-isset-and-empty). – deceze Jun 01 '13 at 12:30
  • @deceze I must say thanks. I know about the logic but expected an E_NOTICE being thrown if `empty($arr[$key])` is accessed but the index does not exists. – hek2mgl Jun 01 '13 at 12:43
-1

No. It depends on the web server whether is serves up remote_addr or not.

RETRACT THAT...was thinking about HTTP_REFERER.

It should give you the ip address...yes. Remember there could be proxy's.

Senica Gonzalez
  • 7,996
  • 16
  • 66
  • 108