Express.js req.ip está regresando :: ffff: 127.0.0.1

98

Actualmente estoy tratando de obtener la IP del usuario solicitado. El problema es que la IP está regresando en ::ffff:127.0.0.1lugar de 127.0.0.1. Intenté usar la trusted proxyopción (aunque no usé un proxy) y req.ipsestá en blanco. Usando 4.x Express.js.

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});
rockerBOO
fuente
Entonces, ¿qué estás usando req.ipo req.ips?
Aleksandr M
req.ip, solo probado req.ipscomo prueba. Simplemente no estoy seguro de qué está causando el prefijo ::ffff:.
rockerBOO
Sí, esto fue todo. Windows 7 tiene una capa de transición para solicitudes de IPv4 y agrega este prefijo a la IP.
rockerBOO

Respuestas:

155

::ffff:es un prefijo de subred para direcciones IPv4 (32 bits) que se colocan dentro de un espacio IPv6 (128 bits). IPv6 se divide en dos partes, el prefijo de subred y el sufijo de interfaz. Cada uno tiene 64 bits de longitud o 4 grupos de 4 caracteres hexadecimales.

En IPv6, puede eliminar los ceros iniciales y luego eliminar los ceros consecutivos, lo que significa que en ::ffff:realidad se traduce en0000:0000:ffff:0000 , esta dirección ha sido designada como el prefijo de subred IPv4 a IPv6, por lo que cualquier procesador IPv6 entenderá que está funcionando con una dirección IPv4 y la manejará. en consecuencia.

En un futuro cercano, todas las direcciones IP serán IPv6, esto se debe a que estamos casi sin números (4,2 mil millones, menos algo de espacio para propósitos diversos) en el espacio de direcciones IPv4.

IPv6 permite un espacio mucho más grande. "340 mil millones deberían ser suficientes para cualquiera" - Bill Gates hablando por IPv6.

Es importante comenzar a direccionar las direcciones IP utilizando el espacio de nombres IPv6 y, por lo tanto, incluirlas ::ffff:en su código porque en el futuro habrá datos hexadecimales reales entre esos dos puntos. Si lo quita por razones estéticas, su código se romperá cuando cambie a una red IPv6 o se enfrente a una dirección IPv6.

Algunas redes ejecutan actualmente IPv6 y pronto se enfrentará a direcciones IP IPv6; dé el salto ahora o arriesgue su código en el futuro.

La versión TL; DR (corta) del asunto es: Todo está funcionando bien. No lo cambie, es la versión IPv6 de una dirección IPv4.

IPv6 IPv4

Si desea que su código sea compatible con IPv6, todo lo que tiene que hacer es verificar el ::ffff:prefijo ... si existe, eliminarlo y procesar el resto como IPv4 ... si ::ffff:no existe, es una dirección IPv6 y necesita ser procesado como tal. Puede verificar si hay puntos en la cadena, si es así, es IPv4.

Tenga en cuenta que para todo menos los ajustes que necesita hacer en las direcciones IP, solo está grabando la IP, ¿verdad? Será importante para el analizador y los agregados de registros esperar ::ffff:127.0.0.1y demás en el futuro. A menos que necesite modificar una IP, déjela como lo recibe.

Nick Steele
fuente
Sin embargo, parece bastante peligroso comprobar el ::ffff:prefijo . Ya sabes, un IPv6 tiene muchas notaciones.
Константин Ван
1
No, es seguro :) Está la propuesta y luego está la implementación. en.wikipedia.org/wiki/… El IETF ha reconocido que los enrutadores no pueden grabar tantos ciclos buscando direcciones IP, y también en la naturaleza, nadie mantiene los ceros porque es espacio desperdiciado. La idea de permitir los ceros fue solo una idea. En 2019, si envió :: ffff: en un paquete de red como 0000: 0000: ffff: 0000, aunque técnicamente es válido para la propuesta original, no es válido para la recomendación actual de IETF y no se verá en la mayoría de los enrutadores compatibles con IPv6.
Nick Steele
1
Así que puedo estar seguro de que siempre estarán en las formas canónicas . No sabía cómo iban las cosas en la naturaleza. Gracias.
Константин Ван
Desafortunadamente, esto es común. Los humanos prestan atención solo cuando es necesario. Alguien redacta algo, el diseño original admite muchas características, hacen un RFC, nadie realmente presta atención a muchas partes del diseño, se convierte en un estándar, luego, cuando se implementa, la gente nota que se necesitan grandes cambios :) IPv6 es un poco extraño porque llamarlo "canónico" es un poco extraño. Probablemente deberían llamarlo "1.1" o algo así para que la gente pueda entender rápidamente lo que está sucediendo, pero debido a que los ceros opcionales del borrador original te hacen gastar 10 veces más en computación en enrutadores, simplemente fue ignorado.
Nick Steele
29

Esto parece ser una peculiaridad de ipv6: para las direcciones ipv4, ipv6 parece mezclar la notación ipv6 con la notación ipv4.

Para obtener las direcciones ipv4 e ipv6 en la notación simple y sin mezclar, estoy usando:

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

Windows 7 tiene IPv6 habilitado de forma predeterminada. Aunque mi servidor solo escucha en IPv4, Windows 7 envía el ::ffff:prefijo a IPv4 como parte de la transición a IPv6

::ffff:0:0:0/96 - Un prefijo utilizado para direcciones traducidas de IPv4 que utiliza el protocolo de traducción de IP / ICMP sin estado (SIIT).

Transición de IPv4

rockerBOO
fuente
8

Estaba teniendo problemas al intentar comparar direcciones asignadas ipv4 y encontré útil la biblioteca ipaddr.js :-)

p.ej

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

Intente esto para obtener la dirección IP exacta eliminando las subredes,

    let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    ip = ip.toString().replace('::ffff:', '');
MAREESKANNNAN RAJENDRAN
fuente
-2

Puede obtener su dirección IP sola o con la familia especificada usando sockets

     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]);  
      }
muthukumar selvaraj
fuente
-2
var ip = req.ip.split(':').pop();
Mateo Marín
fuente
Como explican otras respuestas, esta es una dirección IPv6. Vea la respuesta de @Nick Steele arriba. Realmente no quieres hacer esto.
Misha Nasledov