Express.js req.ip возвращает :: ffff: 127.0.0.1


99

Я сейчас пытаюсь узнать IP запрошенного пользователя. Проблема в том, что ::ffff:127.0.0.1вместо него возвращается IP 127.0.0.1. Я пробовал использовать trusted proxyопцию (хотя и не через прокси), но поле req.ipsпусто. Использование 4.x Express.js.

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

Так что вы используете req.ipили req.ips?
Александр М

req.ip, просто пробовал req.ipsв качестве теста. Я просто не уверен, что вызывает префикс ::ffff:.
rockerBOO 02


Да вот оно что. Windows 7 имеет переходный уровень для запросов IPv4 и добавляет этот префикс к IP.
rockerBOO 02

Ответы:


157

::ffff:- это префикс подсети для адресов IPv4 (32 бита), которые помещаются внутри пространства IPv6 (128 бит). IPv6 разбит на две части: префикс подсети и суффикс интерфейса. Каждый из них имеет длину 64 бита или 4 группы по 4 шестнадцатеричных символа.

В IPv6 вам разрешено удалить ведущие нули, а затем удалить последовательные нули, что означает, что ::ffff:фактически переводится 0000:0000:ffff:0000, этот адрес был обозначен как префикс подсети IPv4 в IPv6, поэтому любой процессор IPv6 поймет, что он работает с адресом IPv4, и обработает его. соответственно.

В ближайшем будущем все IP-адреса будут IPv6, потому что мы почти исчерпали число (4,2 миллиарда, за вычетом некоторого места для разных целей) в адресном пространстве IPv4.

IPv6 позволяет использовать гораздо больше места. «340 ундециллионов должно хватить любому», - говорит Билл Гейтс о IPv6.

Важно начать адресацию IP-адресов с использованием пространства имен IPv6 и, следовательно, включить ::ffff:в свой код, потому что в будущем между этими двоеточиями будут настоящие шестнадцатеричные данные. Если вы удалите его из эстетических соображений, ваш код сломается, когда он переключится на сеть IPv6 или столкнется с IPv6-адресом.

Некоторые сети в настоящее время используют IPv6, и вскоре вы столкнетесь с IP-адресами IPv6; совершите скачок сейчас или рискуете взломать код в будущем.

TL; DR (краткая) версия вопроса: все работает нормально. Не меняйте его, это версия IPv6 адреса IPv4.

IPv4 IPv6

Если вы хотите сделать свой код совместимым с IPv6, все, что вам нужно сделать, это проверить ::ffff:префикс ... если он существует, удалить его и обработать остаток как IPv4 ... если ::ffff:не существует, это адрес IPv6 и должны обрабатываться как таковые. Вы можете дважды проверить, есть ли в строке точки, если да, то это IPv4.

Помните обо всем, кроме настроек, которые вам нужно внести в IP-адреса, вы просто записываете IP-адрес, верно? Для агрегатов парсера и журналов будет важно ожидать ::ffff:127.0.0.1и тому подобное в будущем. Если вам не нужно изменять IP-адрес, просто оставьте его таким, каким вы его получили.


Однако проверять ::ffff:префикс звучит довольно опасно . Вы знаете, IPv6 имеет много обозначений.
Константин Ван

1
Нет, безопасно :) Есть предложение, а есть реализация. en.wikipedia.org/wiki/… IETF признал, что маршрутизаторы не могут прожигать столько циклов в поисках IP-адресов, а также в дикой природе никто не хранит нули, потому что это тратит впустую пространство. Идея разрешить нули была всего лишь идеей. Если в 2019 году вы отправили :: ffff: в сетевом пакете как 0000: 0000: ffff: 0000, хотя технически он действителен для исходного предложения, он недействителен для текущей рекомендации IETF, а также не будет отображаться в большинстве маршрутизаторов, совместимых с IPv6.
Ник Стил,

1
Так что я могу быть уверен, что они всегда будут в канонической форме. Не знал, как дела в дикой природе. Спасибо.
Константин Ван

К сожалению, это обычное дело. Люди обращают внимание только тогда, когда это необходимо. Кто-то что-то набрасывает, оригинальный дизайн поддерживает множество функций, они делают RFC, никто особо не обращает внимания на многие части дизайна, он становится стандартом, а когда внедряется, люди замечают, что нужны большие изменения :) IPv6 немного странный потому что называть это «каноническим» немного странно. Вероятно, им следовало бы назвать это «1.1» или как-то так, чтобы люди могли быстро понять, что происходит, но поскольку необязательные нули исходного черновика заставляют вас тратить в 10 раз больше вычислительных ресурсов в маршрутизаторах, это просто игнорировалось.
Ник Стил

29

Это похоже на причуду ipv6: для адресов ipv4 ipv6, похоже, смешивает нотацию ipv6 с нотацией ipv4.

Чтобы получить адреса ipv4 и ipv6 в простой, несмешанной нотации, я использую:

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


10

В Windows 7 по умолчанию включен IPv6. Несмотря на то, что мой сервер прослушивает только IPv4, Windows 7 отправляет ::ffff:префикс IPv4 как часть перехода на IPv6.

::ffff:0:0:0/96 - Префикс, используемый для адресов с преобразованием IPv4, которые используются протоколом трансляции IP / ICMP без сохранения состояния (SIIT).

Переход с IPv4


8

У меня возникли проблемы с попыткой сравнить сопоставленные адреса ipv4, и я нашел библиотеку ipaddr.js полезной :-)

например

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


-2

Вы можете получить свой IP-адрес самостоятельно или с указанной семьей, используя сокеты

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.