Как определить IP-адрес пользователя в узле


349

Как я могу определить IP-адрес данного запроса из контроллера? Например (в экспрессе):

app.post('/get/ip/address', function (req, res) {
    // need access to IP address here
})

22
Если вы используете Express, вы можете использовать req.ip source - expressjs.com/en/api.html#req.ip
FrickeFresh


16
Для тех, кто работает из localhost- как я сделал, может прийти результат для всех ответов ниже (почти все ответы работают) ::1. Это запутало меня на некоторое время. Позже выяснилось, что ::1это настоящий IP-адрес и это IPV6нотация для localhost. Hope this helps someone
Прамеш Баджрачарья

Ответы:


452

В вашем requestобъекте есть свойство с именем connection, которое является net.Socketобъектом. Объект net.Socket имеет свойство remoteAddress, поэтому вы сможете получить IP с помощью этого вызова:

request.connection.remoteAddress

Смотрите документацию по http и net

РЕДАКТИРОВАТЬ

Как указывает @juand в комментариях, правильный способ получения удаленного IP-адреса, если сервер находится за прокси-сервером, - это request.headers['x-forwarded-for']


6
Это дает мне IP-адрес, отличный от того, что дает мне whatismyip.com. С чего бы это?
Shamoon

3
У меня установлена ​​служба API на экземпляре no.de. Когда я пытаюсь получить к нему доступ со своего компьютера, я получаю IP-адрес «10.2.XXX.YYY», тогда как мой реальный IP-адрес - «67.250.AAA.BBB»
Shamoon

7
это request.headers ['X-Forwarded-For']
0x6A75616E

4
Обратите внимание, что net.Stream теперь является net.Socket, и документация находится здесь: nodejs.org/api/net.html#net_class_net_socket
monsur

4
Для тех, кому интересно, для Heroku это: request.headers['x-forwarded-for']
FueledPublishing

408
var ip = req.headers['x-forwarded-for'] || 
     req.connection.remoteAddress || 
     req.socket.remoteAddress ||
     (req.connection.socket ? req.connection.socket.remoteAddress : null);

Обратите внимание, что иногда вы можете получить более одного IP-адреса req.headers['x-forwarded-for']. Кроме того, x-forwarded-forзаголовок не всегда будет установлен, что может привести к ошибке.

Общий формат поля:

х-пересылаются-за: client, proxy1, proxy2, proxy3

где значение представляет собой список IP-адресов, разделенных запятыми + пробелами, крайний левый - исходный клиент, и каждый последующий прокси-сервер, прошедший запрос, добавляет IP-адрес, с которого он получил запрос. В этом примере, запрос проходит через proxy1, proxy2и затем proxy3. proxy3отображается как удаленный адрес запроса.

Это решение, предложенное Арнавом Гуптой с исправлением, предложенным Мартином ниже в комментариях для случаев, когда x-forwarded-forоно не установлено:

var ip = (req.headers['x-forwarded-for'] || '').split(',').pop().trim() || 
         req.connection.remoteAddress || 
         req.socket.remoteAddress || 
         req.connection.socket.remoteAddress

9
Как предотвратить подделку этих заголовков?
Доми

8
Обычно это работает хорошо, но по какой-то причине я недавно получил ошибку «Невозможно прочитать свойство 'remoteAddress' undefined", потому что, по-видимому, все было нулевым / неопределенным, в том числе req.connection.socket. Я не уверен, почему / при каких условиях это так, но было бы хорошо проверить, что req.connection.socketсуществует, чтобы избежать сбоя вашего сервера, если это произойдет.
Мэтт Браун

9
Последняя строка req.connection.socket.remoteAddress сгенерировала ошибку. Будь осторожен.
Январь 18.12.14

11
Возвращенный IP-адрес: :: 1. Почему?
Bagusflyer

3
Глядя на то, как работает pop (), кажется, что вы получите последний прокси, а не клиент, который вам нужен. Я ошибаюсь?
Мишель


31

Вы можете оставаться СУХИМ и просто использовать node-ipware, который поддерживает IPv4 и IPv6 .

Установка:

npm install ipware

В вашем app.js или промежуточном программном обеспечении:

var getIP = require('ipware')().get_ip;
app.use(function(req, res, next) {
    var ipInfo = getIP(req);
    console.log(ipInfo);
    // { clientIp: '127.0.0.1', clientIpRoutable: false }
    next();
});

