Проксирование запросов в nginx с помощью proxy_pass

0
5608
Обложка статьи: Проксирование запросов в nginx с помощью proxy_pass

Нужно отдать запрос с nginx на бэкенд через proxy_pass и не потерять имя клиента. TLS снаружи — в статье про HTTPS.

1. Минимальный location

По ngx_http_proxy_module:

upstream app {
    server 127.0.0.1:8080;
}

server {
    listen 80;
    server_name www.example.com;

    location / {
        proxy_pass http://app;
        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;
        proxy_connect_timeout 5s;
        proxy_read_timeout 60s;
    }
}

Слэш в proxy_pass меняет путь: proxy_pass http://app; оставляет URI, proxy_pass http://app/; подменяет location. Не угадайте — сверьте в доке модуля.

2. Проверить конфиг

sudo nginx -t
sudo systemctl reload nginx
curl -sI -H "Host: www.example.com" http://127.0.0.1/

Ожидание: nginx -t successful, бэкенд отвечает 200 или свой редирект. Если 502 — апстрим не слушает. Проверьте ss -lntup | grep 8080.

3. Не открыть лишнее

Бэкенд должен слушать localhost или внутренний VLAN, не 0.0.0.0 в интернет. Ограничьте методы, если API не публичный:

location /admin/ {
    allow 192.0.2.0/24;
    deny all;
    proxy_pass http://app;
}

Таймауты держите явными: иначе nginx будет висеть на мёртвом апстриме. Если апстрим по HTTPS — свой proxy_ssl_*, не «просто http на 443».

WebSocket

Для приложений с веб-сокетами (чаты, панели в реальном времени) нужны дополнительные заголовки и HTTP/1.1:

location /ws/ {
    proxy_pass http://app;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_read_timeout 3600s;
}

Без этого соединение закрывается сразу после установки.

Размер запросов и буферы

  • client_max_body_size 20m;: лимит на загрузку файлов. По умолчанию 1 МБ, и большие файлы получат ошибку 413.
  • proxy_buffering off; нужен для потоковых ответов (серверные события), но снижает пропускную способность для обычных страниц.

Настоящий адрес клиента в приложении

Приложение за прокси видит адрес nginx, а не пользователя. Доверяйте заголовкам X-Forwarded-For и X-Real-IP только от своего прокси. Если перед nginx стоит ещё один балансировщик, настройте модуль realip:

set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;

Указывайте адреса только своих промежуточных узлов, иначе клиент подделает заголовок, и ограничения по IP перестанут работать.

Диагностика 502 и 504

sudo tail -n 30 /var/log/nginx/error.log
curl -sI http://127.0.0.1:8080/
Сообщение в error.log Причина
connect() failed (111: Connection refused) Приложение не запущено или слушает другой порт
upstream timed out (504) Приложение отвечает медленнее proxy_read_timeout
no live upstreams Все серверы группы помечены недоступными

Включите HTTPS на этом же сервере: TLS в nginx. Для приложения по HTTP во внутренней сети TLS заканчивается на nginx, а бэкенд закрывайте firewall: nftables и firewalld.

Как проверить

sudo nginx -t
curl -sI -H "Host: www.example.com" http://127.0.0.1/
ss -lntup | grep -E ':80|:8080'

80 слушает nginx, 8080 — не на публичном адресе, заголовок Host доехал до приложения (смотрите access-лог бэкенда).

Источники

Комментарии закрыты.