Вопрос или проблема
У меня в локальной сети настроено перенаправление портов с несколькими разными серверами за одним маршрутизатором. У меня есть первый слой nginx-прокси, который я использую для маршрутизации ко второму nginx, который является обратным прокси приложения.
Вот конфигурация первого слоя:
error_log /var/log/nginx/error.log warn;
events {
worker_connections 1024;
}
stream {
upstream server1 {
server 10.0.0.119:8443;
}
upstream server2 {
server 10.0.0.126:9443;
}
upstream server3 {
server 10.0.0.119:7443;
}
map $ssl_preread_server_name $upstream {
server1.co server1_ssl;
server2.com server2_ssl;
server3.com server3_ssl;
default server3_ssl;
}
server {
listen 443;
proxy_pass $upstream;
ssl_preread on;
}
}
http {
log_format main '$http_x_forwarded_for $remote_addr - [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_user_agent" "$http_referer"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log warn;
server {
listen 80;
server_name server1.co;
location / {
proxy_pass http://10.0.0.119:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name server2.com;
location / {
proxy_pass http://10.0.0.126:9080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name server3.com;
location / {
proxy_pass http://10.0.0.119:7080;
# Установить оба заголовка
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
вот конфигурация nginx для приложения:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
Я также использовал файл из папки “sites enabled” в приложении:
server {
listen 80;
server_name server3.com;
# Разрешить аутентификацию certbot
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
# Перенаправить весь остальной трафик на HTTPS с пользовательским портом
location / {
return 301 https://$host:7443$request_uri;
}
}
server {
listen 7443 ssl;
server_name server3.com;
ssl_certificate /etc/letsencrypt/live/server3.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/server3.com/privkey.pem;
location / {
proxy_pass http://frontend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Добавить поддержку WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /api/ {
proxy_pass http://backend:8001/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Мой вопрос: как в этой конфигурации я могу сохранить IP-адрес запроса клиента в логах? Сейчас показывается всё как будто пришло с 172.21.0.1
.
Я пробовал добавлять различные заголовки, но безуспешно.
Вот пример лога:
172.21.0.1 - - [31/Dec/2024:17:31:06 +0000] "GET / HTTP/1.1" 200 1716 "-" "Uptime-Kuma/1.23.16" "-"
172.21.0.1 - - [31/Dec/2024:17:35:36 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 18_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1.1 Mobile/15E148 Safari/604.1" "-"
172.21.0.1 - - [31/Dec/2024:17:35:36 +0000] "GET /manifest.json HTTP/1.1" 304 0 "https://premiumtenant.com/" "Mozilla/5.0 (iPhone; CPU iPhone OS 18_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1.1 Mobile/15E148 Safari/604.1" "-"
172.21.0.1 - - [31/Dec/2024:17:35:36 +0000] "GET /static/js/bundle.js HTTP/1.1" 304 0 "https://premiumtenant.com/" "Mozilla/5.0 (iPhone; CPU iPhone OS 18_1_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1.1 Mobile/15E148 Safari/604.1" "-"
172.21.0.1 - - [31/Dec/2024:17:36:06 +0000] "GET / HTTP/1.1" 200 1716 "-" "Uptime-Kuma/1.23.16" "-"
Ответ или решение
Для решения проблемы с сохранением реальных IP-адресов клиентов в логах вашего Nginx-прокси требуется несколько корректировок как в конфигурации первого уровня прокси, так и приложения, на которое направляется трафик.
Проблема
Сложность заключается в том, что в текущей настройке вы видите IP-адрес 172.21.0.1 во всех логах. Это может быть связано с тем, что текущий прокси не передает оригинальные IP-адреса клиентов, что искажает данные об активности пользователей.
Решение
Чтобы правильно передавать IP-адреса клиентов через несколько уровней Nginx-прокси, необходимо убедиться в правильной установке и передаче заголовков, таких как X-Real-IP
и X-Forwarded-For
.
-
Первый уровень прокси (стим-процесс):
- В конфигурации
stream
заголовки напрямую не используются, так как данный блок работает на уровне TCP / UDP. Основной фокус следует обратить на http-блоки.
- В конфигурации
-
Первый уровень прокси (HTTP-блок):
-
Убедитесь, что заголовки
X-Real-IP
иX-Forwarded-For
добавляются корректно:proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Эти строки обеспечивают передачу IP-адреса клиента и цепочки прокси-серверов.
-
-
Второй уровень (в приложении):
-
Проверьте, чтобы приложением также были правильно обработаны эти заголовки. В логах
nginx
приложения настройте отображение$http_x_forwarded_for
. -
Вам может понадобиться настроить
real_ip_module
в Nginx для обработки переданных заголовков IP:http { ... set_real_ip_from 10.0.0.0/8; real_ip_header X-Forwarded-For; ... }
Это позволит серверу использовать переданный IP, а не подсеть Docker или еще какого-то внутреннего слоя.
-
Дополнительные шаги
-
SSL Предварительное чтение (ssl_preread): если маршрутизация происходит на уровне TLS, убедитесь, что ssl_preread включен, чтобы правильно обрабатывать SNI, так как это влияет на правильную маршрутизацию запросов.
-
Улучшенная диагностика: возможно, вам будет полезно временно добавить в логирование полное содержание заголовков запроса для диагностики передачи IP.
Внедрение данных изменений должно способствовать правильной передаче реального IP-адреса клиента через все слои вашего прокси-сервиса и, следовательно, его отображению в логах.