Express.js req.ip sta restituendo :: ffff: 127.0.0.1


98

Attualmente sto cercando di ottenere l'IP dell'utente richiesto. Il problema è che l'IP sta tornando ::ffff:127.0.0.1invece di 127.0.0.1. Ho provato a utilizzare l' trusted proxyopzione (anche se non utilizzando un proxy) ed req.ipsè vuoto. Utilizzando 4.x Express.js.

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});

Allora cosa stai usando req.ipo req.ips?
Aleksandr M

req.ip, appena provato req.ipscome prova. Non sono sicuro di cosa stia causando il prefisso ::ffff:.
rockerBOO


Sì, era questo. Windows 7 ha un livello di transizione per le richieste IPv4 e aggiunge questo prefisso all'IP.
rockerBOO

Risposte:


156

::ffff:è un prefisso di sottorete per indirizzi IPv4 (32 bit) inseriti in uno spazio IPv6 (128 bit). IPv6 è suddiviso in due parti, il prefisso della sottorete e il suffisso dell'interfaccia. Ciascuno è lungo 64 bit o 4 gruppi di 4 caratteri esadecimali.

In IPv6, è possibile rimuovere gli zeri iniziali e quindi rimuovere gli zeri consecutivi, il che significa che in ::ffff:realtà si traduce in 0000:0000:ffff:0000, questo indirizzo è stato designato come prefisso della sottorete da IPv4 a IPv6, quindi qualsiasi processore IPv6 capirà che sta lavorando con un indirizzo IPv4 e lo gestirà di conseguenza.

Nel prossimo futuro, gli indirizzi IP saranno tutti IPv6, questo perché abbiamo quasi esaurito i numeri (4,2 miliardi, meno un po 'di spazio per scopi vari) nello spazio degli indirizzi IPv4.

IPv6 consente uno spazio molto più ampio. "340 undecillion dovrebbero essere sufficienti per chiunque" - Bill Gates parlando su IPv6.

È importante iniziare a indirizzare gli indirizzi IP utilizzando lo spazio dei nomi IPv6 e quindi includere il ::ffff:nel codice perché in futuro ci saranno dati esadecimali reali tra quei due punti. Se lo rimuovi per motivi estetici, il tuo codice si interromperà quando passa a una rete IPv6 o viene confrontato con un indirizzo IPv6.

Alcune reti attualmente eseguono IPv6 e presto ti troverai di fronte a indirizzi IP IPv6; fai il salto adesso o rischi di rompere il tuo codice in futuro.

La versione TL; DR (breve) della questione è: tutto funziona correttamente. Non cambiarlo, è la versione IPv6 di un indirizzo IPv4.

IPv6 IPv4

Se vuoi rendere il tuo codice compatibile con IPv6, tutto quello che devi fare è controllare il ::ffff:prefisso ... se esiste, rimuoverlo ed elaborare il resto come IPv4 ... se ::ffff:non esiste, è un indirizzo IPv6 e deve essere elaborato come tale. Puoi ricontrollare vedendo se i punti sono nella stringa, in tal caso, è IPv4.

Tieni presente che per tutto tranne le modifiche che devi apportare agli indirizzi IP, stai solo registrando l'IP, giusto? Sarà importante che il parser e gli aggregati di log si aspettino ::ffff:127.0.0.1e cose del genere in futuro. A meno che tu non debba modificare un IP, lascialo come quello che ricevi.


Tuttavia, sembra abbastanza pericoloso controllare il ::ffff:prefisso . Sai, un IPv6 ha molte notazioni.
Константин Ван

1
No, è sicuro :) C'è la proposta e poi c'è l'implementazione. en.wikipedia.org/wiki/… L'IETF ha riconosciuto che i router non possono masterizzare così tanti cicli alla ricerca di indirizzi IP, e anche in natura nessuno mantiene gli zeri perché è spazio sprecato. L'idea di consentire gli zeri era solo un'idea. Nel 2019 se hai inviato :: ffff: in un pacchetto di rete come 0000: 0000: ffff: 0000, sebbene tecnicamente valido per la proposta originale, non è valido per l'attuale raccomandazione IETF e non sarà visto nella maggior parte dei router compatibili con IPv6.
Nick Steele

1
Quindi posso essere sicuro che siano sempre nelle forme canoniche . Non sapevo come andassero le cose in natura. Grazie.
Константин Ван

Questo è comune purtroppo. Gli esseri umani prestano attenzione solo quando necessario. Qualcuno redige qualcosa, il design originale supporta molte funzionalità, crea un RFC, nessuno presta davvero attenzione a molte parti del design, diventa uno standard, quindi quando le persone implementate notano che sono necessari grandi cambiamenti :) IPv6 è un po 'strano perché definirlo "cannonico" è un po 'strano. Probabilmente dovrebbero chiamarlo "1.1" o qualcosa del genere in modo che le persone possano capire rapidamente cosa sta succedendo, ma poiché gli zeri opzionali della bozza originale ti fanno spendere 10 volte più risorse di calcolo nei router, è stato semplicemente ignorato.
Nick Steele

29

Questa sembra essere una stranezza di ipv6: per gli indirizzi ipv4, ipv6 sembra mescolare la notazione ipv6 con la notazione ipv4.

Per ottenere entrambi gli indirizzi ipv4 e ipv6 nella notazione semplice e non miscelata, sto usando:

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


10

Windows 7 ha IPv6 abilitato per impostazione predefinita. Anche se il mio server ascolta solo su IPv4, Windows 7 invia il ::ffff:prefisso a IPv4 come parte della transizione a IPv6

::ffff:0:0:0/96 - Un prefisso utilizzato per gli indirizzi IPv4 tradotti utilizzati dal protocollo SIIT (Stateless IP / ICMP Translation).

Transizione da IPv4


8

Ho avuto problemi con il tentativo di confrontare gli indirizzi mappati ipv4 e ho trovato utile la libreria ipaddr.js :-)

per esempio

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

3

Prova questo per ottenere l'indirizzo IP esatto rimuovendo il subnetting,

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

-2

Puoi ottenere il tuo indirizzo IP da solo o con la famiglia specificata utilizzando i socket

     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]);  
      }

-2
var ip = req.ip.split(':').pop();

Come spiegano altre risposte, questo è un indirizzo IPv6. Vedi la risposta di @Nick Steele sopra. Davvero non vuoi farlo.
Misha Nasledov
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.