Протокол PROXY дозволяє проксі-серверу або балансувальнику навантаження передавати інформацію про з'єднання оригінального клієнта, включаючи його реальну IP-адресу та порт, до бекенд-сервера, додаючи невеликий, стандартизований заголовок на початку TCP-з'єднання.
Чому PROXY Protocol? Проблема, яку він вирішує
Стандартні TCP-проксі працюють шляхом встановлення нового з'єднання з бекенд-сервером від імені клієнта. З точки зору бекенд-сервера, з'єднання походить від IP-адреси проксі-сервера, а не від оригінального клієнта. Така поведінка приховує справжню ідентичність клієнта, створюючи кілька проблем:
- Логування: Журнали доступу сервера записують IP-адресу проксі-сервера, що унеможливлює відстеження запитів до окремих клієнтів.
- Безпека: Брандмауери веб-додатків (WAF), обмежувачі швидкості (rate limiters) та списки контролю доступу (ACL) на бекенд-серверах не можуть точно ідентифікувати та блокувати зловмисних клієнтів на основі їхніх реальних IP-адрес.
- Аналітика: Системи геотаргетингу, персоналізованої доставки контенту та виявлення зловживань втрачають критичні дані про місцезнаходження клієнта та його поведінку.
- Відлагодження: Усунення несправностей мережі або специфічної поведінки клієнтів стає значно складнішим без видимості оригінального джерела клієнта.
Протокол PROXY вирішує цю проблему, надаючи механізм для проксі-сервера, щоб передавати деталі з'єднання клієнта (вихідний IP, вихідний порт, цільовий IP, цільовий порт) через проксі-рівень, дозволяючи бекенд-серверу правильно ідентифікувати оригінального клієнта.
Як працює PROXY Protocol
Протокол PROXY працює на транспортному рівні (Рівень 4) моделі OSI. Коли проксі-сервер або балансувальник навантаження, що підтримує протокол PROXY, отримує з'єднання від клієнта, він встановлює нове з'єднання з бекенд-сервером. Перед відправленням будь-яких даних прикладного рівня (наприклад, HTTP-запитів, запитів до бази даних), проксі-сервер спочатку надсилає заголовок PROXY Protocol. Цей заголовок містить інформацію про з'єднання клієнта.
Для коректної роботи протоколу PROXY необхідно виконати дві умови:
1. Проксі-сервер або балансувальник навантаження має бути налаштований на відправлення заголовка PROXY Protocol.
2. Бекенд-сервер має бути налаштований на отримання та розбір заголовка PROXY Protocol перед обробкою будь-яких даних прикладного рівня. Якщо бекенд-сервер не розуміє заголовок, він інтерпретуватиме його як некоректні дані програми, що призведе до помилок з'єднання.
Версії PROXY Protocol
Існують дві основні версії протоколу PROXY: v1 та v2.
Версія 1 (v1)
PROXY Protocol v1 — це текстовий формат на основі ASCII, зручний для читання людиною. Він підтримує IPv4 та IPv6 через TCP.
Формат:
PROXY <INET_PROTOCOL> <CLIENT_IP> <PROXY_IP> <CLIENT_PORT> <PROXY_PORT>\r\n
<INET_PROTOCOL>:TCP4для IPv4 абоTCP6для IPv6.<CLIENT_IP>: IP-адреса оригінального клієнта.<PROXY_IP>: IP-адреса проксі-сервера (IP, який бекенд бачить як джерело з'єднання).<CLIENT_PORT>: Вихідний порт оригінального клієнта.<PROXY_PORT>: Цільовий порт на проксі-сервері, до якого підключився клієнт.
Приклад (IPv4):
PROXY TCP4 192.168.1.1 10.0.0.1 52345 80\r\n
Цей заголовок вказує на TCPv4-з'єднання від клієнта 192.168.1.1:52345 до проксі-сервера, який потім підключився до бекенду на 10.0.0.1:80.
Обмеження v1:
* Обмежено TCP-з'єднаннями.
* Накладні витрати ASCII можуть бути дещо менш ефективними.
* Не підтримує додаткові метадані.
Версія 2 (v2)
PROXY Protocol v2 — це бінарний формат, розроблений для ефективності та розширюваності. Він підтримує IPv4, IPv6 та UNIX-сокети через TCP та UDP, а також включає механізм полів Type-Length-Value (TLV) для передачі додаткових метаданих з'єднання.
Переваги v2:
* Ефективність: Бінарний формат зменшує розмір заголовка.
* Ширша підтримка протоколів: Підтримує TCP, UDP та UNIX-сокети.
* Підтримка IPv6: Повністю інтегрує IPv6.
* Розширюваність (TLV): Дозволяє передавати довільні метадані, такі як інформація про SSL-з'єднання, унікальні ідентифікатори з'єднань або інші дані, специфічні для програми.
Огляд структури (спрощено):
Заголовок v2 починається з 13-байтової сигнатури, за якою слідує 1-байтове поле версії/команди, 1-байтове поле протоколу, 2-байтове поле довжини адреси, а потім змінна довжина інформації про адресу та необов'язкові поля TLV.
Хоча сирий бінарний формат є складним, ключовим є його здатність ефективно передавати більше інформації та через ширший спектр протоколів.
PROXY Protocol проти X-Forwarded-For (XFF)
Як PROXY Protocol, так і HTTP-заголовок X-Forwarded-For (XFF) мають на меті передавати інформацію про IP-адресу клієнта через проксі-сервер. Однак вони працюють на різних рівнях і мають відмінні характеристики.
| Функція | PROXY Protocol | Заголовок X-Forwarded-For (XFF) |
|---|---|---|
| Рівень роботи | Транспортний рівень (L4) | Прикладний рівень (L7 - зокрема HTTP) |
| Область протоколу | Будь-який протокол на основі TCP/UDP (HTTP, FTP, SSH, SMTP тощо) | Лише HTTP/HTTPS |
| Механізм | Доданий заголовок до сирого потоку TCP/UDP | Заголовок HTTP-запиту |
| Контроль клієнта | Не може бути підроблений зловмисним клієнтом після першого довіреного проксі | Може бути підроблений зловмисним клієнтом, якщо не обробляється належним чином першим довіреним проксі |
| Інформація | IP клієнта, порт клієнта, IP проксі, порт проксі, (v2: TLV) | IP клієнта (і, можливо, IP попередніх проксі) |
| Накладні витрати | Мінімальні, фіксованого розміру (v1) або невеликі бінарні (v2) | Невеликий рядок, доданий до HTTP-заголовків |
| Випадки використання | Будь-яка служба TCP/UDP, що потребує реального IP клієнта | Служби HTTP/HTTPS, що потребують реального IP клієнта |
Протокол PROXY пропонує більш надійне та універсальне рішення для передачі інформації про IP-адресу клієнта, особливо для не-HTTP служб або сценаріїв, де потрібні сильні гарантії проти підробки IP-адреси клієнта на мережевому рівні.
Впровадження PROXY Protocol
Впровадження PROXY Protocol вимагає конфігурації як на проксі-сервері/балансувальнику навантаження, що відправляє, так і на бекенд-сервері, що приймає.
Конфігурація проксі-сервера/балансувальника навантаження (відправлення PROXY Protocol)
HAProxy:
HAProxy є поширеним вибором для балансування навантаження та повністю підтримує PROXY Protocol.
frontend http_in
bind *:80
mode tcp
default_backend web_servers
backend web_servers
mode tcp
server s1 192.168.1.10:80 send-proxy-v2 # Надсилає PROXY Protocol v2
server s2 192.168.1.11:80 send-proxy # Надсилає PROXY Protocol v1
AWS Network Load Balancer (NLB):
При налаштуванні цільової групи для NLB ви можете увімкнути підтримку PROXY Protocol v2. Це налаштування застосовується до всієї цільової групи. Усі цілі в цій групі повинні бути налаштовані на прийом PROXY Protocol.
Cloudflare Spectrum:
Для служб, що проксуються через Cloudflare Spectrum, ви можете увімкнути підтримку PROXY Protocol. Cloudflare надсилатиме заголовки PROXY Protocol v2 на ваші вихідні сервери.
Nginx (Stream Module - як проксі):
ngx_stream_proxy_module Nginx може бути налаштований на відправлення PROXY Protocol, переважно в його комерційній версії або спеціальних збірках.
stream {
upstream backend_servers {
server 192.168.1.10:80;
server 192.168.1.11:80;
}
server {
listen 12345;
proxy_pass backend_servers;
proxy_protocol on; # Nginx надсилає PROXY Protocol v1
}
}
Конфігурація бекенд-сервера (отримання та розбір PROXY Protocol)
Nginx (як бекенд веб-сервер):
Nginx може бути налаштований на прослуховування та розбір заголовків PROXY Protocol.
http {
server {
listen 80 proxy_protocol; # Прослуховувати PROXY Protocol v1/v2 на порту 80
listen 443 ssl proxy_protocol;
set_real_ip_from 10.0.0.0/8; # Довіряти IP-адресам з вашої проксі-мережі
real_ip_header proxy_protocol; # Використовувати IP з заголовка PROXY Protocol
location / {
root /var/www/html;
index index.html;
# Реальна IP-адреса клієнта тепер буде доступна в $remote_addr
# а $proxy_protocol_addr можна використовувати для логування або специфічної логіки
log_format custom_log '$proxy_protocol_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log custom_log;
}
}
}
У Nginx $remote_addr буде встановлено на IP-адресу проксі-сервера, але змінні $proxy_protocol_addr та $proxy_protocol_port міститимуть реальну IP-адресу та порт клієнта. Директиви set_real_ip_from та real_ip_header proxy_protocol дозволяють Nginx правильно заповнювати $remote_addr фактичною IP-адресою клієнта.
Apache HTTP Server:
Apache може використовувати модуль mod_remoteip для розбору заголовків PROXY Protocol.
<IfModule mod_remoteip.c>
# Увімкнути розбір PROXY Protocol
RemoteIPProxyProtocol On
# Визначити довірені проксі
RemoteIPTrustedProxy 10.0.0.0/8
RemoteIPTrustedProxy 192.168.0.0/16
# Налаштувати формат журналу для використання реального IP клієнта
LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
</IfModule>
З RemoteIPProxyProtocol On Apache очікуватиме заголовок PROXY Protocol. Змінна %a у LogFormat тоді правильно відображатиме реальну IP-адресу клієнта.
Користувацькі програми:
Для користувацьких програм, написаних мовами, такими як Python, Node.js, Go або Java, сама програма повинна прочитати вхідний TCP-потік, перевірити наявність заголовка PROXY Protocol, розібрати його, а потім продовжити роботу з протоколом, специфічним для програми.
- Виявлення: Програма повинна спочатку прочитати кілька байтів (наприклад, 100-200 байтів) із сокета, щоб перевірити, чи відповідають вони сигнатурі PROXY Protocol v1 (
PROXY) або сигнатурі v2. - Розбір: Якщо заголовок PROXY Protocol виявлено, програма розбирає його, щоб витягти IP-адресу клієнта, порт тощо.
- Продовження: Після розбору програма обробляє решту даних на сокеті як свій власний протокол.
- Відсутність заголовка: Якщо заголовок PROXY Protocol не знайдено, програма припускає, що з'єднання надходить безпосередньо від клієнта або проксі-сервера без PROXY Protocol, і обробляє дані безпосередньо.
Багато мережевих бібліотек та фреймворків пропонують проміжне програмне забезпечення або вбудовану підтримку для розбору PROXY Protocol.
Переваги використання PROXY Protocol
- Точне логування IP: Забезпечує, що журнали доступу сервера, брандмауери та системи моніторингу записують справжню IP-адресу клієнта.
- Покращена безпека: Дозволяє інструментам безпеки (WAF, пом'якшення DDoS, обмежувачі швидкості) на бекенд-серверах застосовувати політики на основі реальної ідентичності клієнта.
- Покращена аналітика: Надає точні географічні та демографічні дані для аналітики, A/B-тестування та персоналізації.
- Спрощена мережева архітектура: Консолідує обробку IP-адрес клієнтів на транспортному рівні, зменшуючи потребу в заголовках, специфічних для програм, таких як XFF.
- Широка сумісність: Працює з будь-якою програмою на основі TCP/UDP, а не лише HTTP.
Міркування та найкращі практики
- Межі довіри: Увімкніть PROXY Protocol лише для довірених проксі-серверів або балансувальників навантаження, які ви контролюєте. Якщо недовірена сутність надсилає підроблений заголовок PROXY Protocol, ваш бекенд-сервер може бути введений в оману щодо походження клієнта.
- Наскрізна сумісність: Переконайтеся, що як проксі-сервер, так і бекенд-сервер правильно налаштовані на відправлення та отримання конкретної версії PROXY Protocol (v1 або v2). Невідповідності призведуть до збоїв з'єднання.
- Продуктивність: Накладні витрати, спричинені заголовком PROXY Protocol, мінімальні, особливо з бінарним форматом v2. Однак розбір при кожному з'єднанні додає невелику, незначну вартість обробки.
- Моніторинг: Відстежуйте журнали вашого бекенд-сервера та мережевий трафік, щоб переконатися, що IP-адреси клієнтів ідентифікуються правильно і що не виникає несподіваних помилок PROXY Protocol.