Когда сайт не справляется: Nginx, SSL и балансировка для финтех-стартапа

Задача клиента

К нам обратился CTO финтех-стартапа из Москвы — платформа для управления корпоративными расходами с ~3000 активными компаниями-клиентами. Проект быстро рос: за последний квартал трафик увеличился в 4 раза, и единственный сервер приложения перестал справляться с нагрузкой.

Проблемы, которые описал клиент:

  • Время ответа API выросло с 200 мс до 2-3 секунд в часы пик
  • Периодические 502-ошибки — бэкенд не успевал обрабатывать запросы
  • Отсутствие SSL-терминации — шифрование выполнялось на уровне приложения, нагружая CPU
  • Нет защиты от DDoS — один инцидент с ботами уже положил сервис на 40 минут
  • Масштабирование невозможно — монолитная архитектура без балансировки

Мы предложили комплексное решение: Nginx как обратный прокси с SSL-терминацией, балансировкой нагрузки между тремя бэкенд-серверами, кешированием и многоуровневой защитой.

Проектирование архитектуры reverse proxy

Обратный прокси (reverse proxy) — это сервер, который принимает входящие запросы клиентов и перенаправляет их на один или несколько бэкенд-серверов. Nginx — самый популярный выбор для этой роли благодаря высокой производительности и низкому потреблению ресурсов.

Задачи, которые мы закрыли обратным прокси для клиента:

  • SSL-терминация — разгрузили бэкенд-серверы от шифрования
  • Балансировка нагрузки — распределили запросы между тремя серверами
  • Кеширование — снизили нагрузку на бэкенд, отдавая статический контент из кеша
  • Защита — скрыли внутреннюю инфраструктуру, фильтровали вредоносные запросы
  • Rate limiting — защита от DDoS и брутфорса
  • Единая точка входа — маршрутизация по доменам/URL на разные сервисы

Спроектированная архитектура

Мы разработали следующую схему для production:

Клиент → Nginx (reverse proxy, порт 443/SSL) → Backend-серверы:
  ├── upstream app_servers  → Node.js / Python / PHP (порт 8080)
  ├── upstream api_servers  → REST API (порт 3000)
  └── upstream static       → CDN или файловый сервер

Nginx обрабатывает тысячи одновременных соединений, потребляя при этом минимум памяти. На одном выделенном Nginx мы обеспечили обслуживание всех сервисов клиента.

Установка Nginx из официального репозитория

Мы установили последнюю стабильную версию Nginx — важно использовать официальный репозиторий, а не устаревшую версию из дистрибутива:

# Debian/Ubuntu: добавляем официальный репозиторий Nginx
apt install curl gnupg2 ca-certificates lsb-release -y

curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor -o /usr/share/keyrings/nginx-archive-keyring.gpg

echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] http://nginx.org/packages/debian $(lsb_release -cs) nginx" > /etc/apt/sources.list.d/nginx.list

apt update && apt install nginx -y

# Проверяем версию и запускаем
nginx -v
systemctl enable --now nginx

# Проверяем конфигурацию
nginx -t

Для CentOS/RHEL процедура аналогична:

cat > /etc/yum.repos.d/nginx.repo << 'EOF'
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
EOF

dnf install nginx -y
systemctl enable --now nginx

Настройка proxy_pass для сервисов клиента

Директива proxy_pass — ядро обратного проксирования в Nginx. Мы настроили проксирование для каждого компонента платформы клиента.

Базовое проксирование на бэкенд

Первым делом мы настроили проксирование на основное приложение:

# /etc/nginx/conf.d/app.conf
server {
    listen 80;
    server_name app.example.ru;

    location / {
        proxy_pass http://127.0.0.1:8080;

        # Передаём реальный IP клиента
        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 30s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # Буферизация
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 16k;
        proxy_busy_buffers_size 32k;
    }
}

Важно: без заголовка X-Real-IP бэкенд видит IP-адрес Nginx (127.0.0.1), а не реального клиента. Для финтех-платформы это критично для аудита и безопасности.

WebSocket для real-time уведомлений

Платформа клиента использовала WebSocket для мгновенных уведомлений о транзакциях. Для WebSocket-соединений требуется особая конфигурация:

