Express.js req.ip renvoie :: ffff: 127.0.0.1

98

J'essaye actuellement d'obtenir l'adresse IP de l'utilisateur demandé. Le problème est que l'adresse IP revient ::ffff:127.0.0.1au lieu de 127.0.0.1. J'ai essayé d'utiliser l' trusted proxyoption (sans utiliser de proxy) et le req.ipsest vide. Utilisation de 4.x Express.js.

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});
basculeBOO
la source
Alors, qu'utilisez-vous req.ipou req.ips?
Aleksandr M
req.ip, juste essayé req.ipscomme test. Je ne suis tout simplement pas sûr de la cause du préfixe ::ffff:.
rockerBOO
Oui c'était ça. Windows 7 a une couche de transition pour les demandes IPv4 et ajoute ce préfixe à l'adresse IP.
rockerBOO

Réponses:

156

::ffff:est un préfixe de sous-réseau pour les adresses IPv4 (32 bits) placées dans un espace IPv6 (128 bits). IPv6 est divisé en deux parties, le préfixe de sous-réseau et le suffixe d'interface. Chacun a une longueur de 64 bits, soit 4 groupes de 4 caractères hexadécimaux.

Dans IPv6, vous êtes autorisé à supprimer les zéros non significatifs, puis à supprimer les zéros consécutifs, ce ::ffff:qui signifie en fait que 0000:0000:ffff:0000cette adresse a été désignée comme le préfixe de sous-réseau IPv4 à IPv6, de sorte que tout processeur IPv6 comprendra qu'il fonctionne avec une adresse IPv4 et la traitera en conséquence.

Dans un proche avenir, les adresses IP seront toutes IPv6, c'est parce que nous sommes presque à court de chiffres (4,2 milliards, moins un peu d'espace à des fins diverses) dans l'espace d'adressage IPv4.

IPv6 permet un espace beaucoup plus grand. "340 undecillions devraient suffire à n'importe qui" - Bill Gates s'exprimant sur IPv6.

Il est important de commencer à adresser les adresses IP en utilisant l'espace de noms IPv6 et donc d'inclure le ::ffff:dans votre code car à l'avenir, il y aura de vraies données hexadécimales entre ces deux points. Si vous le supprimez pour des raisons esthétiques, votre code se cassera lorsqu'il basculera sur un réseau IPv6 ou sera confronté à une adresse IPv6.

Certains réseaux utilisent actuellement IPv6 et vous serez bientôt confronté à des adresses IP IPv6; faites le saut maintenant ou risquez de casser votre code à l'avenir.

La version TL; DR (courte) du problème est la suivante: tout fonctionne correctement. Ne le changez pas, c'est la version IPv6 d'une adresse IPv4.

IPv6 IPv4

Si vous souhaitez rendre votre code compatible avec IPv6, il vous suffit de vérifier le ::ffff:préfixe ... s'il existe, supprimez-le et traitez le reste comme IPv4 ... s'il ::ffff:n'existe pas, c'est une adresse IPv6 et doit être traité comme tel. Vous pouvez revérifier en voyant si les points sont dans la chaîne, si c'est le cas, c'est IPv4.

Gardez à l'esprit que pour tout sauf les ajustements que vous devez apporter aux adresses IP, vous enregistrez simplement l'adresse IP, non? Il sera important pour l'analyseur et les agrégats de journaux de s'attendre ::ffff:127.0.0.1à l'avenir. À moins que vous n'ayez besoin de modifier une adresse IP, laissez-la comme ce que vous recevez.

Nick Steele
la source
Cela semble assez dangereux de vérifier le ::ffff:préfixe , cependant. Vous savez, un IPv6 a de nombreuses notations.
Константин Ван
1
Non, c'est sûr :) Il y a la proposition, puis il y a la mise en œuvre. fr.wikipedia.org/wiki/... L'IETF a reconnu que les routeurs ne peuvent pas graver autant de cycles à la recherche d'adresses IP, et aussi dans la nature, personne ne garde les zéros parce que c'est de l'espace perdu. L'idée d'autoriser les zéros n'était qu'une idée. En 2019, si vous avez envoyé :: ffff: dans un paquet réseau comme 0000: 0000: ffff: 0000, bien que techniquement valide pour la proposition originale, il n'est pas valide pour la recommandation IETF actuelle et ne sera pas vu dans la plupart des routeurs compatibles IPv6.
Nick Steele
1
Je peux donc être sûr qu'ils sont toujours sous les formes canoniques . Je ne savais pas comment les choses se passaient dans la nature. Merci.
Константин Ван
Ceci est malheureusement courant. Les humains ne prêtent attention que lorsque cela est nécessaire. Quelqu'un rédige quelque chose, la conception originale prend en charge beaucoup de fonctionnalités, ils font un RFC, personne ne fait vraiment attention à de nombreuses parties de la conception, cela devient une norme, puis lorsque les gens mis en œuvre remarquent que de grands changements sont nécessaires :) IPv6 est un peu étrange parce que l'appeler «canon» est un peu bizarre. Ils devraient probablement l'appeler "1.1" ou quelque chose comme ça pour que les gens puissent comprendre rapidement ce qui se passe, mais comme les zéros optionnels du brouillon original vous font dépenser 10 fois plus de calcul dans les routeurs, cela a été simplement ignoré.
Nick Steele
29

Cela semble être une bizarrerie d'ipv6: pour les adresses ipv4, ipv6 semble mélanger la notation ipv6 avec la notation ipv4.

Afin d'obtenir à la fois les adresses ipv4 et ipv6 dans la notation simple et non mélangée, j'utilise:

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

Windows 7 a activé IPv6 par défaut. Même si mon serveur écoute uniquement sur IPv4, Windows 7 envoie le ::ffff:préfixe à l'IPv4 dans le cadre de la transition vers IPv6

::ffff:0:0:0/96 - Un préfixe utilisé pour les adresses traduites IPv4 qui sont utilisées par le protocole Stateless IP / ICMP Translation (SIIT).

Transition depuis IPv4

basculeBOO
la source
8

J'avais des problèmes en essayant de comparer les adresses mappées ipv4 et j'ai trouvé la bibliothèque ipaddr.js utile :-)

par exemple

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

Essayez ceci pour obtenir l'adresse IP exacte en supprimant le sous-réseau,

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

Vous pouvez obtenir votre adresse IP seule ou avec la famille spécifiée à l'aide de 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
la source
-2
var ip = req.ip.split(':').pop();
Mateo Marin
la source
Comme d'autres réponses l'expliquent, il s'agit d'une adresse IPv6. Voir la réponse de @Nick Steele ci-dessus. Vous ne voulez vraiment pas faire ça.
Misha Nasledov