Is $_SERVER['REMOTE_ADDR'] secure? - php

I'm working on a API project that depends partialy from $_SERVER['REMOTE_ADDR'] (like 50%).
My API checks the IP of client first and then checks the token, and i want to know if should i worry about getting this IP from this global variable.
can the client some how "forge" this?
i know that VPN can camouflage the IP, but thats not a problem since he will not getting access anyway.

Due to the three way handshake of TCP/IP - $_SERVER['REMOTE_ADDR'] cannot be spoofed. There is (however) no guarantee that this is the IP address of the end user. He may be behind proxy or VPN. What you can guarantee with $_SERVER['REMOTE_ADDR'] is that the machine which is directly connected to you has this exact IP and it is real.

Related

How PHP populates $_SERVER['REMOTE_ADDR'] with client IP address?

I have a PHP application in front of me that reads the IP address of the user from $_SERVER['REMOTE_ADDR'].
I don't seem to quite understand how it gets populated. I assume that it is basically reading the client IP address from the request headers. Is that correct?
Note:
I am not asking about whether it is providing the client IP address or not. The documentation already states that fact. I am more interested in the knowing about the "how". Is it retrieving the IP address implicitly from the request headers?
Not a network expert in any way, but as it's an HTTP request, it gets delivered over a TCP connection. The webserver populates $_SERVER['REMOTE_ADDR'] from a TCP socket that is used to communicate with the browser.

Why does $_SERVER['REMOTE_ADDR'] return the gateway ip rather than the remote ip with a fortigate router?

I have a server connected to the internet through a Fortigate 40C. When my php code calls $_SERVER['REMOTE_ADDR'], it returns the ip address of the router (the fortigate) rather than the remote IP accessing the php script.
Why is this?
The Fortigate has an option to "enable NAT" on a policy, which doesn't mean translate the addresses (it does that for you anyway), but does mean it alters some packets replacing the remote IP with the gateway IP.
Make sure that "Enable NAT" is disabled, and $_SERVER['REMOTE_ADDR'] will work as expected.

Can we spoof $_SERVER['REMOTE_ADDR'] / user ip with php cURL?

Well the title basically says it.
But for more info . .
This method works but . .
$ip = '1.1.1.1';
curl_setopt($handle, CURLOPT_HTTPHEADER, array("REMOTE_ADDR: $ip", "X_FORWARDED_FOR: $ip"));
It only adds these two keys on the $_SERVER array
HTTP_REMOTE_ADDR
HTTP_X_FORWARDED_FOR
The key REMOTE_ADDR still remains the same.
Can REMOTE_ADDR be changed? The answer here says NO. But a comment also says It may, however, NOT be the user's real IP address because it may be hidden by proxies and other methods. That is why the general rule is to not depend on $_SERVER['REMOTE_ADDR'] for a security feature.
With all that aside is there a curl php method to also hide/mask/change the ip? (any other php method aside from the above code would do.)
AND
Is there a way for countering the method OR Is there a way to get the ACTUAL REAL IP of a user?
Cheers!
No. $_SERVER['REMOTE_ADDR'] is the actual physical IP address the client used to connect to the webserver, as confirmed by a three-way TCP handshake. There's no way to fake this by setting simple HTTP headers. You also cannot make the webserver/PHP overwrite this value with something else in any way. $_SERVER['REMOTE_ADDR'] is set from TCP connection information, period.
To actually spoof an IP address, you have to go much deeper into the actual network layer and have some level of control over network equipment/man in the middle positions/proxies/whatnot to actually be able to establish a TCP connection from an IP address other than the one you're establishing it from.
Is there a way for countering the method OR Is there a way to get the ACTUAL REAL IP of a user?
No. "The actual IP address of the user" is the address your webserver received the connection from, period. There is no other address for you. The client connects to your server from a certain IP, this is confirmed with a three-way TCP handshake, that's the only address you know for this client. This client may be a proxy or a NAT router (i.e. a proxy) or something else, you simply do not know and neither should it make any difference to you.
If the client uses a browser behind a proxy, the $_SERVER['REMOTE_ADDR'] will be the IP address of the proxy. The remote address is the IP of the machine that is making the connection.
If the proxy uses headers to indicate if the connection is performed in behalf of other machines, you can use these headers to determine the IP of the browser behind the proxy.
Some of these HTTP headers are converted to environment variables such as $_SERVER['HTTP_X_FORWARDED_FOR'], $_SERVER['HTTP_X_FORWARDED'], $_SERVER['HTTP_FORWARDED_FOR'] and $_SERVER['HTTP_FORWARDED']
You may check if some of these variables have been defined by the server and (try to) determine the IP of the browser behind of the proxy.
Note that the RFC 6648 deprecated the X-* headers and the RFC 7239 deprecated X-Forwarded-* by defining a Forwarded header.
You can check some answers at
Get the client IP address using PHP
What is a full specification of X-Forwarded-Proto HTTP header?

How do I securely identify a remote device in PHP?

Is there a safe way, to identify a device which might be behind a Router (so the IP is not unique) in PHP?
Background: I have several embedded devices (self programmed & adaptable) which contact a webserver (php+mysql) with status updates. These updates are then - if the source is confirmed - saved to the database.
As I understand it $_SERVER['REMOTE_ADDR'] usually can be trusted (except some IIS configuration where it may - under special circumstances - wrongfully return 127.0.0.1; but different story)
Anyhow since I use SSL, the IP address really should not be a problem, because there a handshake is required and if the IP is faked or simply wrong, the connection should not be established
For now I require IP addresses to be whitelisted by admin, for an status update to be acceppted
The device additionally sends the MAC address via $_POST to identify the different modules with identical IP address (I know this can very easily be forged, and right now will be trusted if the IP address is trusted)
So first of all I am not sure if the IP address in itself is enough for it to be safe from attacks from the outside
Secondly if the device is behind a router, it will have the same IP address as every PC/device on that network. So about anyone there could forge a status update with a fake MAC address (simply as post variable), and since the IP address is whitelisted it will be trusted
So is there any way of confirming the identity of a device, or do you know a better way of doing this?
Aside: Going the other way, and have the webserver poll the different devices might be an option, but since there might be many (> 2000) devices of which we need the very last status (change) I thought it to be inefficient.
IP addresses can be spoofed, MAC addresses can be forged, so theses methods are not sufficient. The general approach is to assign a key to each client device (possibly the same key to all devices, even if this probably a bad idea). The "key" can be anything from a predefined string (weak, think username/password) to a signed certificate (strong, think SSL).
Both can be implemented either at the application level (by PHP) or at server level. If your application runs on Apache httpd server, I would rather recommend using its built-in features as it supports both approaches.

Alternative to $_SERVER['REMOTE_ADDR'] in php

Is there any alternative to the $_SERVER['REMOTE_ADDR']. Which returns the ip address of the computer accessing a site.
I'm trying to search about same external ip assigned by router, and got into this:
How do two computers connect to same external address through NAT?
And found out that the same external ip is assigned if the computers are connected to the same modem.
I'm creating a simple login program in php which uses $_SERVER['REMOTE_ADDR'] to determine if a user is already logged in somewhere else in the same network. And this won't actually work if those computers are connected to the same modem through the router.
No, this is the best you can do. The server only knows where the request is coming from, and that may be a proxy or a NAT router or some other entity which is not the direct enduser. There's nothing you can do about that, that's how networks work.
The solution is simple: Don't use IPs to identify users. Ever. Use cookies.
Using a more traditional cookie based login solves this. The browser identifies the user by providing a unique token. Ip, as you have discovered, is not unique.

Categories