Express.js req.ip gibt :: ffff: 127.0.0.1 zurück

96

Ich versuche gerade, die IP des angeforderten Benutzers zu erhalten. Das Problem ist, dass die IP ::ffff:127.0.0.1statt zurückkehrt 127.0.0.1. Ich habe versucht, die trusted proxyOption zu verwenden (obwohl ich keinen Proxy verwende) und die req.ipsist leer. Verwenden von 4.x Express.js.

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});
rockerBOO
quelle
Also, was benutzt du req.ipoder req.ips?
Aleksandr M
req.ip, nur req.ipsals Test versucht . Ich bin mir nur nicht sicher, was das Präfix verursacht ::ffff:.
RockerBOO
Ja das war es. Windows 7 verfügt über eine Übergangsebene für IPv4-Anforderungen und fügt dieses Präfix der IP hinzu.
RockerBOO

Antworten:

155

::ffff:ist ein Subnetzpräfix für IPv4-Adressen (32 Bit), die in einem IPv6-Bereich (128 Bit) platziert sind. IPv6 besteht aus zwei Teilen, dem Subnetzpräfix und dem Schnittstellensuffix. Jedes ist 64 Bit lang oder 4 Gruppen mit 4 Hexadezimalzeichen.

In IPv6 können Sie führende Nullen entfernen und dann aufeinanderfolgende Nullen entfernen. Dies bedeutet , dass diese Adresse ::ffff:tatsächlich 0000:0000:ffff:0000als IPv4-zu-IPv6-Subnetzpräfix bezeichnet wurde, sodass jeder IPv6-Prozessor versteht, dass er mit einer IPv4-Adresse arbeitet, und damit umgehen kann entsprechend.

In naher Zukunft werden alle IP-Adressen IPv6 sein. Dies liegt daran, dass wir im IPv4-Adressraum fast keine Zahlen mehr haben (4,2 Milliarden, abzüglich etwas Speicherplatz für verschiedene Zwecke).

IPv6 bietet viel mehr Platz. "340 Undecillion sollten für jeden ausreichen" - Bill Gates spricht über IPv6.

Es ist wichtig, IP-Adressen mithilfe des IPv6-Namespace zu adressieren und diese daher ::ffff:in Ihren Code aufzunehmen, da in Zukunft echte hexadezimale Daten zwischen diesen Doppelpunkten vorhanden sein werden. Wenn Sie es aus ästhetischen Gründen entfernen, wird Ihr Code beschädigt, wenn er zu einem IPv6-Netzwerk wechselt oder mit einer IPv6-Adresse konfrontiert wird.

In einigen Netzwerken wird derzeit IPv6 ausgeführt, und Sie werden bald mit IPv6-IP-Adressen konfrontiert. Machen Sie jetzt den Sprung oder riskieren Sie, Ihren Code in Zukunft zu brechen.

Die TL; DR (kurze) Version der Sache lautet: Alles funktioniert gut. Ändern Sie es nicht, es ist die IPv6-Version einer IPv4-Adresse.

IPv6 IPv4

Wenn Sie Ihren Code mit IPv6 kompatibel machen möchten, müssen Sie nur nach dem ::ffff:Präfix suchen. Wenn es vorhanden ist, entfernen Sie es und verarbeiten Sie den Rest als IPv4. Wenn ::ffff:es nicht vorhanden ist, handelt es sich um eine IPv6-Adresse und muss als solche verarbeitet werden. Sie können überprüfen, ob Punkte in der Zeichenfolge enthalten sind. Wenn ja, handelt es sich um IPv4.

Denken Sie an alles außer an Anpassungen, die Sie an IP-Adressen vornehmen müssen. Sie zeichnen nur die IP auf, oder? Es wird für den Parser und die Protokollaggregate wichtig sein, dies ::ffff:127.0.0.1in Zukunft zu erwarten . Wenn Sie eine IP nicht ändern müssen, lassen Sie sie einfach so, wie Sie sie erhalten.

Nick Steele
quelle
Es klingt jedoch ziemlich gefährlich, nach dem ::ffff:Präfix zu suchen. Sie wissen, ein IPv6 hat viele Notationen.
9онстантин Ван
1
Nein, es ist sicher :) Es gibt den Vorschlag und dann die Implementierung. de.wikipedia.org/wiki/… Die IETF hat erkannt, dass Router nicht so viele Zyklen brennen können, um nach IP-Adressen zu suchen, und auch in freier Wildbahn behält niemand die Nullen, weil dadurch Platz verschwendet wird. Die Idee, die Nullen zuzulassen, war nur eine Idee. Wenn Sie im Jahr 2019 :: ffff: in einem Netzwerkpaket als 0000: 0000: ffff: 0000 gesendet haben, obwohl dies für den ursprünglichen Vorschlag technisch gültig ist, ist es für die aktuelle IETF-Empfehlung ungültig und wird in den meisten IPv6-kompatiblen Routern nicht angezeigt.
Nick Steele
1
So kann ich sicher sein, dass sie immer in kanonischen Formen vorliegen . Ich wusste nicht, wie es in freier Wildbahn lief. Vielen Dank.
10онстантин Ван
Dies ist leider üblich. Menschen achten nur dann, wenn es nötig ist. Jemand entwirft etwas, das ursprüngliche Design unterstützt viele Funktionen, sie erstellen einen RFC, niemand achtet wirklich auf viele Teile des Designs, es wird zum Standard, und wenn implementiert, bemerken die Leute, dass große Änderungen erforderlich sind :) IPv6 ist etwas seltsam weil es ein bisschen komisch ist, es "kanonisch" zu nennen. Sie sollten es wahrscheinlich "1.1" oder so nennen, damit die Leute schnell verstehen können, was los ist. Da Sie jedoch aufgrund der optionalen Nullen des ursprünglichen Entwurfs 10-mal mehr Rechenaufwand in Routern ausgeben, wurde dies einfach ignoriert.
Nick Steele
29

Dies scheint eine Eigenart von IPv6 zu sein: Bei IPv4-Adressen scheint IPv6 die IPv6-Notation mit der IPv4-Notation zu mischen.

Um sowohl IPv4- als auch IPv6-Adressen in der einfachen, nicht gemischten Notation zu erhalten, verwende ich:

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

In Windows 7 ist IPv6 standardmäßig aktiviert. Obwohl mein Server nur IPv4 überwacht, sendet Windows 7 das ::ffff:Präfix im Rahmen des Übergangs zu IPv6 an IPv4

::ffff:0:0:0/96 - Ein Präfix für IPv4-übersetzte Adressen, die vom SIIT-Protokoll (Stateless IP / ICMP Translation) verwendet werden.

Übergang von IPv4

rockerBOO
quelle
8

Ich hatte Probleme beim Versuch, IPv4-zugeordnete Adressen zu vergleichen, und fand die Bibliothek ipaddr.js hilfreich :-)

z.B

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

Versuchen Sie dies, um die genaue IP-Adresse zu erhalten, indem Sie das Subnetz entfernen.

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

Sie können Ihre IP-Adresse allein oder mit der angegebenen Familie über Sockets abrufen

     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
quelle
-2
var ip = req.ip.split(':').pop();
Mateo Marin
quelle
Wie andere Antworten erklären, handelt es sich um eine IPv6-Adresse. Siehe die Antwort von @Nick Steele oben. Das willst du wirklich nicht.
Mischa Nasledov