IP-трассировка в основном используется для получения реального IP-адреса запроса. Поскольку существующий сервис основан на Nginx для достижения балансировки нагрузки, получить реальный IP-адрес запроса сложно. В существующей реализации Matrix прослеживаемость IPgetIp
Функция завершена, и ее конкретный код выглядит следующим образом.
/**
* 获得请求发送方的 ip
* @param {Context} ctx
* @return {string}
*/
export function getIp(ctx) {
const xRealIp = ctx.get('X-Real-Ip');
const { ip } = ctx;
const { remoteAddress } = ctx.req.connection;
return xRealIp || ip || remoteAddress;
}
Прежде чем обсуждать код более подробно, нам нужно проанализировать несколько общихПолучить IP-источник запросаПуть:
req.socket.remoteAddress
X-Forwarded-For
X-Real-IP
req.socket.remoteAddress
В официальной документации Node.jsnet_socket_remoteaddress, мы знаем, что можно пройтиreq.socket.remtoeAddress
Получите информацию об исходном IP-адресе подключения к сокету.
socket.remoteAddress
Added in: v0.5.10
- String
The string representation of the remote IP address. For example,
'74.125.127.100'
or'2001:4860:a005::68'
. Value may beundefined
if the socket is destroyed (for example, if the client disconnected).
Согласно официальной документацииhttp_request_socketописание,req.connection
иreq.socket
эквивалентно, мы также можем передатьreq.connection.remoteAddress
Получите информацию об исходном IP-адресе соединения сокета. Этот способ получения IP-источника запроса подходит дляПрямое подключение клиента к серверуместо действия.
Однако, поскольку существующий сервис Matrix использует Nginx для балансировки нагрузки сервисного кластера,req.socket.connection
Получается IP-адрес Nginx, а не реальный IP-адрес запроса.
X-Forwarded-For
в соответствии сRFC 7239спецификация, прокси-серверы HTTP (такие как Nginx, Apache и т. д.) будут переписывать заголовок HTTP-запроса, добавляяX-Forwarded-For
Поле, используемое для отслеживания источника запроса, формат этого поля следующий:
X-Forwarded-For: client, proxy1, proxy2
следующая параX-Forwarded-For
Подробно объясняется процесс обработки поля:
- Когда клиент (например, браузер) отправляет HTTP-запрос, по умолчанию
X-Forwarded-For
поле. - Когда запрос достигает первого прокси-сервера HTTP, прокси-сервер добавляет к заголовку запроса в соответствии со спецификацией RFC 7239.
X-Forwared-For
поле и установите значениеIP-адрес клиента. - Если позади несколько HTTP-прокси (то есть запрос будет обрабатываться несколькими HTTP-прокси по очереди), каждый прокси будет
X-Forwarded-For
в значении поляДобавить IP-адрес предыдущего прокси. - На бизнес-сервере мы можем передать
X-Forwarded-For
стоило тогоКрайний левый IP-адресПолучить IP-адрес клиента.
Но, к сожалению,X-Forwarded-For
даподлог: если клиент устанавливает поддельный HTTP-запрос при выполнении HTTP-запросаX-Forwarded-For
поле, из-заПоследующие уровни прокси будут только добавлять это поле, а не перезаписывать его., поэтому IP-адрес клиента, окончательно полученный сервером службы, может быть поддельным адресом клиента.
Обычно нам нужно сделать дополнительную настройку, чтобы сделать поддержку NginxX-Forwarded-For
.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
X-Real-IP
HTTP-прокси-сервер можно указать в заголовке запроса.X-Real-IP
запрашивать исходную информацию, ноЭтого нет в спецификации RFC..
X-Real-IP
даКлиент не может быть подделанДа, ноМогу только описать реальный IP ближайшего прокси, если есть несколько уровней прокси, он по-прежнему недоступен, поскольку реальный IP-адрес запрошен клиентом. в реальной жизни,Многослойные агенты на самом деле относительно редки, а однослойные агенты распространены., поэтому в обычном случае используйтеX-Real-IP
достаточно для выполнения задачи, а относительноX-Forwarded-For
Там безопасность лучше.
Мы можем сделать поддержку Nginx следующими настройкамиX-Real-IP
Автоматическая настройка полей.
proxy_set_header X-Real-IP $remote_addr;
Сравнение нескольких способов
Ниже приводится мое резюме нескольких способов получения реального IP-адреса клиента, а также анализируются ограничения и сценарии применения каждого метода.
req.socket.remoteAddress | X-Forwarded-For | X-Real-IP | |
---|---|---|---|
Можно ли подделать | нет | да | нет |
срок действия | Только когда клиент напрямую подключается к серверу | только если не подделка | только если клиент не многоуровневый проксируется |