Он сделает лучшую попытку получить IP-адрес пользователя или возврат, 127.0.0.1чтобы указать, что он не может определить IP-адрес пользователя. Посмотрите на файл README для расширенных опций.


40
"или возвращает 127.0.0.1, чтобы указать, что он не может определить IP-адрес пользователя" Существует довольно большая разница между 127.0.0.1 и неизвестным ...
Nepoxx

4
Это показало мне что-то странное :ffff:(not my IP address)при тестировании от Heroku. Ответ @ edmar-miyake работает правильно для меня.
Ниллок

Интересно, каким был бы IP, если бы вы использовали поиск right2left в случае «x-forwarded-for». var ip_info = get_ip (req, right_most_proxy = True), как в некоторых настройках, IP-адрес клиента может быть самым правильным IP-адресом.
un33k

2
Этот метод возвращается clientIp: '::1'для меня. Это не похоже на работу.
JamEngulfer

@JamEngulfer - ipware работает только в том случае, если IP-адрес правильно передан в ваше приложение через request.headers []. пример: AWS LBS отправляет IP-адрес в «x-forwarded-for», в то время как пользовательский NginX часто использует другие переменные. ipware делает лучшую попытку выяснить IP-адрес, но только если IP-адрес был передан в заголовках.
un33k

19

Вы можете использовать request-ip , чтобы получить IP-адрес пользователя. Он обрабатывает довольно много различных крайних случаев, некоторые из которых упомянуты в других ответах.

Раскрытие: я создал этот модуль

Установка:

npm install request-ip

В вашем приложении:

var requestIp = require('request-ip');

// inside middleware handler
var ipMiddleware = function(req, res, next) {
    var clientIp = requestIp.getClientIp(req); // on localhost > 127.0.0.1
    next();
};

Надеюсь это поможет


2
проверяя исходный код пакета request-ip по адресу github.com/pbojinov/request-ip/blob/master/index.js, он проверяет x-forwarded-for и все виды других заголовков для популярных балансировщиков нагрузки, таких как AWS ELB, Cloudflare , Akamai, nginx, Rackspace LB и Stingray от Riverbed
Джорджио

1
это возвращается nullдля меня.
S.M_Emamian

То же самое вместо использованияrequest.headers['x-forwarded-for']
Prathamesh Подробнее

19

request.headers['x-forwarded-for'] || request.connection.remoteAddress

Если x-forwarded-forесть заголовок, используйте его, в противном случае используйте.remoteAddress свойство.

x-forwarded-forДобавляются заголовок запросов, проходящих через балансировку нагрузки (или другие тип прокси) , созданную для HTTP или HTTPS (это также можно добавить этот заголовок на запросы при балансировке на TCP уровне с использованием прокси - протокола ). Это связано с тем, что request.connection.remoteAddressсвойство будет содержать частный IP-адрес балансировщика нагрузки, а не публичный IP-адрес клиента. Используя оператор OR в указанном выше порядке, вы проверяете наличие x-forwarded-forзаголовка и используете его, если он существует, в противном случае используйте request.connection.remoteAddress.


12

Следующая функция имеет все случаи поможет

var ip;
if (req.headers['x-forwarded-for']) {
    ip = req.headers['x-forwarded-for'].split(",")[0];
} else if (req.connection && req.connection.remoteAddress) {
    ip = req.connection.remoteAddress;
} else {
    ip = req.ip;
}console.log("client IP is *********************" + ip);

Обратите внимание на то, что у ips есть , промежуток для меня.
ThomasReggi

8

Есть два способа получить IP-адрес:

  1. let ip = req.ip

  2. let ip = req.connection.remoteAddress;

Но есть проблема с вышеуказанными подходами.

Если вы запускаете свое приложение за Nginx или любым прокси, каждый IP-адрес будет 127.0.0.1 .

Итак, лучшее решение для получения IP-адреса пользователя:

let ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

6

