Серверное оборудование для бизнеса — надёжные решения для любых задач Подробнее →
Статья

Nginx как reverse proxy: от простого к продвинутому

Nginx как reverse proxy: от простого к продвинутому

Nginx давно перестал быть просто веб-сервером. В современных архитектурах он чаще всего выступает как reverse proxy — принимает запросы от клиентов и передаёт их бэкенд-сервисам. Это даёт централизованное управление SSL, балансировку нагрузки, кэширование и защиту приложений. Разберём все ключевые возможности последовательно.

Базовый proxy_pass

Минимальная конфигурация reverse proxy:

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

    location / {
        proxy_pass http://127.0.0.1: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;
    }
}

proxy_set_header критически важен — без этих заголовков бэкенд не будет знать реальный IP клиента и протокол.

Upstream: балансировка нагрузки

Директива upstream позволяет распределять запросы между несколькими бэкендами:

upstream app_backend {
    least_conn;                    # алгоритм: наименьшее число соединений
    server 10.0.0.1:3000 weight=3;
    server 10.0.0.2:3000 weight=1;
    server 10.0.0.3:3000 backup;   # резервный, включается при падении остальных
    keepalive 32;
}

server {
    location / {
        proxy_pass http://app_backend;
    }
}

Алгоритмы: round-robin (умолчание), least_conn, ip_hash (sticky sessions), random.

Health checks (Nginx Plus / open-source)

В Nginx Plus health checks встроены. В open-source версии используйте модуль nginx_upstream_check_module или пассивные проверки:

upstream app_backend {
    server 10.0.0.1:3000 max_fails=3 fail_timeout=30s;
    server 10.0.0.2:3000 max_fails=3 fail_timeout=30s;
}

После трёх неудачных запросов за 30 секунд сервер помечается как недоступный на 30 секунд.

Кэширование

# В http блоке:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=app_cache:10m max_size=1g
                 inactive=60m use_temp_path=off;

# В server/location блоке:
location / {
    proxy_cache app_cache;
    proxy_cache_valid 200 302 10m;
    proxy_cache_valid 404 1m;
    proxy_cache_use_stale error timeout updating;
    proxy_cache_lock on;
    add_header X-Cache-Status $upstream_cache_status;
}

Заголовок X-Cache-Status покажет HIT/MISS/BYPASS — удобно для отладки.

SSL Termination

Nginx принимает HTTPS от клиента, а к бэкенду обращается по HTTP — это SSL termination:

server {
    listen 443 ssl http2;
    server_name app.example.com;

    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_session_cache shared:SSL:10m;

    location / {
        proxy_pass http://app_backend;
    }
}

Rate Limiting

Защита от злоупотреблений:

# В http блоке:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

# В location:
location /api/ {
    limit_req zone=api_limit burst=20 nodelay;
    limit_conn conn_limit 10;
    proxy_pass http://app_backend;
}

burst=20 разрешает кратковременные всплески до 20 запросов. nodelay обрабатывает их немедленно, не ставя в очередь.

WebSocket проксирование

WebSocket требует специальных заголовков для upgrade соединения:

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

Управление заголовками

Скрывайте информацию о бэкенде, добавляйте заголовки безопасности:

proxy_hide_header X-Powered-By;
proxy_hide_header Server;

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

Nginx как reverse proxy — это не сложно, но важно понимать каждую директиву. Типичные ошибки: забытые proxy_set_header, неправильный proxy_read_timeout для долгих запросов и кэширование там, где оно не нужно.

3 Ответа

  1. Отличная статья, особенно раздел про WebSocket — это реально часто вызывает вопросы у тех кто переходит с Apache. Без правильных заголовков Upgrade соединение просто не устанавливается и непонятно почему.

  1. По кэшированию важно добавить: не кэшируйте запросы с авторизацией без явной проверки — можно случайно отдать одному пользователю кэш с данными другого. Используйте proxy_cache_bypass $http_authorization.

  1. Rate limiting через limit_req спас нас от нескольких волн ботов. Главное правильно подобрать burst — слишком маленький и будут жалобы от реальных пользователей, слишком большой — не защищает.