Научно-популярная статья: Как веб-служба Node.js получает реальный IP-адрес пользователя?

Node.js

## задний план

Это кажется очевидным вопросом.

В Node.js каждое TCP-соединение имеетremoteAddressсвойство, через которое запрошенный IP-адрес может быть получен напрямую. И в HTTP-запросе мы можем передатьrequest.socket.remoteAddressдоступ к этому свойству.

Но все действительно так просто?

Вообще говоря, наши службы приложений не будут напрямую получать внешние запросы, а будут развертывать службы за уровнем доступа, чтобы обеспечить балансировку нагрузки нескольких машин и плавный выпуск служб для обеспечения высокой доступности. Например, обратный прокси-сервер Alibaba Cloud SLB или Nginx.

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


## Регулярное решение

Наиболее распространенная архитектура веб-сервисов


X-Forwarded-Forзаголовок запроса.

X-Forwarded-For

X-Forwarded-For: client, proxy1, proxy2

Проблема кажется идеальным решением.


## Это действительно решено?

Но всегда есть «умные» пользователи, у которых возникает озарение, когда они сталкиваются с ограничениями IP на сервисе: если мы добавим его прямо в запросX-Forwarded-ForЗаголовок запроса, не должен ли запрашиваться IP-маскарад?

curl -H 'X-Forwarded-For: 1.2.3.4' http://iplimit.resource.com/api/resources

согласно сX-Forwarded-ForКак это работает, первый обратный прокси-сервер, который его получит, будет думать, что исходный адрес запроса1.2.3.4, затем добавьте реальный IP-адрес пользователя в качестве «первого прокси» вX-Forwarded-For, окончательный результат на прикладном уровне будет таким:

X-Forwarded-For: 1.2.3.4, client, proxy1, proxy2



## решение

Чтобы избежать получения поддельных IP-адресов пользователей, мы можем сделать еще один шаг и определить, сколько обратных прокси-сервисов у нас есть в нашей архитектуре развертывания, чтобы мы моглиX-Forwarded-ForПри запросе получения реального IP-заголовка пользователь должен отфильтровать фиктивный IP-адрес.

// 伪代码
// [ illegalIp, clientRealIp, proxyIp1, proxyIp2 ...]
const val = ctx.get('X-Forwarded-For');
let ips = val ? val.split(/\s*,\s*/) : [];
ips = ips.slice(-(maxProxyCount + 1));


Глупо получилось, не правда ли? Но решения по обеспечению безопасности часто настолько грязны и преследуют практические цели.

В то же время, как среда Node.js корпоративного уровня,Egg.jsПрямой встроенный предоставляет соответствующее решение.

Просто простая конфигурация:

// config/config.default.js
config.proxy = true;
config.maxProxyCount = 1;

Разработчики приложений могут получить правильную информацию без восприятия:

ctx.ip       // 获取用户的 IP 地址
ctx.host     // 获取用户请求的域名
ctx.protocol // 获取用户请求的协议


Для подробного плана заинтересованные студенты могут расширить, чтобы прочитать следующееДокументация

X-Forwarded-ForМожет это?

proxy_set_header X-Forwarded-For $remote_addr;

  • Не все уровни унифицированного доступа контролируются пользователями.Например, в коммерческих службах балансировки нагрузки, таких как Alibaba Cloud SLB, вы не сможете настроить эти требования.
  • Платформа предпочитает использовать стандартное (де-факто стандартное) решение для конвергенции функций.Поскольку унифицированный доступ верхнего уровня соответствует стандарту, инфраструктура может быть напрямую подключена и настроена единообразно, не требуя от пользователей реализации различных реализаций в соответствии с различными слои доступа.
  • Два не конфликтуют, фреймворк полностью реализован, по умолчанию хороший.

## Об этой статье

Эта программа происходит отязык птицаРеальный случай атаки и защиты от инженеров@мертвая лошадь.

Оригинальный адрес:https://www.yuque.com/egg/nodejs/coopsc

Yuque, ваша эксклюзивная база знаний — «инструмент для создания и обмена знаниями», созданный на основе технологии опыта Ant Financial.