I'm sorry if this is a repeated question but I don't completely understand how I should get a remote user IP address.
Let's say I have a simple request route such as:
app.get(/, function (req, res){
var forwardedIpsStr = req.header('x-forwarded-for');
var IP = '';
if (forwardedIpsStr) {
IP = forwardedIps = forwardedIpsStr.split(',')[0];
}
});
Is the above approach correct to get the real user IP address or is there a better way? And what about proxies?
If you are running behind a proxy like NGiNX or what have you, only then you should check for 'x-forwarded-for':
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
If the proxy isn't 'yours', I wouldn't trust the 'x-forwarded-for' header, because it can be spoofed.
While the answer from @alessioalex works, there's another way as stated in the Express behind proxies section of Express - guide. I prefer this solution because I feel the one from @alessioalex is hacky and may require code changes everywhere.
app.enable('trust proxy')
to your express initialization codereq.ip
or req.ips
in the usual way (as if there isn't a reverse proxy)NOTE: req.connection.remoteAddress
won't work with my solution.
In nginx.conf
file:
proxy_set_header X-Real-IP $remote_addr;
In node.js
server file:
var ip = req.headers['X-Real-IP'] || req.connection.remoteAddress;
Particularly for node, the documentation for the http server component, under event connection says:
[Triggered] when a new TCP stream is established. [The] socket is an object of type net.Socket. Usually users will not want to access this event. In particular, the socket will not emit readable events because of how the protocol parser attaches to the socket. The socket can also be accessed at
request.connection
.
So, that means request.connection
is a socket and according to the documentation there is indeed a socket.remoteAddress attribute which according to the documentation is:
The string representation of the remote IP address. For example, '74.125.127.100' or '2001:4860:a005::68'.
Under express, the request object is also an instance of the Node http request object, so this approach should still work.
However, under Express.js the request already has two attributes: req.ip and req.ips
req.ip
Return the remote address, or when "trust proxy" is enabled - the upstream address.
req.ips
When "trust proxy" is
true
, parse the "X-Forwarded-For" ip address list and return an array, otherwise an empty array is returned. For example if the value were "client, proxy1, proxy2" you would receive the array ["client", "proxy1", "proxy2"] where "proxy2" is the furthest down-stream.
It may be worth mentioning that, according to my understanding, the Express req.ip
is a better approach than req.connection.remoteAddress
, since req.ip
contains the actual client ip (provided that trusted proxy is enabled in express), whereas the other may contain the proxy's IP address (if there is one).
That is the reason why the currently accepted answer suggests:
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
The req.headers['x-forwarded-for']
will be the equivalent of express req.ip
.