Прокси-сервер Nginx направлен на другой Nginx и фиксирует и не фиксирует реальный IP-адрес.

Вопрос или проблема

У меня в локальной сети настроено перенаправление портов с несколькими разными серверами за одним маршрутизатором. У меня есть первый слой 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.

  1. Первый уровень прокси (стим-процесс):

    • В конфигурации stream заголовки напрямую не используются, так как данный блок работает на уровне TCP / UDP. Основной фокус следует обратить на http-блоки.
  2. Первый уровень прокси (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-адреса клиента и цепочки прокси-серверов.

  3. Второй уровень (в приложении):

    • Проверьте, чтобы приложением также были правильно обработаны эти заголовки. В логах 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-адреса клиента через все слои вашего прокси-сервиса и, следовательно, его отображению в логах.

Оцените материал
Добавить комментарий

Капча загружается...