Express.js req.ip正在返回:: ffff:127.0.0.1

我目前正在尝试获取请求的用户的IP。 问题是IP正在返回::ffff:127.0.0.1而不是127.0.0.1 。 我尝试使用trusted proxy选项(虽然不使用代理), req.ips是空白的。 使用4.x Express.js。

 router.get('/', function(req, res, next) { console.log('ip', req.ip) res.send({}) }); 

::ffff:是放置在IPv6(128位)空间内的IPv4(32位)地址的子网前缀。 IPv6分为两部分,子网前缀和接口后缀。 每个是64位长,或者4个4个hex字符组。

在IPv6中,您可以删除前导零,然后删除连续的零,意思是::ffff:实际转换为0000:0000:ffff:0000 ,这个地址被指定为IPv4到IPv6子网前缀,所以任何IPv6处理器会理解它正在使用IPv4地址并相应地处理它。

在不久的将来,IP地址将全部是IPv6,这是因为我们在IPv4地址空间中几乎没有数字(42亿,减去一些空间用于其他目的)。

IPv6允许更大的空间。 “对于任何人来说,340亿就足够了” – 比尔·盖茨谈到IPv6。

使用IPv6命名空间开始寻址IP地址非常重要,因此在您的代码中包含::ffff:因为将来会在这些冒号之间存在真正的hex数据。 如果出于审美原因将其剥离,则当您切换到IPv6networking或面临IPv6地址时,您的代码将会中断。

有些networking当前正在运行IPv6,您将很快遇到IPv6 IP地址; 现在做出这个飞跃或者将来有可能破坏你的代码。

TL; DR(简称)版本的问题是:一切工作正常。 不要改变它,它是IPv4地址的IPv6版本。

IPv6的 IPv4的

如果你想使你的代码与IPv6兼容,你所要做的就是检查::ffff:前缀…如果存在,将其移除,并将其余部分处理为IPv4 … if ::ffff: doesn'不存在,它是一个IPv6地址,需要像这样处理。 您可以通过查看句点是否在string中进行仔细检查,如果是,则为IPv4。

请记住,除了需要对IP地址进行的调整之外,您只需loggingIP即可,对吗? parsing器和日志聚合将会非常重要,以期望::ffff:127.0.01等。 除非您需要更改IP,否则将其作为您收到的内容保留。

Windows 7默认启用了IPv6。 即使我的服务器仅侦听IPv4,Windows 7也会将::ffff:前缀作为向IPv6过渡的一部分发送给IPv4

::ffff:0:0:0/96 – 用于无状态IP / ICMP转换(SIIT)协议使用的IPv4转换地址的前缀。

从IPv4过渡

我遇到了尝试比较ipv4映射地址的问题,并发现ipaddr.js库有帮助:-)

例如

 _.isEqual(ipaddr.process('::ffff:127.0.0.1'), ipaddr.process('127.0.0.1')) === true 

这似乎是ipv6的怪癖:对于ipv4地址,ipv6似乎将ipv6表示法与ipv4表示法混合在一起。

为了使ipv4和ipv6地址都以简单的混合符号表示,我正在使用:

 var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; if (ip.substr(0, 7) == "::ffff:") { ip = ip.substr(7) } 

您可以单独获取您的IP地址,也可以使用套接字指定家庭

  var app = require('express')(); app.get("/ip", (req, res) => { console.log(req.ip) let ip = req.ip.split(':'); let ip_details = req.socket.address(); console.log(ip_details); // { address: '::ffff:127.0.0.1', family: 'IPv6', port: 3001 console.log(ip[3]);//127.0.0.1 res.json(ip[3]); }