Express.js:如何获取远程客户端地址

我不完全了解如何获得远程用户IP地址。

比方说,我有一个简单的请求路线,如:

app.get(/, function (req, res){ var forwardedIpsStr = req.header('x-forwarded-for'); var IP = ''; if (forwardedIpsStr) { IP = forwardedIps = forwardedIpsStr.split(',')[0]; } }); 

上面的方法是否正确得到真正的用户IP地址还是有更好的办法? 那么代理呢?

如果你在NGiNX之类的代理之后运行,那么你应该检查'x-forwarded-for':

 var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; 

如果代理不是'你的',我不会相信'x-forwarded-for'标题,因为它可能被欺骗。

虽然@alessioalex的答案是有效的,但快递指南的 代理部分后面还有另一种方法。

  1. app.enable('trust proxy')到您的快速初始化代码。
  2. 当你想获得远程客户端的IP地址时,以通常的方式使用req.ipreq.ips (就好像没有反向代理一样)

如果您需要比信任x-forwarded-for标头中所有内容更复杂的东西,并且代理不会从不受信任的来源中移除预先存在的x-forwarded-for标头,那么可以使用“信任代理”的更多选项。 有关更多详细信息,请参阅链接指南

注意: req.connection.remoteAddress不适用于我的解决scheme。

nginx.conf文件中:
proxy_set_header X-Real-IP $remote_addr;

node.js服务器文件中:
var ip = req.headers['x-real-ip'] || req.connection.remoteAddress;

注意,表示小写标题

特别是对于节点,HTTP服务器组件的文档,在事件连接下说:

当一个新的TCPstreambuild立时触发。 [socket]是net.Sockettypes的对象。 通常用户不会想要访问这个事件。 特别是,由于协议parsing器如何连接到套接字,套接字将不会发出可读的事件。 套接字也可以通过request.connection访问。

所以,这意味着request.connection是一个套接字,根据文档确实有一个socket.remoteAddress属性,根据文档是:

远程IP地址的string表示。 例如,“74 .125.127.100”或“2001:4860:a005 :: 68”。

在express下,请求对象也是Node http请求对象的一个​​实例,所以这种方法应该仍然有效。

但是,在Express.js下,请求已经有两个属性: req.ip和req.ips

req.ip

返回远程地址,或当“信任代理”启用 – 上游地址。

req.ips

当“信任代理”为true ,parsing“X-Forwarded-For”IP地址列表并返回一个数组,否则返回一个空数组。 例如,如果值为“client,proxy1,proxy2”,您将收到数组[“client”,“proxy1”,“proxy2”],其中“proxy2”是最下游的数据stream。

值得一提的是,根据我的理解,Express req.ip是比req.connection.remoteAddress更好的方法,因为req.ip包含实际的客户端ip(假设在express中启用了可信代理),而其他可能包含代理的IP地址(如果有的话)。

这就是为什么目前接受的答案表明:

var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;

req.headers['x-forwarded-for']将等同于express req.ip

根据Express后面的代理 , req.ip已经考虑了反向代理,如果你已经正确configurationtrust proxy 。 因此,它比从networking层获得并且不知道代理的req.connection.remoteAddress要好。

  1. 添加app.set('trust proxy', true)
  2. 以通常的方式使用req.ipreq.ips

这对我来说比其他的更好。 我的网站在CloudFlare的后面,似乎需要cf-connecting-ip

 req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress 

没有testingExpress后面的代理,因为它没有说这个cf-connecting-ip头。