Если вы используете экспресс-версию 3.x или выше, вы можете использовать параметр доверенного прокси ( http://expressjs.com/api.html#trust.proxy.options.table ), и он будет проходить цепочку адресов в заголовок x-forwarded-for и поместите последний ip в цепочку, которую вы не настроили как доверенный прокси, в свойство ip объекта req.


6

function getCallerIP(request) {
    var ip = request.headers['x-forwarded-for'] ||
        request.connection.remoteAddress ||
        request.socket.remoteAddress ||
        request.connection.socket.remoteAddress;
    ip = ip.split(',')[0];
    ip = ip.split(':').slice(-1); //in case the ip returned in a format: "::ffff:146.xxx.xxx.xxx"
    return ip;
}


1
Вы правы, если вы хотите, чтобы ip был строкой, тогда вы можете заменить последнюю строку на: ip = ip.split (':'). Slice (-1) [0]
Ахмад Агбарья

Ответы только на код не приветствуются. Можете ли вы объяснить, как этот ответ лучше, чем более старый, лучше объясненный и (гораздо) более отнятый ответ ?
Дан Дакалеску

5

Предупреждение:

Не просто слепо используйте это для важного ограничения скорости:

let ip = request.headers['x-forwarded-for'].split(',')[0];

Это очень легко подделать:

curl --header "X-Forwarded-For: 1.2.3.4" "https://example.com"

В этом случае реальный IP-адрес пользователя будет:

let ip = request.headers['x-forwarded-for'].split(',')[1];

Я удивлен, что никакие другие ответы не упомянули это.


Верхний ответ делает обрабатывать это, pop()ИНГ из массива, который является более общим , чем получить элемент с индексом 1, который можно обмануть с помощью curl --header "X-Forwarded-For: 1.2.3.4, 5.6.7.8" "https://example.com".
Дан Дакалеску

3

Если вы получаете несколько IP-адресов, это работает для меня:

var ipaddress = (req.headers['x-forwarded-for'] || 
req.connection.remoteAddress || 
req.socket.remoteAddress || 
req.connection.socket.remoteAddress).split(",")[0];


3

Простой получить удаленный IP-адрес в nodejs:

var ip = req.header('x-forwarded-for') || req.connection.remoteAddress;

3

В узле 10.14 за nginx вы можете получить ip, запросив его через заголовок nginx, например:

proxy_set_header X-Real-IP $remote_addr;

Тогда в вашем app.js:

app.set('trust proxy', true);

После этого везде, где вы хотите, чтобы оно появилось:

var userIp = req.header('X-Real-IP') || req.connection.remoteAddress;

2

Я понимаю, что на это ответили до смерти, но вот современная версия ES6, которую я написал, которая соответствует стандартам eslint на базе airbnb.

const getIpAddressFromRequest = (request) => {
  let ipAddr = request.connection.remoteAddress;

  if (request.headers && request.headers['x-forwarded-for']) {
    [ipAddr] = request.headers['x-forwarded-for'].split(',');
  }

  return ipAddr;
};

Заголовок X-Forwarded-For может содержать разделенный запятыми список IP-адресов прокси. Заказ является клиентом, proxy1, proxy2, ..., proxyN. В реальном мире люди внедряют прокси, которые могут предоставлять все, что они хотят в этом заголовке. Если вы находитесь за балансировщиком нагрузки или чем-то еще, вы можете, по крайней мере, доверять первому IP-адресу в списке, по крайней мере, любому прокси-серверу, через который прошел какой-либо запрос.


1

Если вы используете Graphql-Yoga, вы можете использовать следующую функцию:

const getRequestIpAddress = (request) => {
    const requestIpAddress = request.request.headers['X-Forwarded-For'] || request.request.connection.remoteAddress
    if (!requestIpAddress) return null

    const ipv4 = new RegExp("(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")

    const [ipAddress] = requestIpAddress.match(ipv4)

    return ipAddress
}



-7

Была та же проблема ... Я также новичок в JavaScript, но я решил это с req.connection.remoteAddress; это дало мне IP-адрес (но в формате ipv6 :: ffff.192.168.0.101) и затем .slice, чтобы удалить 7 первых цифр.

var ip = req.connection.remoteAddress;

if (ip.length < 15) 
{   
   ip = ip;
}
else
{
   var nyIP = ip.slice(7);
   ip = nyIP;
}

это не очень хороший метод, поскольку ipv6 - это НЕ просто 7 цифр + IPv4, но может быть совершенно другим.
Радек

@Radek, если вы проверяете начало адреса, он соответствует спецификации (см. En.wikipedia.org/wiki/IPv6_address ctrl-f для поиска «IPv4-mapped») ip= (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined))заменит if ... в приведенном выше коде
несинхронизированный

я лично обертываю getClientIp () из npm request-ip, чтобы создать, function getClientIp4(req){ var ip=typeof req==='string'?req:getClientIp(req); return (ip.length<15?ip:(ip.substr(0,7)==='::ffff:'?ip.substr(7):undefined)); }который принимает либо ранее извлеченный ip, либо объект запроса в качестве входных данных и дает в результате ip или неопределенный
несинхронизированный
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.