Короткий ответ: чтобы использовать NGINX как обратный прокси, укажите управляемый сервер и блок location, направьте запросы к приложению через proxy_pass, задайте доверенные заголовки, проверьте конфигурацию и выполните reload. Проверяйте ответ приложения через NGINX, а не только результат nginx -t или приветственную страницу. Обратный прокси обслуживает входящие запросы к приложению; Socks5.IO относится к отдельному исходящему маршруту приложения.
В этом руководстве создаётся небольшой локальный HTTP-стенд для Ubuntu/Debian-подобной системы. NGINX принимает запросы на 127.0.0.1:8080 и передаёт их демонстрационному приложению на 127.0.0.1:3000. Публичный домен не нужен, существующий сайт не изменяется, открытый прокси наружу не создаётся. Перед публикацией сервиса сначала завершите локальную проверку.
Команды рассчитаны на Linux-сервер и не предназначены для Windows PowerShell. Результаты ниже взяты из тестовых записей исходного материала; при подготовке русской версии команды повторно не запускались.
Как работает обратный прокси NGINX?
NGINX принимает соединение клиента, выбирает виртуальный сервер и location, отправляет запрос выбранному upstream-приложению и возвращает его ответ. Клиенту не нужно знать внутренний порт или адрес бэкенда. Подробности описаны в официальном руководстве NGINX по reverse proxy.
Запрос: клиент -> слушатель NGINX -> бэкенд приложения
Ответ: клиент <- слушатель NGINX <- бэкенд приложения
Стенд из статьи:
curl -> 127.0.0.1:8080, Host proxy-demo.test -> 127.0.0.1:3000