location /ws/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;

    # Увеличиваем таймаут для долгих соединений
    proxy_read_timeout 86400s;
    proxy_send_timeout 86400s;
}

# Для Server-Sent Events (SSE)
location /events/ {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Connection '';
    proxy_http_version 1.1;
    proxy_buffering off;
    proxy_cache off;
    chunked_transfer_encoding off;
}

Маршрутизация по URL: фронтенд, API, админка

Мы разделили трафик на несколько бэкендов по URL-паттернам:

# Маршрутизация по URL
server {
    listen 80;
    server_name example.ru;

    # Фронтенд
    location / {
        proxy_pass http://127.0.0.1:3000;
    }

    # API
    location /api/ {
        proxy_pass http://127.0.0.1:8080/;
        # Trailing slash в proxy_pass убирает /api/ из пути
    }

    # Статика
    location /static/ {
        alias /var/www/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # Админка
    location /admin/ {
        proxy_pass http://127.0.0.1:8000;
        allow 10.0.0.0/24;
        deny all;  # Доступ только из внутренней сети
    }
}

Админ-панель мы ограничили по IP — доступ только из офисной сети клиента.

SSL/TLS: рейтинг A+ на SSL Labs

Для финтех-платформы HTTPS — не просто рекомендация, а требование регуляторов. Мы настроили SSL с рейтингом A+ на SSL Labs.

Получение сертификатов Let's Encrypt

Мы использовали Certbot для получения бесплатных SSL-сертификатов с автоматическим обновлением:

# Установка Certbot
apt install certbot python3-certbot-nginx -y

# Получение сертификата (автоматическая настройка Nginx)
certbot --nginx -d example.ru -d www.example.ru \
  --non-interactive --agree-tos --email admin@itfresh.ru

# Или только получение сертификата без изменения конфига
certbot certonly --webroot -w /var/www/html \
  -d example.ru -d www.example.ru \
  --non-interactive --agree-tos --email admin@itfresh.ru

# Wildcard сертификат через DNS challenge
certbot certonly --manual --preferred-challenges dns \
  -d "*.example.ru" -d example.ru

# Проверяем автоматическое обновление
certbot renew --dry-run

# Автообновление через systemd timer (уже настроено)
systemctl status certbot.timer

Конфигурация SSL для рейтинга A+

Мы создали сниппет с оптимальной SSL-конфигурацией:

# /etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 1.1.1.1 8.8.8.8 valid=300s;
resolver_timeout 5s;

# SSL session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;

# DH параметры
ssl_dhparam /etc/nginx/dhparam.pem;

# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

Сгенерировали DH-параметры:

openssl dhparam -out /etc/nginx/dhparam.pem 2048

Production-ready конфигурация HTTPS

Итоговая конфигурация виртуального хоста, которую мы развернули:

# /etc/nginx/conf.d/example.ru.conf

# Редирект HTTP → HTTPS
server {
    listen 80;
    server_name example.ru www.example.ru;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.ru www.example.ru;

    # SSL сертификаты
    ssl_certificate /etc/letsencrypt/live/example.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.ru/privkey.pem;
    include /etc/nginx/snippets/ssl-params.conf;

    # Логи
    access_log /var/log/nginx/example.ru.access.log;
    error_log /var/log/nginx/example.ru.error.log;

    # Обратное проксирование
    location / {
        proxy_pass http://127.0.0.1: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;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Балансировка нагрузки между тремя серверами

Ключевая задача — распределить нагрузку между тремя бэкенд-серверами, которые мы добавили в инфраструктуру клиента. Nginx поддерживает несколько алгоритмов балансировки через директиву upstream.

Выбор алгоритма балансировки

Мы протестировали несколько алгоритмов и выбрали оптимальный для нагрузки клиента:

# Round Robin (по умолчанию) — равномерное распределение
upstream backend {
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
    server 10.0.0.13:8080;
}

# Weighted Round Robin — с учётом мощности серверов
upstream backend {
    server 10.0.0.11:8080 weight=5;  # Мощный сервер, 5x запросов
    server 10.0.0.12:8080 weight=3;
    server 10.0.0.13:8080 weight=1;  # Слабый сервер
}

# Least Connections — на наименее загруженный сервер
upstream backend {
    least_conn;
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
    server 10.0.0.13:8080;
}

# IP Hash — один клиент всегда попадает на один сервер (sticky sessions)
upstream backend {
    ip_hash;
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
    server 10.0.0.13:8080;
}

# Hash по произвольному ключу
upstream backend {
    hash $request_uri consistent;
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}

Для API клиента мы выбрали Least Connections — алгоритм направляет запрос на наименее загруженный сервер, что идеально для API с разной длительностью запросов.

Health checks и отказоустойчивость

Мы настроили автоматический вывод из ротации недоступных серверов и повтор запросов:

upstream backend {
    least_conn;

    # max_fails — количество неудач до вывода из ротации
    # fail_timeout — время, на которое сервер выводится
    server 10.0.0.11:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.12:8080 max_fails=3 fail_timeout=30s;
    server 10.0.0.13:8080 max_fails=3 fail_timeout=30s;

    # Резервный сервер (используется только если все основные недоступны)
    server 10.0.0.20:8080 backup;

    # Keepalive-соединения к бэкенду для производительности
    keepalive 32;
}

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

    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;

        # Повтор запроса на другой сервер при ошибке
        proxy_next_upstream error timeout http_502 http_503 http_504;
        proxy_next_upstream_tries 2;
        proxy_next_upstream_timeout 10s;
    }
}

Благодаря proxy_next_upstream при падении одного бэкенда пользователь даже не заметит проблемы — запрос автоматически уйдёт на другой сервер.

Sticky sessions для авторизованных пользователей

Для части сервисов с серверными сессиями мы настроили привязку по cookie:

# Nginx Plus (коммерческая версия) имеет встроенный sticky cookie.
# Для открытой версии — используем модуль nginx-sticky-module или ip_hash.

# Альтернатива: sticky через map
map $cookie_backend_server $backend_sticky {
    default backend;
    ~server1 backend_1;
    ~server2 backend_2;
}

upstream backend_1 {
    server 10.0.0.11:8080;
}

upstream backend_2 {
    server 10.0.0.12:8080;
}

upstream backend {
    least_conn;
    server 10.0.0.11:8080;
    server 10.0.0.12:8080;
}

server {
    location / {
        proxy_pass http://$backend_sticky;
        # Устанавливаем cookie при первом запросе
        add_header Set-Cookie "backend_server=server1; Path=/; HttpOnly" always;
    }
}

Кеширование: снизили нагрузку на бэкенд в 10 раз

Статический контент (JS, CSS, изображения) и ряд API-ответов не менялись между запросами. Кеширование на уровне Nginx позволило снизить нагрузку на бэкенд в 10 раз для этих запросов.

Настройка proxy cache

Полная конфигурация кеширования, которую мы применили:

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

# В server/location
server {
    listen 443 ssl http2;
    server_name example.ru;

    location / {
        proxy_pass http://backend;
        proxy_cache app_cache;

        # Время кеширования по коду ответа
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 301 1h;
        proxy_cache_valid 404 1m;
        proxy_cache_valid any 5m;

        # Ключ кеша
        proxy_cache_key $scheme$request_method$host$request_uri;

        # Заголовок для отладки (HIT/MISS/BYPASS)
        add_header X-Cache-Status $upstream_cache_status;

        # Отдавать устаревший кеш при ошибке бэкенда
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;

        # Обновлять кеш в фоне
        proxy_cache_background_update on;
        proxy_cache_lock on;
    }

    # Не кешировать API и авторизованные запросы
    location /api/ {
        proxy_pass http://backend;
        proxy_cache off;
        proxy_no_cache 1;
    }

    # Длительный кеш для статики
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
        proxy_pass http://backend;
        proxy_cache app_cache;
        proxy_cache_valid 200 30d;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

Gzip-сжатие для экономии трафика

Мы настроили сжатие, уменьшающее объём передаваемых данных на 60-80%:

# /etc/nginx/conf.d/compression.conf

# Gzip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 5;
gzip_min_length 256;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/json
    application/javascript
    application/xml
    application/rss+xml
    image/svg+xml
    font/woff2;

# Brotli (требует модуль ngx_brotli)
# brotli on;
# brotli_comp_level 6;
# brotli_types text/plain text/css text/xml application/json application/javascript;

Тюнинг worker-процессов для высокой нагрузки

Мы оптимизировали Nginx для максимальной производительности под нагрузку клиента:

# /etc/nginx/nginx.conf
worker_processes auto;  # По количеству ядер CPU
worker_rlimit_nofile 65535;

events {
    worker_connections 16384;
    multi_accept on;
    use epoll;
}

http {
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    types_hash_max_size 2048;
    server_tokens off;  # Скрываем версию Nginx

    # Увеличиваем буфер для больших заголовков
    large_client_header_buffers 4 16k;
    client_max_body_size 100m;

    # Open file cache
    open_file_cache max=10000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
}

Безопасность: security headers и защита от атак

Для финтех-платформы безопасность — приоритет номер один. Мы настроили многоуровневую защиту на уровне Nginx.

HTTP Security Headers

Мы создали сниппет с полным набором заголовков безопасности:

# /etc/nginx/snippets/security-headers.conf

# Защита от XSS
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;

# Referrer Policy
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

# Permissions Policy
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

# Content Security Policy (настройте под ваше приложение)
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.ru; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com;" always;

# HSTS (только если уверены, что HTTPS настроен правильно)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;

Подключение в виртуальном хосте одной строкой:

server {
    listen 443 ssl http2;
    server_name example.ru;
    include /etc/nginx/snippets/security-headers.conf;
    # ...
}

Rate limiting — защита от DDoS и брутфорса

Мы настроили многоуровневое ограничение частоты запросов — особенно важно для API платёжной платформы:

# Определяем зоны ограничений (в блоке http)

# Лимит по IP: 10 запросов в секунду
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;

# Лимит на API: 5 запросов в секунду
limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;

# Лимит на логин: 1 запрос в секунду
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

# Лимит на соединения
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

server {
    # Общий лимит с burst (всплеском)
    location / {
        limit_req zone=general burst=20 nodelay;
        limit_conn conn_limit 50;
        proxy_pass http://backend;
    }

    # Строгий лимит для API
    location /api/ {
        limit_req zone=api burst=10 nodelay;
        limit_req_status 429;  # Too Many Requests
        proxy_pass http://backend;
    }

    # Очень строгий лимит для логина
    location /login {
        limit_req zone=login burst=3;
        proxy_pass http://backend;
    }
}

Параметр burst — допускает кратковременные всплески. burst=20 nodelay означает: принять до 20 запросов сверх лимита мгновенно, далее — отклонять.

Фильтрация вредоносного трафика

На основании логов DDoS-инцидента клиента мы настроили фильтрацию подозрительного трафика:

# Блокируем известных ботов и сканеры
map $http_user_agent $bad_bot {
    default 0;
    ~*sqlmap 1;
    ~*nikto 1;
    ~*nmap 1;
    ~*masscan 1;
    ~*python-requests 1;
    ~*dirbuster 1;
}

server {
    # Блокируем плохих ботов
    if ($bad_bot) {
        return 403;
    }

    # Блокируем запросы без Host
    if ($host = '') {
        return 444;  # Закрываем соединение без ответа
    }

    # Блокируем типичные пути атак
    location ~* /(wp-admin|wp-login|xmlrpc|phpmyadmin|\.env|\.git) {
        return 444;
    }

    # Запрещаем доступ к скрытым файлам
    location ~ /\. {
        deny all;
        return 404;
    }
}

После внедрения этих правил количество паразитного трафика снизилось на 70%, что дополнительно разгрузило бэкенд.

Мониторинг и отладка: видим всё в реальном времени

Мы настроили мониторинг Nginx, чтобы команда клиента могла отслеживать состояние системы.

Stub status и метрики для Prometheus

Включили модуль статистики для интеграции с системой мониторинга:

# /etc/nginx/conf.d/status.conf
server {
    listen 127.0.0.1:8080;
    server_name localhost;

    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

# Проверяем
curl http://127.0.0.1:8080/nginx_status
# Active connections: 42
# server accepts handled requests
#  10543 10543 28456
# Reading: 0 Writing: 3 Waiting: 39

JSON-логи для анализа и алертов

Мы перевели логи в JSON-формат для интеграции с системой логирования клиента:

# В блоке http
log_format json_combined escape=json
  '{"time":"$time_iso8601",'
  '"remote_addr":"$remote_addr",'
  '"request_method":"$request_method",'
  '"request_uri":"$request_uri",'
  '"status":$status,'
  '"body_bytes_sent":$body_bytes_sent,'
  '"request_time":$request_time,'
  '"upstream_response_time":"$upstream_response_time",'
  '"upstream_addr":"$upstream_addr",'
  '"http_user_agent":"$http_user_agent",'
  '"http_referer":"$http_referer",'
  '"cache_status":"$upstream_cache_status"}';

server {
    access_log /var/log/nginx/access.json json_combined;
}

Быстрый анализ логов для диагностики:

# Топ-10 IP по количеству запросов
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -10

# Запросы с ошибками 5xx
grep '" 5[0-9][0-9] ' /var/log/nginx/access.log | tail -20

# Среднее время ответа
awk '{sum += $NF; n++} END {print sum/n}' /var/log/nginx/access.log

Результаты внедрения

Проект был реализован за 4 рабочих дня, включая нагрузочное тестирование. Вот измеримые результаты:

  • Время ответа API снизилось с 2-3 секунд до 150 мс — благодаря балансировке и кешированию
  • 502-ошибки полностью исчезли — proxy_next_upstream автоматически перенаправляет запросы
  • Нагрузка на бэкенд снизилась на 75% — статика и повторяющиеся запросы отдаются из кеша Nginx
  • Рейтинг A+ на SSL Labs — соответствие требованиям финтех-регуляторов
  • Блокировка 70% паразитного трафика — rate limiting и фильтрация ботов
  • Горизонтальное масштабирование — добавить новый бэкенд-сервер можно за 5 минут, просто добавив строку в upstream
  • Нулевой downtime при обновлениях — можно обновлять бэкенд-серверы по одному, выводя из ротации

Спустя месяц трафик клиента вырос ещё в 2 раза, но инфраструктура справилась без каких-либо проблем — мы просто добавили четвёртый бэкенд-сервер за 10 минут. Если ваш проект растёт и текущая инфраструктура не справляется — обратитесь в АйТи Фреш, и мы спроектируем масштабируемое решение.

Часто задаваемые вопросы

Trailing slash в proxy_pass влияет на передачу URI. proxy_pass http://backend; — передаёт полный оригинальный URI. proxy_pass http://backend/; — убирает часть URI, совпавшую с location. Например, при location /api/ запрос /api/users будет передан как /users при наличии slash и как /api/users без него.

Создайте отдельный файл конфигурации для каждого домена в /etc/nginx/conf.d/. Каждый файл содержит свой блок server с уникальным server_name. Nginx определяет нужный виртуальный хост по заголовку Host входящего запроса. Для SSL получите отдельные сертификаты для каждого домена или один wildcard-сертификат.

Ошибка 502 означает, что Nginx не может получить ответ от бэкенд-сервера. Частые причины: 1) Бэкенд-сервис не запущен — проверьте systemctl status; 2) Неправильный порт в proxy_pass; 3) Файрвол блокирует соединение; 4) Бэкенд перегружен — увеличьте таймауты proxy_read_timeout; 5) При использовании unix-сокета — неправильные права доступа. Мы помогаем клиентам диагностировать и устранять такие проблемы.

Certbot автоматически настраивает обновление через systemd timer или cron. Проверьте: systemctl status certbot.timer. Для ручного обновления: certbot renew. Если автообновление не работает, добавьте в crontab: 0 3 * * * certbot renew --quiet --post-hook 'systemctl reload nginx'. Сертификаты обновляются за 30 дней до истечения.

Используйте директивы allow и deny в блоке location или server: allow 10.0.0.0/24; allow 192.168.1.100; deny all;. Порядок важен — Nginx проверяет правила сверху вниз. Для geo-блокировки используйте модуль ngx_http_geoip2_module с базой MaxMind GeoIP2.

Нужна помощь с настройкой?

Специалисты АйТи Фреш помогут с внедрением и настройкой — 15+ лет опыта, обслуживание от 15 000 ₽/мес

📞 Связаться с нами
#nginx reverse proxy#обратный прокси nginx#nginx ssl#let's encrypt nginx#nginx балансировка нагрузки#nginx upstream#nginx кеширование#nginx security headers