我目前正在尝试获取所请求用户的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({})
});
答案 0 :(得分:130)
::ffff:
is a subnet prefix for IPv4 (32 bit) addresses that are placed inside an IPv6 (128 bit) space. IPv6 is broken into two parts, the subnet prefix, and the interface suffix. Each one is 64 bits long, or, 4 groups of 4 hexadecimal characters.
In IPv6, you are allowed to remove leading zeros, and then remove consecutive zeros, meaning ::ffff:
actually translates to 0000:0000:ffff:0000
, this address has been designated as the IPv4 to IPv6 subnet prefix, so any IPv6 processor will understand it's working with an IPv4 address and handle it accordingly.
In the near future, IP addresses will all be IPv6, this is because we are nearly out of numbers (4.2 billion, minus some space for misc. purposes) in the IPv4 address space.
IPv6 allows for a much larger space. "340 undecillion aught to be enough for anyone" - Bill Gates speaking on IPv6.
It is important to start addressing IP addresses using the IPv6 namespace and therefore include the ::ffff:
in your code because in the future there will be real hexadecimal data between those colons. If you strip it off for aesthetic reasons, your code will break when it switches to an IPv6 network or it's confronted with an IPv6 address.
Some networks are currently running IPv6 and you will soon be confronted with IPv6 IP addresses; make the leap now or risk breaking your code in the future.
The TL;DR (short) version of the matter is: Everything is working fine. Don't alter it, it's the IPv6 version of an IPv4 address.
If you want to make your code compatible with IPv6, all you have to do is check for the ::ffff:
prefix... if it exists, remove it and process the remainder as IPv4... if ::ffff:
doesn't exist, it's an IPv6 address and needs to be processed as such.
You can double-check by seeing if periods are in the string, if so, it's IPv4.
Keep in mind for everything but adjustments you need to make to IP addresses, you're just recording the IP, right? It's going to be important to parser and log aggregates to expect ::ffff:127.0.0.1
and such in the future. Unless you need to alter an IP, just leave it as what you receive.
答案 1 :(得分:20)
这似乎是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)
}
答案 2 :(得分:9)
Windows 7默认启用了IPv6。即使我的服务器仅侦听IPv4,Windows 7也会向IPv4发送::ffff:
前缀,作为向IPv6过渡的一部分
::ffff:0:0:0/96
- 用于IPv4转换地址的前缀,由无状态IP / ICMP转换(SIIT)协议使用。
答案 3 :(得分:8)
我遇到了尝试比较ipv4映射地址的问题,并发现ipaddr.js库很有用: - )
例如
_.isEqual(ipaddr.process('::ffff:127.0.0.1'), ipaddr.process('127.0.0.1')) === true
答案 4 :(得分:5)
如果只需要IPv4,则可以强制节点服务器使用IPv4进行侦听。
对于快速应用,请编辑/bin/www
:
更改
server.listen(port);
到
server.listen(port, '0.0.0.0');
这至少对我有用。
https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback
答案 5 :(得分:1)
尝试通过删除子网划分来获取确切的IP地址,
let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
ip = ip.replace('::ffff:', '');
答案 6 :(得分:-1)
var ip = req.ip.split(':').pop();
答案 7 :(得分:-2)
您可以使用套接字单独或使用指定系列获取您的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]);
}