Як визначити IP-адресу користувача у вузлі


350

Як я можу визначити IP-адресу даного запиту від контролера? Наприклад (у експресі):

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

23
Якщо ви використовуєте Express, ви можете використовувати req.ip джерело - expressjs.com/en/api.html#req.ip
FrickeFresh

Спробуйте це: github.com/indutny/node-ip
Stephen Last

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

EDIT

Як в коментарях зазначає @juand, правильним методом отримання віддаленого IP-адреси, якщо сервер стоїть за проксі-сервером, є request.headers['x-forwarded-for']


6
Це дає мені IP-адресу, відмінну від того, що мені дає whatismyip.com. Чому це було б?
Шамун

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

7
it 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не завжди буде встановлений заголовок, який може призвести до помилки.

Загальний формат поля:

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. Будьте обережні.
yAnTar

11
Повернута ip-адреса: 1. Чому?
Bagusflyer

3
Дивлячись на те, як працює pop (), вам здається, що ви збираєтеся отримати останній проксі, а не клієнт, якого саме ви хочете. Я помиляюся?
Мішель


31

Ви можете залишатися DRY та просто використовувати 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 відповідь справно працює для мене.
Nilloc

Цікаво, який би був 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 More

19

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

Якщо x-forwarded-forзаголовок є, то використовуйте це, інакше використовуйте.remoteAddress властивість.

x-forwarded-forДодаються заголовок запитів, що проходять через балансування навантаження (або інші тип проксі) , створену для HTTP або HTTPS (це також можна додати цей заголовок на запити при балансуванні на TCP рівні з використанням проксі - протоколу ). Це тому, що request.connection.remoteAddressвластивість буде містити приватну IP-адресу балансира навантаження, а не публічну IP-адресу клієнта. Використовуючи оператор АБО , у наведеному вище порядку ви перевіряєте наявність 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]
Ahmad Agbaryah

Відповіді, що стосуються лише коду, не враховують. Чи можете ви пояснити, наскільки ця відповідь краща за старіші, краще пояснені та (набагато) більш відповідні відповіді ?
Дан Даскалеску

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-base.

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-відображених") 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.