Обратный прокси используют для маршрутизации разных путей, завершения клиентского TLS, распределения запросов между бэкендами и заданной политики кэширования. Эти возможности требуют отдельных настроек: добавление proxy_pass не включает их автоматически. Reverse proxy не устраняет уязвимости приложения, не превращается по умолчанию в WAF и не гарантирует, что исходный сервер нельзя достичь другим разрешённым маршрутом.
Обратный и прямой прокси: в чём разница?
| Вопрос | Обратный прокси NGINX | Исходящий прокси приложения |
|---|---|---|
| Кто подключается первым | Клиент обращается к приложению | Приложение обращается к внешнему источнику |
| Что выбирается | Управляемый вами бэкенд | Поддерживаемый шлюз выхода и разрешённый адрес назначения |
| Кто настраивает | Оператор приложения настраивает NGINX | Сам клиент или приложение настраивает прокси |
| Что доказывает успех | Запрос дошёл до нужного бэкенда через выбранный listener | Конкретный исходящий клиент использовал проверенный маршрут |
Прямой прокси может изменить адрес источника, который видит назначение. Это не означает полной анонимности всего соединения: обратный прокси, сервис выхода и конечный ресурс могут видеть разные части обмена. Сам факт использования прокси не даёт права доступа к данным.
Как настроить обратный прокси NGINX на Ubuntu или Debian
Используйте временный тестовый сервер или согласованный стенд с правами sudo. Ниже предполагается пакетная установка Ubuntu/Debian под управлением systemd, с каталогами /etc/nginx/sites-available и /etc/nginx/sites-enabled. В контейнерах, других дистрибутивах и управляемом хостинге пути и команды могут отличаться.
Не перезаписывайте рабочий сайт. Проверьте, свободны ли локальные порты 3000 и 8080. Если они заняты, выберите другие и одинаково измените все команды и настройки. Примеры ниже предназначены для Bash в Linux.
1. Установите инструменты и проверьте сервис
sudo apt update
sudo apt install nginx python3 curl
nginx -v
sudo nginx -t
sudo systemctl status nginx --no-pager
sudo ss -ltnp '( sport = :3000 or sport = :8080 )'
Инструкции Ubuntu доступны в официальном руководстве по установке NGINX. Установка пакета может автоматически запустить стандартный сервис. На общем сервере сначала оцените влияние на существующие сайты. Если NGINX остановлен, выясните причину и только затем при необходимости выполните sudo systemctl start nginx. Не отключайте firewall и не останавливайте чужой процесс ради прохождения лабораторной проверки.
2. Запустите бэкенд с различимым ответом
В рабочем каталоге обычного пользователя сохраните код под именем proxy_demo_backend.py. Он отдаёт один диагностический endpoint и привязывается только к loopback.
import json
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from urllib.parse import urlsplit
class Handler(BaseHTTPRequestHandler):
protocol_version = "HTTP/1.1"
def do_GET(self):
if urlsplit(self.path).path != "/healthz":
self.send_error(404)
return
payload = {
"backend": "proxy-demo-backend",
"path": self.path,
"host": self.headers.get("Host"),
"x_real_ip": self.headers.get("X-Real-IP"),
"x_forwarded_for": self.headers.get("X-Forwarded-For"),
"x_forwarded_proto": self.headers.get("X-Forwarded-Proto"),
"forwarded": self.headers.get("Forwarded"),
"request_id": self.headers.get("X-Request-ID"),
}
body = json.dumps(payload).encode("utf-8")
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Cache-Control", "no-store")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
pass
if __name__ == "__main__":
ThreadingHTTPServer(("127.0.0.1", 3000), Handler).serve_forever()
В терминале A запустите сервер и оставьте процесс работать:
python3 proxy_demo_backend.py
Опция --fail-with-body доступна в curl 7.76.0 и новее. Проверьте версию командой curl --version; в старой версии замените её на --fail. При такой замене тело HTTP-ошибки не выводится.
В терминале B проверьте бэкенд напрямую:
curl --noproxy '*' --fail-with-body --silent --show-error \\
http://127.0.0.1:3000/healthz
Условие успеха: JSON содержит "backend": "proxy-demo-backend" и "path": "/healthz". При прямом базовом запросе поля forwarding обычно равны null, потому что клиент не передавал их. Этот Python-сервер предназначен для обучения, а не для production и не для проверки реальных зависимостей.
3. Добавьте отдельный тестовый сайт NGINX
Через sudoedit /etc/nginx/sites-available/proxy-demo создайте новый файл. Если имя уже занято, проверьте его содержимое и выберите другое, чтобы ничего не перезаписать. Фрагмент ниже размещается внутри существующего контекста http, а не на верхнем уровне.
# /etc/nginx/sites-available/proxy-demo
# Фрагмент находится внутри существующего контекста http.
log_format proxy_demo '$request_id $remote_addr $request_method $uri '
'status=$status upstream=$upstream_addr '
'upstream_status=$upstream_status '
'upstream_time=$upstream_response_time total=$request_time';
server {
listen 127.0.0.1:8080 default_server;
server_name _;
access_log off;
return 404;
}
server {
listen 127.0.0.1:8080;
server_name proxy-demo.test;
access_log /var/log/nginx/proxy-demo.access.log proxy_demo;
error_log /var/log/nginx/proxy-demo.error.log warn;
add_header X-Request-ID $request_id always;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-ID $request_id;
proxy_set_header Forwarded "";
proxy_connect_timeout 3s;
proxy_read_timeout 15s;
proxy_send_timeout 15s;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
Upstream здесь — локальное приложение, а не шлюз исходящего прокси. В простой location-структуре форма proxy_pass без URI сохраняет входящий путь. Сервер по умолчанию отклоняет неизвестные Host на выделенном loopback-listener и не меняет другие сайты.

Явный HTTP/1.1 не позволяет зависеть от значения по умолчанию конкретной версии. Таймауты выбраны для стенда: proxy_read_timeout и proxy_send_timeout ограничивают паузы между операциями, а не общий срок выполнения приложения. Перед изменением проверьте справочник модуля NGINX proxy.
4. Включите сайт, проверьте конфигурацию и выполните reload
Сначала убедитесь, что в sites-enabled нет файла или ссылки с таким именем:
sudo ln -s /etc/nginx/sites-available/proxy-demo /etc/nginx/sites-enabled/proxy-demo
sudo nginx -t
Не повторяйте команду создания ссылки и не используйте принудительную перезапись. Если тест конфигурации завершился ошибкой, исправьте её до следующего шага. Успешный nginx -t подтверждает загрузку конфигурации, но не живое соединение с бэкендом.
sudo systemctl reload nginx
sudo systemctl status nginx --no-pager
Для работающего сервиса обычно достаточно reload, а не restart. Подробности есть в руководстве NGINX для начинающих.

Как проверить работу обратного прокси NGINX
Проверяйте маршрут по слоям: прямое соединение с бэкендом, выбранный listener NGINX, содержимое ответа и связанные записи логов. Один только nginx -t не показывает, дошёл ли запрос до приложения.
Проверьте бэкенд через настроенный виртуальный хост
curl --noproxy '*' --fail-with-body --silent --show-error --include \\
--resolve proxy-demo.test:8080:127.0.0.1 \\
http://proxy-demo.test:8080/healthz
Опция --resolve задаёт адрес только для этого запроса, не меняя DNS и hosts-файл. --noproxy исключает случайный внешний forward proxy из локальной проверки.
Условия успеха:
- HTTP-статус 200, а в теле есть
proxy-demo-backend. pathравен/healthz,host—proxy-demo.test, аx_forwarded_protoв этом HTTP-стенде равенhttp.x_real_ipиx_forwarded_forпоказывают фактический loopback-адрес клиента, а не произвольное значение из заголовка посетителя.X-Request-IDв ответе совпадает сrequest_idв JSON бэкенда и выделенной access-записью.
В конфигурации Host задаётся через $host, поэтому порт клиента не сохраняется. Если приложение формирует абсолютные URL, отдельно задайте политику канонического host/port.

Проверьте границу доверия forwarding-заголовков
Повторите запрос с намеренно поддельными входящими заголовками:
curl --noproxy '*' --fail-with-body --silent --show-error \\
--resolve proxy-demo.test:8080:127.0.0.1 \\
-H 'X-Forwarded-For: 198.51.100.77' \\
-H 'X-Real-IP: 198.51.100.77' \\
-H 'X-Forwarded-Proto: https' \\
-H 'Forwarded: for=198.51.100.77;proto=https' \\
http://proxy-demo.test:8080/healthz
Условие успеха: бэкенд по-прежнему получает loopback-адрес клиента и http, а forwarded равен null. В реальном приложении доверяйте только тем proxy-hop и заголовкам, которыми вы управляете: эти поля не являются учётными данными.

Если перед NGINX есть доверенный CDN или балансировщик, настройте доверенные диапазоны и заголовок через модуль real-IP, где он доступен. Не доверяйте всем адресам из интернета право объявлять собственную идентичность.
Проверьте логи и безопасно воспроизведите ошибку
sudo tail -n 20 /var/log/nginx/proxy-demo.access.log
sudo tail -n 20 /var/log/nginx/proxy-demo.error.log
Access-лог содержит upstream-адрес, статусы и время ответа. Ограничьте доступ и срок хранения: пути, адреса и error-лог могут содержать чувствительные сведения, поэтому перед публикацией маскируйте их.

Только в этом стенде остановите демонстрационный бэкенд через Ctrl+C и повторите curl-запрос. При отсутствии upstream ожидается 502 и ошибка соединения в логе. Запустите python3 proxy_demo_backend.py снова и убедитесь, что возвращается 200. Не останавливайте production-приложение ради эксперимента.

Проверка неизвестного Host должна вернуть 404 и не передать запрос приложению:
curl --noproxy '*' --silent --show-error --include \\
-H 'Host: other.example' http://127.0.0.1:8080/healthz
Этот тест проверяет маршрутизацию Host на локальном listener, но не TLS и не публичную доступность. curl -I отправляет HEAD, а маленькое учебное приложение реализует GET; не принимайте неподдержанный HEAD за поломку reverse proxy.
Диапазон исходной проверки: в предоставленном материале указаны 12 локальных проверок с официальной portable-версией NGINX 1.31.8 на Windows и отдельной top-level-конфигурацией, которая подключает тот же фрагмент. Проверялись ответы, замена заголовков, отклонение Host, связь request ID с логом, префиксы пути и восстановление после 502. Ubuntu-пакеты, systemd, публичные DNS/TLS/firewall и реальный маршрут Socks5.IO этой loopback-проверкой не подтверждены.
Проверьте преобразование пути proxy_pass перед добавлением /api/
Для входящего /api/healthz?check=1 завершающий URI в proxy_pass меняет путь бэкенда:
| Location и upstream | Путь, который получает бэкенд |
|---|---|
location /api/, proxy_pass http://127.0.0.1:3000; |
/api/healthz?check=1 |
location /api/, proxy_pass http://127.0.0.1:3000/; |
/healthz?check=1 |
Это два альтернативных примера, а не инструкция вставлять одинаковые location одновременно. В тестовой ветке добавьте один вариант, сохраните политику заголовков, проверьте и перезагрузите NGINX. При удалении префикса запрос достигнет /healthz; при его сохранении учебный бэкенд вернёт 404.

Перед публикацией: HTTPS, origin и особый трафик
Loopback-стенд не является публичным HTTPS-развёртыванием. Перед публикацией приложения:
- Создайте согласованный публичный virtual host с реальным доменом и намеренно выбранными listener. Тестовый loopback-сайт оставьте отдельно или удалите после проверки.
- Получите действующий сертификат и приватный ключ по утверждённой процедуре. Настройте клиентский TLS и проверьте его; не отключайте проверку сертификата.
- Оставьте бэкенд на loopback, если он работает на том же хосте, либо ограничьте его частный listener маршрутом прокси. В контейнере
127.0.0.1указывает на этот контейнер. - Защитите upstream-соединение через недоверенную сеть: задайте имя TLS-сервера, проверку сертификата и доверенный CA bundle. Публичный HTTPS не шифрует автоматически HTTP-соединение к бэкенду. См. руководство NGINX по защите upstream-трафика.
- Отдельно настройте доверенные proxy, аутентификацию, загрузки и таймауты фреймворка. Проверяйте redirect, Secure Cookie, тело запроса и публичные пути, а не только
/healthz.
Для WebSocket явно обработайте Upgrade-заголовки и проверьте настоящее обновление соединения; см. документацию NGINX по WebSocket. Для streaming/SSE может понадобиться отдельная политика буферизации. Кэширование в этом стенде отключено: не применяйте общий кэш к авторизованным или персонализированным ответам.
В upstream-группу балансировки добавляют endpoints приложений. Состояние сессий и отказоустойчивость проектируются отдельно; добавление второго адреса само по себе не создаёт высокую доступность. Не добавляйте residential proxy-узлы в upstream приложения как будто это его взаимозаменяемые серверы.
Может ли NGINX использовать Socks5.IO для исходящих запросов?
Разделяйте компоненты по направлению трафика:
Входящий: клиент -> reverse proxy NGINX -> ваше приложение
Исходящий: приложение -> совместимый forward proxy Socks5.IO -> разрешённый внешний источник
Обычный HTTP proxy_pass не является SOCKS5-клиентом. Указание коммерческого HTTP-прокси также не добавляет автоматически формат forward-запроса или HTTPS CONNECT. Upstream-группа не выполняет преобразование протоколов. proxy_bind выбирает локальный адрес источника и не выдаёт удалённый residential IP.
Исходящий прокси обычно задаётся в HTTP/browser-клиенте приложения либо в специально спроектированном компоненте выхода. Возможности NGINX зависят от продукта и модулей; эта лаборатория не подтверждает универсальную совместимость с любым внешним прокси.
Для разрешённой интеграции, которой нужен исходящий трафик через резидентные IP, в клиентском компоненте можно рассмотреть динамические резидентные прокси Socks5.IO. Актуальные адреса подключения, протокол и параметры сессии проверяйте в аккаунте. Не помещайте секреты прокси в публичную конфигурацию NGINX или диагностический ответ.
Выбирайте протокол с учётом возможностей клиента. Подробнее — в руководстве «SOCKS5 или HTTP: чем отличаются прокси и какой выбрать». Маркировка SOCKS5 не превращает любой браузер или reverse proxy в аутентифицированный SOCKS-клиент. Проверяйте исходящий маршрут из самого приложения и отдельно подтверждайте разрешённый адрес назначения.
Например, внутренний API отчётности может принимать входящие запросы через NGINX, а фоновый worker — обращаться к разрешённому внешнему товарному фиду через отдельный выход. Успешный /healthz доказывает только входящий маршрут и ничего не говорит об IP worker. Это архитектурный пример, а не клиентский бенчмарк Socks5.IO.
Устранение неполадок: 502, 504, неверная страница и IP клиента
При ошибке проверяйте клиент, listener NGINX и upstream-бэкенд по отдельности: настройки, ответ и логи. Правила сети меняйте только после установления причины.
| Симптом | Что проверить сначала | Чего избегать |
|---|---|---|
Ошибка nginx -t |
Файл и строку ошибки, контекст, дублирующий listener, синтаксис и права | Делать reload при ошибке или публиковать вывод nginx -T с секретами |
502 Bad Gateway |
Listener бэкенда, протокол upstream, отказ соединения и error-лог | Считать каждый 502 блокировкой firewall |
504 Gateway Timeout |
Хоп с таймаутом, задержку бэкенда и нужный timeout | Увеличивать все таймауты без диагностики |
| Приветственная страница или неожиданный 200 | Адрес, Host, выбранный listener и тело ответа | Считать любой 200 доказательством правильного маршрута |
/api/ возвращает 404 |
Сохранение или удаление префикса и маршрут приложения | Менять слэши наугад |
| Приложение видит адрес NGINX | Политику доверенных прокси/заголовков и прямую доступность бэкенда | Доверять произвольному X-Forwarded-For посетителя |
| Цикл redirect или неверная схема | Хопы TLS, доверенную схему и canonical URL приложения | Безусловно доверять X-Forwarded-Proto клиента |
| Публичный запрос не работает, локальный работает | DNS, выбранный IP/listener, согласованные firewall/security-group и TLS | Отключать firewall или публиковать порт 3000 |
Один timeout не доказывает блокировку firewall. Тестируйте каждый хоп и проверяйте правила до их изменения. В этом стенде публичное правило UFW не нужно: оба listener работают на loopback. Порты 80/443 проверяются отдельно, не блокируя SSH.
Итог: проверяйте входящий и исходящий маршруты отдельно
При использовании NGINX как reverse proxy отдельно проектируйте выбор listener, маршрутизацию к upstream и доверие приложения к заголовкам. Создайте различимый бэкенд, проверьте конфигурацию, безопасно выполните reload, а затем сопоставьте реальный ответ с логами. HTTPS, специальные протоколы и эксплуатационные ограничения добавляйте только после определения критериев успеха.
Исходящий прокси настраивается отдельно. Socks5.IO может быть вариантом для разрешённых исходящих соединений совместимого приложения, но не заменяет бэкенд. Успешная проверка reverse proxy не подтверждает внешний маршрут приложения.






