0

Определение реального IP на бекендах

В процессе организации отказоустойчивого решения для WWW сервисов возникла проблема проброса реальных IP адресов на WWW сервисы, находящиеся за балансировщиком нагрузки. Понятно, что делается это через HTTP заголовки, например, X-FORWARDED-FOR. Но в моей схеме есть нюансы.
Итак, обо всем по порядку.

Описание

Очень упрощенно схема выглядит следующим образом:

real_ip

В качестве балансировщика нагрузки выступает «черный ящик», который записывает реальный IP адрес в HTTP заголовок X-FORWADED-FOR. От этого и буду отталкиваться.
Связка NGINX — Apache уже настроена и работает, отмечу только изменения.

NGINX

Сначала сделаю логирование реального IP у nginx.

Для этого в /etc/nginx/nginx.conf в секции логирования вношу следующие изменения:

-	log_format common '$remote_addr - - [$time_local - $upstream_response_time] "$request" $status $bytes_sent "$http_referer" "$http_user_agent" $msec';
+	log_format common '$http_x_forwarded_for - - [$time_local - $upstream_response_time] "$request" $status $bytes_sent "$http_referer" "$http_user_agent" $msec';

Затем нужно организовать передачу реального IP далее на Apache. Для этого в секции проксирования вношу следующие изменения:

-		proxy_set_header	X-Real-IP        $remote_addr;
+		proxy_set_header	X-Real-IP        $http_x_forwarded_for;

Apache

Затем в в описание формата лога Apache следующие изменения:

-	LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+	LogFormat "%{X-Real-IP}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

В итоге в логах как Apache, так и NGINX появляются реальные IP адреса вместо адреса балансировщика.

Post Scriptum

Стоит отметить, что если в HTTP запросе не указан X-FORWARD-FOR, то запрос прошел не через балансировщик, и как следствие в логах записи о его IP не будет. Предполагаю, что для исправления этого недостатка в конфиги нужно добавить проверку на наличие в HTTP headers X-FORWARDED-FOR. Мне рабираться смысла не было.. Но если кто подскажет решение — буду рад.

Кроме логирования запросов преследовались и другие цели, а именно заставить нормально работать приложение с GEOIP сервисом. Проблема была в том, что сервису для проверки посетителя передавался локальный адрес балансировщика. Разработчики вместо REMOTE_ADD стали передавать X-REAL-IP и все встало на свои места.

Alexey Egorychev

FreeBSD and Linux sysadmin. Know many systems like mailsystems, DB, WWW stack. Automation with salt, ansible. Monitoring with nagios, zabbix.