Express.js req.ip is returning ::ffff:127.0.0.1
::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 ought 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 change 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 the 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.
This seems to be a quirk of ipv6: for ipv4 addresses, ipv6 seems to mix ipv6 notation with ipv4 notation.
In order to get both ipv4 and ipv6 addresses in the simple, unmixed notation, I am using:
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
if (ip.substr(0, 7) == "::ffff:") {
ip = ip.substr(7)
}
If you just need IPv4, you could force the node server to listen using IPv4.
For an express app edit /bin/www
:
change
server.listen(port);
to
server.listen(port, '0.0.0.0');
This worked for me at least.
https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback