Вы развернули панель 3x UI на внутреннем порту и хотите предоставить к ней безопасный доступ извне. Прямой проброс порта панели наружу - плохая практика: вы теряете централизованный контроль над трафиком, не можете гибко управлять шифрованием и оставляете поверхность для атак открытой. Nginx в роли обратного прокси решает эти задачи: он принимает клиентские соединения по HTTPS и прозрачно передаёт трафик на бэкенд 3x UI. В этой инструкции приведён готовый конфиг Nginx с поддержкой WebSocket, корректной передачей URI и SSL от Let's Encrypt, а также проверками, важными для запуска в production.
Что получится. Панель будет открываться по адресу https://panel.example.com, а 3x UI останется доступной Nginx локально по адресу 127.0.0.1:PANEL_PORT. Для доступа к панели извне потребуются порты 80 и 443; фактический порт панели не следует открывать в файрволе. В примерах 54321 - это значение PANEL_PORT, которое нужно заменить на порт вашей установки.
Проверено на. Ubuntu 24.04 LTS, Nginx 1.26.x и 3x-ui 2.6.x, установленной штатным install-скриптом проекта; дата проверки - август 2026. Для другой версии 3x-ui перед применением конфигурации проверьте фактический порт, адрес прослушивания и параметры запуска панели.
Содержание
- Зачем нужен обратный прокси для 3x UI
- Предварительные требования и исходные данные
- Базовая конфигурация обратного прокси
- Настройка поддержки WebSocket
- Обеспечение безопасного доступа через HTTPS
- Финальная конфигурация Nginx для 3x UI
- Тестирование и устранение неполадок
- Дополнительные рекомендации по безопасности
- Частые вопросы (FAQ)
Зачем нужен обратный прокси для 3x UI
Обратный прокси - это прослойка между клиентом и сервером приложения. Когда вы настраиваете Nginx перед 3x UI, вы получаете три ключевых преимущества. Первое: SSL-терминация. Nginx обрабатывает HTTPS, разгружая панель от криптографических операций. Вы можете использовать один сертификат Let's Encrypt для десятка сервисов за прокси. Второе: унификация точки входа. Все запросы приходят на 80 и 443 порты одного IP-адреса, а Nginx маршрутизирует их по разным бэкендам на основе доменного имени. Это критично, когда на сервере крутятся несколько веб-приложений. Третье: безопасность. Если Nginx и панель работают на одном сервере, 3x UI рекомендуется привязать к 127.0.0.1:PANEL_PORT. Порт 54321 не является универсальным: это только распространённый пример. При локальной привязке панель недоступна из внешней сети, а запросы проходят через Nginx, где можно настроить rate limiting, фильтрацию по IP и fail2ban.
Типичный сценарий: у вас один VPS с публичным IP, на нём развёрнуты 3x UI, Zabbix и пара внутренних сервисов. Без прокси вам пришлось бы открывать три разных порта и настраивать SSL для каждого. С Nginx вы открываете только 443 порт для веб-доступа, а маршрутизация идёт по доменным именам - panel.example.com, zabbix.example.com. О том, как построить такую инфраструктуру с нуля, читайте в полном руководстве по настройке Nginx Reverse Proxy.
Предварительные требования и исходные данные
Перед началом настройки убедитесь, что у вас есть всё перечисленное ниже. Отсутствие любого пункта приведёт к ошибке на одном из этапов.
- Сервер с Linux. Подойдёт Ubuntu 22.04/24.04 LTS, Debian 12 или RHEL 9. Все команды в статье приведены для Debian-семейства.
- Установленный Nginx. Версия не ниже 1.24. Проверить:
nginx -v. Если Nginx не установлен -apt update && apt install nginx -y. - Работающая панель 3x UI. Панель должна быть доступна локально. Определите
PANEL_PORTпо параметрам запуска или конфигурации вашей установки 3x-ui либо по слушающему сокету:sudo ss -ltnp | grep -E 'x-ui|3x-ui'. Если имя процесса не выводится, изучите полный выводsudo ss -ltnpи сопоставьте порт со службой панели. Для примера с портом 54321 выполнитеcurl -I http://127.0.0.1:54321. Коды 200, 301, 302 или 401 означают, что HTTP-бэкенд ответил; 301/302 возможны при перенаправлении, а 401 - при требовании авторизации. - Доменное имя. A-запись должна указывать на публичный IP вашего сервера. Если опубликована AAAA-запись, сервер и файрвол также должны принимать IPv6-трафик. Для тестов можно использовать
/etc/hostsна клиентской машине, но для Let's Encrypt нужен реальный DNS. - Права root или sudo. Конфигурация Nginx и запуск certbot требуют привилегий.
Чек-лист готовности:
- ☐ Nginx установлен и запущен (
systemctl status nginx) - ☐ Известны фактические адрес и
PANEL_PORTпанели 3x UI - ☐ Панель отвечает локально по адресу
http://127.0.0.1:PANEL_PORT - ☐ A-запись домена указывает на IP сервера, а AAAA-запись проверена или отсутствует
- ☐ Порт 80 и 443 открыты в файрволе
- ☐ Есть доступ по SSH с правами root или sudo
Во всех фрагментах ниже используется тестовый стенд: Ubuntu 24.04, Nginx 1.26, панель 3x UI на порту 54321, домен panel.example.com. Значение 54321 в proxy_pass заменяйте на ваш PANEL_PORT.
Базовая конфигурация обратного прокси
Начнём с минимальной рабочей конфигурации. Она перенаправляет HTTP-запросы с Nginx на локальный порт панели 3x UI. Создайте файл /etc/nginx/sites-available/3x-ui:
server {
listen 80;
server_name panel.example.com;
location / {
proxy_pass http://127.0.0.1:54321;
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:
ln -s /etc/nginx/sites-available/3x-ui /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
Разберём директивы. proxy_pass http://127.0.0.1:54321; - точка назначения трафика. Nginx принимает запрос на 80 порту и транслирует его на локальный адрес панели. В рабочей конфигурации замените 54321 на фактический PANEL_PORT. Четыре заголовка proxy_set_header критичны: Host передаёт оригинальное доменное имя, чтобы панель знала, куда клиент обращался; X-Real-IP содержит IP клиента; X-Forwarded-For - цепочку прокси-серверов; X-Forwarded-Proto сообщает бэкенду, по какому протоколу пришёл запрос (http или https). Без этих заголовков панель 3x UI будет видеть все соединения как пришедшие с 127.0.0.1, что может исказить логирование и работу некоторых функций.
Корректная передача URI и заголовков
Поведение proxy_pass зависит от наличия завершающего слеша в URI. Это частая причина ошибок 404 после настройки прокси. Рассмотрим два варианта:
proxy_pass http://127.0.0.1:54321;- Nginx передаёт URI без изменений. Запрос к/panel/inboundsуйдёт как/panel/inbounds.proxy_pass http://127.0.0.1:54321/;- Nginx заменяет часть location на слеш. Если location/app/, а запрос пришёл на/app/inbounds, бэкенд получит/inbounds.
Если панель 3x UI должна работать в корне домена, используйте вариант без завершающего слеша. Панель ожидает полные пути, и обрезание URI приведёт к битым ссылкам на статические ресурсы и API-эндпоинты. Дополнительно убедитесь, что заголовок X-Forwarded-Proto передаётся - панель может использовать его для формирования абсолютных URL в ответах API.
Базовый URL и path prefix
Конфигурация из статьи предполагает публикацию панели в корне домена: https://panel.example.com/. Если 3x UI настроена на path prefix, например /app/, настройте этот базовый URL и маршруты в самой панели, а затем согласуйте с ними location и proxy_pass. Один только rewrite в Nginx не гарантирует корректную работу статических файлов, API и ссылок, которые приложение формирует с учётом своего базового пути.
Настройка поддержки WebSocket
Интерфейс 3x UI может использовать WebSocket-соединения для мониторинга в реальном времени: графиков трафика, статуса подключений и логов. Без специальной настройки Nginx эти соединения могут обрываться или не устанавливаться. Прокси по умолчанию работает с HTTP/1.0, а WebSocket требует HTTP/1.1 и явного апгрейда соединения.
Сначала добавьте map в секцию http файла /etc/nginx/nginx.conf. На Debian-подобных системах его также можно поместить в отдельный файл в /etc/nginx/conf.d/, если этот каталог подключается внутри секции http. Не размещайте map внутри server или location:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
Затем добавьте в блок location / директивы для WebSocket:
location / {
proxy_pass http://127.0.0.1:54321;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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_http_version 1.1 включает HTTP/1.1 для соединения с бэкендом. proxy_set_header Upgrade $http_upgrade пробрасывает заголовок апгрейда от клиента. Переменная $connection_upgrade из блока map передаёт Connection: upgrade только при запросе с заголовком Upgrade; для обычного HTTP-запроса она передаёт close. Такой вариант безопаснее, чем постоянная отправка Connection: upgrade для всех запросов.
HTTP/2 на внешнем соединении с браузером не требуется для работы WebSocket: критична настройка HTTP/1.1 между Nginx и бэкендом. Проверка работы WebSocket описана в разделе «Тестирование и устранение неполадок».
Обеспечение безопасного доступа через HTTPS
Панель 3x UI передаёт учётные данные и управляет VPN-подключениями. Передача этой информации по открытому HTTP недопустима. Let's Encrypt предоставляет бесплатные SSL-сертификаты; выпуск и обновление сертификата нужно проверить отдельно от настройки обратного прокси.
Установка и настройка Certbot
Установите certbot и плагин для Nginx. На Ubuntu 24.04 это делается одной командой:
apt update && apt install certbot python3-certbot-nginx -y
Перед выпуском сертификата проверьте, что домен резолвится в IP сервера и HTTP-01 challenge сможет дойти до этого экземпляра Nginx:
dig +short A panel.example.com
dig +short AAAA panel.example.com
Порт 80 должен быть доступен из интернета. Если перед сервером используется CDN, другой reverse proxy или балансировщик, он должен передавать запросы к /.well-known/acme-challenge/ на этот сервер. Опубликованная AAAA-запись также должна вести на доступный по IPv6 сервер; иначе проверка Let's Encrypt может завершиться ошибкой.
Если HTTP server-блок уже существует. Убедитесь, что базовая конфигурация из предыдущего раздела активна и server_name содержит ваш домен, затем запустите мастер:
certbot --nginx -d panel.example.com
Certbot найдёт блок server с соответствующим server_name и предложит включить редирект с HTTP на HTTPS. Выберите вариант с редиректом, если панель не должна быть доступна по HTTP.
Если это первичный выпуск и server-блока ещё нет. Сначала создайте и включите минимальный HTTP server-блок из раздела «Базовая конфигурация обратного прокси», проверьте его командой nginx -t и только затем запускайте certbot --nginx. Режим --standalone требует свободного порта 80, поэтому не используйте его одновременно с работающим Nginx без отдельного плана переключения.
Автоматическое обновление сертификата
Сертификаты Let's Encrypt действительны 90 дней. В распространённых пакетах certbot обычно устанавливается systemd-таймер, но его наличие и успешные запуски нужно подтвердить:
systemctl list-timers | grep certbot
systemctl status certbot.timer
journalctl -u certbot.service -n 100 --no-pager
Для тестового запуска обновления выполните:
certbot renew --dry-run
Успешный тест подтверждает, что правила обновления и проверка домена работают. Перезагрузка Nginx после фактического обновления зависит от использованного плагина certbot или настроенного deploy-hook; не следует считать её гарантированной без проверки. Если плагин не перезагружает Nginx, настройте deploy-hook с командой systemctl reload nginx в каталоге /etc/letsencrypt/renewal-hooks/deploy/ и проверьте журналы после первого обновления.
Финальная конфигурация Nginx для 3x UI
Ниже - полный конфигурационный файл, объединяющий HTTP-редирект, HTTPS с сертификатами Let's Encrypt, проксирование с заголовками и поддержку WebSocket. До его применения добавьте блок map из раздела WebSocket в секцию http. Скопируйте конфигурацию в /etc/nginx/sites-available/3x-ui, замените panel.example.com и 54321 на свои значения, затем выполните nginx -t && systemctl reload nginx.
# Редирект с HTTP на HTTPS
server {
listen 80;
server_name panel.example.com;
return 301 https://$host$request_uri;
}
# Основной HTTPS-сервер
server {
listen 443 ssl;
# Необязательно для Nginx 1.25.1 и новее:
# http2 on;
server_name panel.example.com;
# Сертификаты Let's Encrypt
ssl_certificate /etc/letsencrypt/live/panel.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/panel.example.com/privkey.pem;
# Безопасные параметры SSL
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;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
# Проксирование на 3x UI
location / {
proxy_pass http://127.0.0.1:54321;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
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;
# Нужны, только если proxy_cache включён выше по конфигурации
proxy_cache_bypass $http_upgrade;
proxy_no_cache $http_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
Директива http2 on; необязательна и не влияет на WebSocket 3x-ui. Для Nginx 1.24 не добавляйте её без проверки документации пакета: синтаксис включения HTTP/2 зависит от версии. proxy_buffering off полезна для потоковых данных и обновлений в реальном времени, но увеличивает число незабуференных соединений, поэтому не включайте её глобально без необходимости. proxy_cache_bypass и proxy_no_cache имеют смысл, если кеширование задано в родительском контексте: они исключают запросы с Upgrade из кеша.
proxy_read_timeout отсчитывается между последовательными операциями чтения от бэкенда, а не задаёт гарантированную продолжительность соединения. Значение 3600s - разумная отправная точка для долгоживущих соединений. Для действительно длительных WebSocket-сессий приложение должно отправлять ping или другие keepalive-сообщения; повышайте таймауты только после оценки нагрузки и поведения панели. proxy_send_timeout также ограничивает паузу между операциями отправки данных бэкенду.
Блок ssl_protocols и ssl_ciphers задаёт современный набор шифров для TLS 1.2. Набор шифров TLS 1.3 управляется Nginx и используемой криптобиблиотекой отдельно. Подробнее о выборе шифров и настройке TLS читайте в статье Nginx HTTPS в 2026 году: TLS 1.3, Let's Encrypt и безопасная конфигурация.
Тестирование и устранение неполадок
После применения конфигурации проведите серию проверок. Они выявят проблемы до того, как с ними столкнутся пользователи.
Проверка конфигурации и HTTPS. Сначала убедитесь, что Nginx принял конфигурацию, затем проверьте TLS-рукопожатие и ответ панели:
nginx -t
systemctl reload nginx
curl -vk https://panel.example.com/
Ключ -k в curl -vk нужен только для диагностики и позволяет увидеть ответ даже при проблеме с доверием к сертификату. После исправления сертификата повторите проверку без -k. В браузере по адресу https://panel.example.com должна открыться страница входа в 3x UI. Если страница не открывается, проверьте фактический адрес и порт панели, например для тестового стенда: ss -tlnp | grep 54321.
Проверка редиректа. Перейдите по http://panel.example.com. Вас должно автоматически перенаправить на HTTPS-версию. Код ответа - 301 Moved Permanently.
Проверка DNS, IPv6 и файрвола. Сверьте A- и AAAA-записи с адресами сервера командами dig +short A panel.example.com и dig +short AAAA panel.example.com. Если AAAA-запись существует, но Nginx или файрвол не обслуживают IPv6, удалите неверную запись либо настройте IPv6. Проверьте локальные правила через sudo ufw status или sudo nft list ruleset, а также security group у VPS-провайдера. Для панели должны быть доступны 80 и 443, но не PANEL_PORT из внешней сети.
Проверка работы WebSocket
Откройте инструменты разработчика в браузере (F12), перейдите на вкладку Network и выберите фильтр WS. Обновите страницу панели 3x UI. В списке должны появиться соединения со статусом 101 Switching Protocols. Это подтверждает, что апгрейд до WebSocket прошёл успешно. Если вы видите статус 200, убедитесь, что запрос действительно является WebSocket-запросом, затем проверьте proxy_http_version 1.1, proxy_set_header Upgrade, proxy_set_header Connection $connection_upgrade и блок map в секции http.
Типовые ошибки и их причины. Ниже — таблица с самыми частыми проблемами при настройке прокси для 3x UI:
| Ошибка | Причина | Решение |
|---|---|---|
| 502 Bad Gateway | Nginx не может достучаться до бэкенда. Панель 3x UI не запущена, слушает на другом адресе или порту. | Проверьте статус панели и соответствие адреса с портом в proxy_pass: sudo ss -ltnp. Значение 127.0.0.1:PANEL_PORT должно совпадать с настройкой панели. |
| 504 Gateway Timeout | Бэкенд зависает, не отвечает или соединение остаётся без данных дольше proxy_read_timeout. |
Проверьте журналы панели и Nginx. Для долгоживущих WebSocket-соединений настройте ping/keepalive в приложении и подберите proxy_read_timeout по фактической нагрузке. |
| NET::ERR_CERT_AUTHORITY_INVALID | Сертификат не был выпущен для этого домена, истёк или клиент получает другой сертификат через CDN либо прокси. | Запустите certbot certificates, проверьте DNS и цепочку прокси, затем перевыпустите сертификат при необходимости. |
| WebSocket не подключается (статус 200 вместо 101) | Отсутствуют директивы WebSocket, блок map размещён не в секции http либо запрос не достигает WebSocket-эндпоинта. |
Добавьте map в http и все директивы WebSocket в location, затем проверьте конфигурацию командой nginx -t. |
Логи Nginx - основной инструмент отладки. Начните с системного журнала и стандартного error.log:
journalctl -u nginx -n 100 --no-pager
tail -n 100 /var/log/nginx/error.log
Записи о upstream prematurely closed connection указывают на падение или преждевременное закрытие бэкенда. SSL_do_handshake() failed сигнализирует о проблемах с сертификатом или TLS. При необходимости включите подробное логирование для проблемного location; уровень debug доступен только в сборках Nginx с поддержкой отладки:
error_log /var/log/nginx/3x-ui-error.log debug;
Дополнительные рекомендации по безопасности
Базовая конфигурация закрывает основные риски. Следующие меры усилят защиту и характерны для production-окружений.
Ограничение доступа по IP. Если панель 3x UI используется только из офиса или через VPN, заблокируйте все остальные адреса. Добавьте в блок location:
allow 203.0.113.0/24; # IP офисной сети
allow 198.51.100.5; # IP администратора
deny all;
Nginx проверит IP до передачи запроса бэкенду. Неавторизованные адреса получат 403 Forbidden.
Скрытие версии Nginx. В главном конфигурационном файле /etc/nginx/nginx.conf добавьте в секцию http: server_tokens off;. Это уберёт версию Nginx из заголовков ответа и страниц ошибок, усложняя fingerprinting.
Интеграция с fail2ban. Настройте фильтр для отслеживания неудачных попыток входа в 3x UI через логи Nginx. При превышении порога fail2ban заблокирует IP на уровне iptables. Это дополнит встроенные механизмы защиты панели и снизит эффект от перебора паролей.
Нестандартный порт SSH. Смените порт SSH с 22 на другой, если сервер доступен из интернета. Это не относится напрямую к Nginx, но снижает количество автоматических атак на сервер в целом.
Готовые конфигурации Nginx для типовых задач - проксирования, балансировки, кеширования - собраны в материале рабочие конфигурации Nginx для стандартных задач 2026. Если вы проксируете несколько сервисов и нужна интеллектуальная маршрутизация по доменам или геолокации, изучите руководство по интеллектуальной маршрутизации в Nginx.
Частые вопросы (FAQ)
Почему не работает WebSocket после настройки прокси?
Проверьте, что в блоке location / есть proxy_http_version 1.1, proxy_set_header Upgrade $http_upgrade и proxy_set_header Connection $connection_upgrade. Также убедитесь, что блок map для $connection_upgrade расположен в секции http, а не внутри server или location. Для долгоживущих соединений начните с proxy_read_timeout 3600s и настройте ping/keepalive на стороне приложения.
Как обновить сертификат Let's Encrypt вручную?
Выполните команду certbot renew. Если хотите проверить механизм без реального обновления - используйте certbot renew --dry-run. После успешного обновления проверьте, был ли Nginx перезагружен плагином или deploy-hook, через journalctl -u nginx -n 100 --no-pager. При отсутствии перезагрузки настройте deploy-hook с командой systemctl reload nginx.
Что делать, если панель 3x UI доступна локально, но через Nginx отдаёт 502?
Проверьте, на каком адресе и порту слушает панель. Если она привязана к 127.0.0.1, а в proxy_pass указан другой адрес или порт, Nginx не сможет подключиться. Выполните sudo ss -ltnp и убедитесь, что адрес и PANEL_PORT совпадают с конфигурацией. Если панель слушает только ::1, используйте соответствующий IPv6-адрес в proxy_pass либо измените привязку панели.
Как узнать фактический порт и адрес прослушивания 3x-ui?
Сначала проверьте параметры запуска или конфигурацию вашей установки 3x-ui. Затем подтвердите результат на сервере: sudo ss -ltnp | grep -E 'x-ui|3x-ui'. Если имя процесса не отображается, используйте sudo ss -ltnp и сопоставьте слушающий сокет со службой панели. В proxy_pass должны быть указаны тот же IP-адрес и порт.
Можно ли оставить панель доступной только через localhost?
Да. Если Nginx и 3x UI работают на одном сервере, привязка панели к 127.0.0.1:PANEL_PORT предпочтительна: панель не будет доступна напрямую из внешней сети, а Nginx подключится к ней локально. Не открывайте PANEL_PORT в файрволе. Если Nginx расположен на другом хосте, localhost использовать нельзя: потребуется защищённая внутренняя сеть и ограничения доступа по IP.
Можно ли использовать один сертификат для нескольких доменов?
Да, Let's Encrypt поддерживает мультидоменные сертификаты. При запуске certbot укажите все домены через -d: certbot --nginx -d panel.example.com -d zabbix.example.com. Сертификат будет выпущен для всех перечисленных доменов.
Вы настроили обратный прокси Nginx для 3x UI с поддержкой WebSocket и HTTPS. Панель доступна по защищённому соединению, а её порт не публикуется напрямую. После первого выпуска сертификата проверьте таймер certbot, deploy-hook и журналы Nginx, чтобы убедиться в корректном обновлении SSL.