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

roc*_*BOO 86 node.js express

我目前正在尝试获取所请求用户的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({})
});
Run Code Online (Sandbox Code Playgroud)

Nic*_*ele 139

::ffff:是IPv4(32位)地址的子网前缀,位于IPv6(128位)空间内.IPv6分为两部分,子网前缀和接口后缀.每个都是64位长,或4组4个十六进制字符.

在IPv6中,您可以删除前导零,然后删除连续的零,意味着::ffff:实际转换为0000:0000:ffff:0000,此地址已被指定为IPv4到IPv6子网前缀,因此任何IPv6处理器都将理解它正在使用IPv4地址并处理它因此.

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

IPv6允许更大的空间."对于任何人都应该足够"340亿美元" - 比尔盖茨谈论IPv6.

使用IPv6命名空间开始寻址IP地址非常重要,因此::ffff:在您的代码中包含,因为将来在这些冒号之间会有真正的十六进制数据.如果出于美观原因将其剥离,那么当代码切换到IPv6网络或者遇到IPv6地址时,代码就会中断.

有些网络目前正在运行IPv6,您很快就会面临IPv6 IP地址; 现在实现飞跃,或者将来冒险破坏您的代码.

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

IPv6的 IPv4的

如果你想让你的代码与IPv6兼容,你所要做的就是检查::ffff:前缀...如果存在,删除它并将剩余部分处理为IPv4 ...如果::ffff:不存在,则它是一个IPv6地址,需要像这样处理.您可以通过查看字符串中是否有句点来仔细检查,如果是,则为IPv4.

请记住,除了需要对IP地址进行调整外,您只需记录IP,对吗?解析和记录聚合的期望::ffff:127.0.0.1和未来的重要性是非常重要的.除非您需要更改IP,否则请将其保留为您收到的IP.

  • 不,它是安全的:) 有提案,然后有实施。https://en.wikipedia.org/wiki/IPv6_address#Recommended_representation_as_text IETF 已经认识到路由器无法消耗那么多周期来查找 IP 地址,而且在野外,没有人保留零,因为这是浪费空间。允许零的想法只是一个想法。在 2019 年,如果您在网络数据包中发送 ::ffff: 作为 0000:0000:ffff:0000,尽管技术上对于原始提案有效,但它对于当前的 IETF 建议无效,并且不会在大多数 IPv6 兼容路由器中看到。 (2认同)
  • 不幸的是,这种情况很常见。人类只有在必要时才会注意。有人起草了一些东西,原始设计支持很多功能,他们制作了 RFC,没有人真正关注设计的许多部分,它成为一个标准,然后当实施时,人们注意到需要进行大的更改:) IPv6 有点奇怪因为称其为“规范”有点奇怪。他们可能应该将其称为“1.1”或其他名称,以便人们可以快速了解发生了什么,但由于原始草案的可选零使您在路由器中花费 10 倍的计算量,因此它被简单地忽略了。 (2认同)

ann*_*neb 23

这似乎是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)
}
Run Code Online (Sandbox Code Playgroud)


roc*_*BOO 9

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

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

从IPv4过渡


You*_*Ken 9

如果只需要IPv4,则可以强制节点服务器使用IPv4进行侦听。

对于快速应用程序编辑/bin/www

更改

server.listen(port);
Run Code Online (Sandbox Code Playgroud)

server.listen(port, '0.0.0.0');
Run Code Online (Sandbox Code Playgroud)

这至少对我有用。

https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback


小智 8

我在尝试比较ipv4映射地址时遇到了问题,并发现ipaddr.js很有用:-)

例如

_.isEqual(ipaddr.process('::ffff:127.0.0.1'), ipaddr.process('127.0.0.1')) === true
Run Code Online (Sandbox Code Playgroud)


小智 5

尝试通过删除子网划分来获取确切的 IP 地址,

    let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    ip = ip.toString().replace('::ffff:', '');
Run Code Online (Sandbox Code Playgroud)