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

104

Obecnie próbuję uzyskać adres IP żądanego użytkownika. Problem polega na tym, że adres IP wraca ::ffff:127.0.0.1zamiast 127.0.0.1. Próbowałem użyć trusted proxyopcji (ale nie używam proxy) i req.ipsjest puste. Korzystanie z 4.x Express.js.

router.get('/', function(req, res, next) {
    console.log('ip', req.ip)
    res.send({})
});
rockerBOO
źródło
Więc czego używasz req.iplub req.ips?
Aleksandr M
req.ip, po prostu próbowałem req.ipsjako test. Po prostu nie jestem pewien, co powoduje prefiks ::ffff:.
rockerBOO
Tak, to było to. System Windows 7 ma warstwę przejściową dla żądań IPv4 i dodaje ten prefiks do adresu IP.
rockerBOO

Odpowiedzi:

161

::ffff:jest prefiksem podsieci dla adresów IPv4 (32-bitowych) umieszczonych w przestrzeni IPv6 (128-bitowej). IPv6 jest podzielony na dwie części: prefiks podsieci i sufiks interfejsu. Każdy z nich ma 64 bity lub 4 grupy po 4 znaki szesnastkowe.

W IPv6 możesz usunąć wiodące zera, a następnie usunąć kolejne zera, co oznacza, że ​​w ::ffff:rzeczywistości oznacza to 0000:0000:ffff:0000, że ten adres został wyznaczony jako prefiks podsieci IPv4 do IPv6, więc każdy procesor IPv6 zrozumie, że działa z adresem IPv4 i obsłuży go odpowiednio.

W najbliższej przyszłości wszystkie adresy IP będą w formacie IPv6, ponieważ w przestrzeni adresowej IPv4 prawie zabrakło (4,2 miliarda, minus trochę miejsca na różne cele).

IPv6 pozwala na znacznie większą przestrzeń. „340 undecillionów powinno wystarczyć każdemu” - mówi Bill Gates o IPv6.

Ważne jest, aby rozpocząć adresowanie adresów IP przy użyciu przestrzeni nazw IPv6, a zatem uwzględnić ::ffff:w kodzie znak, ponieważ w przyszłości między tymi dwukropkami będą znajdować się prawdziwe dane szesnastkowe. Jeśli zdejmiesz go ze względów estetycznych, kod zepsuje się, gdy przełączy się na sieć IPv6 lub zostanie skonfrontowany z adresem IPv6.

W niektórych sieciach obecnie działa protokół IPv6 i wkrótce będziesz miał do czynienia z adresami IPv6; zrób krok teraz lub zaryzykuj złamanie kodu w przyszłości.

TL; DR (krótka) wersja sprawy brzmi: Wszystko działa dobrze. Nie zmieniaj tego, to wersja IPv6 adresu IPv4.

IPv4 IPv6

Jeśli chcesz, aby Twój kod był zgodny z IPv6, wszystko, co musisz zrobić, to sprawdzić ::ffff:prefiks ... jeśli istnieje, usunąć go i przetworzyć pozostałą część jako IPv4 ... jeśli ::ffff:nie istnieje, jest to adres IPv6 i muszą być przetwarzane jako takie. Możesz sprawdzić dwukrotnie, sprawdzając, czy w ciągu znaków znajdują się kropki, jeśli tak, to jest to IPv4.

Miej na uwadze wszystko oprócz zmian, które musisz wprowadzić w adresach IP, po prostu rejestrujesz adres IP, prawda? Będzie to ważne dla parsera i agregatów logów, których można się spodziewać ::ffff:127.0.0.1i takich w przyszłości. O ile nie musisz zmieniać adresu IP, po prostu zostaw je tak, jak otrzymujesz.

Nick Steele
źródło
Jednak sprawdzenie ::ffff:przedrostka wydaje się dość niebezpieczne . Wiesz, IPv6 ma wiele notacji.
Константин Ван
1
Nie, to bezpieczne :) Jest propozycja, a potem realizacja. en.wikipedia.org/wiki/… IETF uznał, że routery nie mogą spalić tylu cykli w poszukiwaniu adresów IP, a także w środowisku naturalnym nikt nie zachowuje zer, ponieważ jest to marnowane miejsce. Pomysł, by dopuścić zera, był tylko pomysłem. W 2019 r., Jeśli wysłałeś :: ffff: w pakiecie sieciowym jako 0000: 0000: ffff: 0000, chociaż technicznie poprawne dla pierwotnej propozycji, jest nieważne dla aktualnego zalecenia IETF i nie będzie widoczne w większości routerów kompatybilnych z IPv6.
Nick Steele
1
Mogę więc być pewien, że zawsze będą w formie kanonicznej . Nie wiedziałem, jak się sprawy mają na wolności. Dzięki.
Константин Ван
1
Niestety jest to powszechne. Ludzie zwracają uwagę tylko wtedy, gdy jest to konieczne. Ktoś coś szkicuje, oryginalny projekt obsługuje wiele funkcji, tworzy RFC, tak naprawdę nikt nie zwraca uwagi na wiele części projektu, staje się to standardem, a po wdrożeniu ludzie zauważają, że potrzebne są duże zmiany :) IPv6 jest trochę dziwne ponieważ nazywanie go „kanonicznym” jest trochę dziwne. Powinni prawdopodobnie nazwać to „1.1” lub jakoś tak, aby ludzie mogli szybko zrozumieć, co się dzieje, ale ponieważ opcjonalne zera oryginalnej wersji roboczej powodują, że spędzasz 10 razy więcej mocy obliczeniowej na routerach, zostało to po prostu zignorowane.
Nick Steele,
29

Wydaje się, że jest to dziwactwo ipv6: dla adresów ipv4, ipv6 wydaje się mieszać notację ipv6 z notacją ipv4.

Aby uzyskać adresy IPv4 i ipv6 w prostej, niezmieszanej notacji, używam:

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

Windows 7 ma domyślnie włączony protokół IPv6. Mimo że mój serwer nasłuchuje tylko na IPv4, Windows 7 wysyła ::ffff:prefiks do IPv4 w ramach przejścia na IPv6

::ffff:0:0:0/96 - Prefiks używany dla adresów przetłumaczonych na IPv4, które są używane przez protokół translacji bezstanowej IP / ICMP (SIIT).

Przejście z IPv4

rockerBOO
źródło
8

Miałem problemy z próbą porównania mapowanych adresów IPv4 i okazało się, że biblioteka ipaddr.js jest pomocna :-)

na przykład

_.isEqual(ipaddr.process('::ffff:127.0.0.1'), ipaddr.process('127.0.0.1')) === true
Bryce
źródło
4

Spróbuj tego, aby uzyskać dokładny adres IP, usuwając podsieci,

    let ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
    ip = ip.toString().replace('::ffff:', '');
MAREESKANNNAN RAJENDRAN
źródło
-2

Możesz uzyskać swój adres IP samodzielnie lub z określoną rodziną za pomocą gniazd

     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
źródło
-2
var ip = req.ip.split(':').pop();
Mateo Marin
źródło
Jak wyjaśniają inne odpowiedzi, jest to adres IPv6. Zobacz odpowiedź @Nick Steele powyżej. Naprawdę nie chcesz tego robić.
Misha Nasledov