request.connection.remoteAddress Now Prefixed in ::ffff in node.js

22,043

Solution 1

Is my Node server listening to IPv6 addresses?

Yes. Your server is listening to IPv6 connections and the IPV6_V6ONLY flag isn't set with the result that IPv4 connections are processed by the same socket. You can read some more about this flag in this question.

Whether IPv6 connections are possible (can be routed to your server) is irrelevant in that case - the important thing is that IPv4 connections are received by a socket listening to IPv6 connections.

Is ::ffff:192.168.1.10 actually an IPv6 address or is it an IPv4 address?

Both. IPv6 addresses can embed IPv4 addresses - and this is one of these embedded addresses. See IPv4-mapped IPv6 addresses.

Is the easiest way to tell if a remoteAddress is IPv6 to check if the string contains ::?

An IPv6 address doesn't necessarily contain ::, it's rather a short notation indicating some number of zeroes. ::ffff:192.168.1.10 is equivalent to 0:0:0:0:0:ffff:192.168.1.10 or 0:0:0:0:0:ffff:c0a8:010a (see IPv6 address presentation). So in order to distinguish IPv6 and IPv4 addresses you should simply check for a single colon - :.

When storing IPv4 addresses in the database I used to use something like INET_ATON to change them into large integers. Should I abandon this and just store all remote addresses as strings that can be 45 characters long (maximum length of an IPv6 address string)

An IPv6 address is a 128-bit number - even if you can store it as a number (e.g. as two BIGINT numbers in MySQL), it's questionable whether this approach really makes sense. The only scenario I can think of where you would need to work with numbers is evaluating subnet masks, for everything else a string is sufficient and easier to handle.

Solution 2

re: #4, a library like ipaddr.js works well, e.g.:

var ipString = request.connection.remoteAddress;
if (ipaddr.IPv4.isValid(ipString)) {
  // ipString is IPv4
} else if (ipaddr.IPv6.isValid(ipString)) {
  var ip = ipaddr.IPv6.parse(ipString);
  if (ip.isIPv4MappedAddress()) {
    // ip.toIPv4Address().toString() is IPv4
  } else {
    // ipString is IPv6
  }
} else {
  // ipString is invalid
}
Share:
22,043
Kirk Ouimet
Author by

Kirk Ouimet

The internet is a miracle.

Updated on March 03, 2020

Comments

  • Kirk Ouimet
    Kirk Ouimet about 4 years

    I recently changed my router over to one provided by Google for Google Fiber (yay!) and now I am noticing a change in what I am seeing when I inspect request.connection.remoteAddress while I develop on my local server. Before, I used to see this:

    request.connection.remoteAddress; // 192.168.1.10
    

    Now I am seeing this:

    request.connection.remoteAddress; // ::ffff:192.168.1.10
    
    1. Can anyone explain what is going on?
    2. Is my Node server listening to IPv6 addresses?
    3. Is ::ffff:192.168.1.10 actually an IPv6 address or is it an IPv4 address?
    4. Is the easiest way to tell if a remoteAddress is IPv6 to check if the string contains ::?
    5. When storing IPv4 addresses in the database I used to use something like INET_ATON to change them into large integers. Should I abandon this and just store all remote addresses as strings that can be 45 characters long (maximum length of an IPv6 address string)