Истории успеха наших клиентов — лучшие проекты
Вход/ Регистрация
На главную
61c46507-12c7-4300-a301-bd8bc30c7c19
Инструкции для серверов

Использование proxy_pass в Nginx

proxy_pass — это директива Nginx, при помощи которой можно передавать входящие HTTP-запросы другому сервису. Nginx в принимает запрос от клиента, отправляет его на указанный адрес и возвращает ответ обратно.

Один из самых распространенных примеров применения — сервис, запущенный на сервере и доступный только локально по адресу вида localhost:порт. Технически можно открыть этот порт наружу и обращаться к сервису напрямую, но такой подход может быть неудобным и небезопасным. Обращаться к сервису по домену проще, а сам сервис при этом может не поддерживать SSL, авторизацию или ограничение доступа по IP. В такой схеме Nginx принимает запросы по домену и проксирует их на локальный порт сервиса.

Другой сценарий — использование вебхуков. Например, при работе Telegram-бота вебхуки требуют публичный HTTPS-адрес. Сам бот при этом может работать локально или в контейнере и принимать HTTP-запросы. Nginx в этом случае используется для приема HTTPS-запросов, обработки сертификатов и проксирования запросов к сервису бота через proxy_pass.

proxy_pass также часто применяют, когда инфраструктура разнесена на несколько серверов. Например, сайт работает на одном сервере, а форум — на другом. С помощью Nginx можно настроить проксирование так, чтобы при обращении к /forum запросы отправлялись на отдельный сервер с форумом. Для пользователя все выглядит как единый сайт, хотя фактически сервисы физически разделены.

Перечисленные примеры — лишь часть ситуаций, в которых применим proxy_pass.

Предварительная подготовка

Если Nginx еще не установлен — установите его при помощи команд:

    
sudo apt update && sudo apt install nginx -y

После установки запустите сервис и добавьте его в автозагрузку:

    
sudo systemctl start nginx && sudo systemctl enable nginx

Проверьте статус сервиса — он должен быть в состоянии active:

    
sudo systemctl status nginx

Для удобства управления конфигурациями рекомендуется создавать отдельный конфиг для каждого сервиса. В rpm-based дистрибутивах конфигурационные файлы обычно располагаются в каталоге /etc/nginx/conf.d/.

В deb-based дистрибутивах используется другая схема: конфиги размещаются в /etc/nginx/sites-available/, а для их активации создаются симлинки в /etc/nginx/sites-enabled/.

Далее в примерах будет использоваться deb-based дистрибутив.

По умолчанию Nginx создает конфигурацию default. Если обратиться в браузере к адресу http://IP_сервера, вы увидите стандартную заглушку Nginx — за нее как раз отвечает этот конфиг. Его можно удалить:

    
rm /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default 

Создайте новый конфигурационный файл для сервиса:

    
touch /etc/nginx/sites-available/my-service.conf

И сразу создайте симлинк:

    
sudo ln -s /etc/nginx/sites-available/my-service.conf /etc/nginx/sites-enabled/

Далее, после любого изменения конфигурации проверьте ее корректность:

    
nginx -t

Если ошибок нет, примените изменения:

    
systemctl reload nginx

Пример использования

В первом примере представим, что сервис запущен на localhost:6789. Это может быть, например, сайт на Python или Telegram-бот на Node.js, запущенный через gunicorn или pm2. Мы хотим, чтобы сервис был доступен из интернета по домену service.example.com.

Откройте конфигурационный файл для редактирования:

    
nano /etc/nginx/sites-available/my-service.conf

Минимальная конфигурация будет выглядеть следующим образом:

    
server { listen 80; server_name _; location / { proxy_pass http://127.0.0.1:6789; } }

При такой конфигурации все обращения к серверу, включая обращения по его IP-адресу, будут проксироваться на внутренний сервис 127.0.0.1:6789. Вместо IP-адреса можно указать домен, URI или путь к UNIX-сокету.

Чтобы сервис был доступен по конкретному домену, укажите его вместо _ в директиве server_name.

В текущей конфигурации внутреннему сервису не передаются заголовки, которые отправляет клиент. Это может привести к проблемам с логированием, редиректами и определением реального IP клиента. Для передачи заголовков используются директивы proxy_set_header. Также имеет смысл отключить буферизацию ответов с помощью proxy_buffering, особенно если сервис отдает данные потоково или используется для вебхуков.

Итоговая конфигурация может выглядеть так:

    
server { listen 80; server_name service.example.com; location / { proxy_pass http://127.0.0.1:6789; proxy_http_version 1.1; 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_buffering off; } }

Проверьте конфигурацию:

    
nginx -t

И перезагрузите Nginx, чтобы применить изменения:

    
systemctl reload nginx

Проксирование части запроса

Предположим, что у сервиса есть API, который расположен на другом сервере и должен быть доступен по адресу service.example.com/api. В этом случае также можно использовать proxy_pass.

Добавьте новый блок location в конфигурационный файл:

    
server { listen 80; server_name service.example.com; location / { proxy_pass http://127.0.0.1:6789; proxy_http_version 1.1; 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_buffering off; } location /api/ { proxy_pass http://ip_стороннего_сервера:8000; } }

В этом случае все запросы к /api будут проксироваться на отдельный сервер, а остальные — обрабатываться основным сервисом.

Настройка авторизации

Чтобы ограничить доступ к сервису с помощью базовой HTTP-аутентификации, сначала сгенерируйте хэш пароля. Например, с помощью openssl:

    
openssl passwd -apr1

Дважды укажите желаемый пароль. В результате команда вернет строку с хэшем, например:

    
$apr1$9o.mJgYk$43kvlHx0DSqezaAL3yMHe1

Создайте файл для хранения логинов и хэшей паролей. Его можно разместить в любой удобной директории, например в каталоге Nginx:

    
nano /etc/nginx/.htpasswd

Укажите в файле данные в формате имя_пользователя:хэш_пароля:

    
admin:$apr1$9o.mJgYk$43kvlHx0DSqezaAL3yMHe1

Сохраните файл и установите для него права доступа:

    
sudo chmod 640 /etc/nginx/.htpasswd

Задайте владельца и группу:

    
sudo chown root:www-data /etc/nginx/.htpasswd

В rpm-based дистрибутивах группу www-data нужно заменить на nginx.

После этого добавьте директивы auth_basic в конфигурацию Nginx:

    
server { listen 80; server_name service.example.com; location / { proxy_pass http://127.0.0.1:6789; auth_basic "Restricted Content"; auth_basic_user_file /etc/nginx/.htpasswd; proxy_http_version 1.1; 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_buffering off; } }

Проверьте конфигурацию и примените изменения:

    
sudo nginx -t sudo systemctl reload nginx

Ограничение по IP

Чтобы ограничить доступ к сервису по IP-адресам, используйте директивы allow и deny. Пример конфигурации:

    
server { listen 80; server_name service.example.com; location / { allow IP1; allow IP2.0/24; deny all; proxy_pass http://127.0.0.1:6789; proxy_http_version 1.1; 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_buffering off; } }

В этом случае доступ к сервису будет разрешен только с IP-адреса IP1 и из подсети IP2.0/24.

Настройка SSL

Чтобы настроить SSL-сертификат для уже существующего конфига, можно воспользоваться certbot или установить сертификат вручную

Была ли статья полезна?
Ваша оценка очень важна
Пока нет комментариев