3x‑ui в 2026: xHTTP за nginx, WARP и мониторинг, который реально работает
Поднял сервер, раздал людям ключи — и началось. Один говорит «не работает», другой на том же провайдере, в том же городе — подключается нормально. Третий работает дома, но не с телефона. Знакомо?
Я разбирался с этим достаточно долго. В статье — конкретная схема, которая у меня работает, с объяснением, почему именно так, и с граблями, на которые я наступил.
Статья не для тех, кто только начинает. Предполагается, что 3x‑ui уже стоит, пользователи есть, и хочется, чтобы работало стабильно, а не «вроде ок».
Почему у двух людей на одном провайдере разный результат
ТСПУ давно работает не по сигнатурам, а по поведению трафика. Блокировка сейчас выглядит не как «сайт недоступен» — выглядит как деградация скорости до 200–300 Кбит/с. Пользователь думает, что сервер лёг. На самом деле, сессию просто зашейпили.
Почему разный результат у разных людей — потому что шейпинг разворачивается неравномерно по узлам сети оператора. Одна точка присутствия провайдера уже получила обновление правил, другая — ещё нет. Один тарифный план идёт через один пул оборудования, другой — через другой. Отсюда и расхождения.
Практический вывод один: не надо искать один идеальный транспорт. Надо держать несколько инбаундов, чтобы клиент мог переключиться.
Схема которую я использую
Клиент
│
├ VLESS + REALITY (порт 8443) ─ ► Xray напрямую
│ (nginx не участвует)
│
└ HTTPS 443 ─ ► nginx
│
├─ /ws-[случайный суффикс] ─ ► Xray WS (порт 8002, 127.0.0.1)
└─ /xh-[случайный суффикс] ─ ► Xray xHTTP (порт 8001, 127.0.0.1)
Три инбаунда — три разных сценария.
REALITY — TLS клиент видит как реальный трастовый сайт. Максимальная маскировка, DPI технически не может отличить от легитимного трафика. Но чувствителен к конфигурации: неправильный dest, несовпадение fingerprint — и блокируется быстрее остальных. Требует чистого IP без плохой репутации.
WebSocket — оставил для совместимости. Часть клиентских приложений старых версий работает только с ним, плюс некоторые iOS‑конфигурации.
xHTTP — основной рабочий транспорт. Это не SplitHTTP, путаница частая — разные транспорты. xHTTP работает поверх HTTP/2, создаёт внутри него мультиплексированные подпотоки. DPI видит обычный HTTPS к вашему домену.
Оба WS и xHTTP слушают на 127.0.0.1, наружу не торчат — снаружи только nginx.
nginx
Два момента, которые я выяснил опытным путём.
Для xHTTP обязательно нужны proxy_buffering off и proxy_read_timeout 5d. Без первого nginx буферизует тело запроса — xHTTP это не переживает, соединение рвётся. Без второго nginx закрывает соединение по таймауту раньше, чем надо.
location / возвращает 404 — чтобы сканеры не видели ничего полезного на корне.
server {
listen 80;
server_name your.domain.example;
return 301 https://$host$request\_uri;
}
server {
listen 443 ssl http2;
server_name your.domain.example;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location /ws-ваш-путь {
proxy_pass http://127.0.0.1:8002;
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_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /xh-ваш-путь {
proxy_pass http://127.0.0.1:8001;
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;
proxy_read_timeout 5d;
}
location / {
return 404;
}
}
Грабли с xHTTP и flow
Это стоило мне нескольких часов. В 3x‑ui при создании xHTTP‑инбаунда поле flow надо оставить пустым.
xtls-rprx-vision (Vision Flow) требует прямого TLS‑соединения клиента с Xray. В нашей схеме TLS заканчивается на nginx, дальше идёт plain HTTP до Xray на 127.0.0.1. Vision в такой схеме не работает.
Симптом коварный: клиент подключается, nginx показывает 200 OK в логах, трафик идёт, но соединение обрывается через 10–15 секунд. Убираешь flow — всё работает.
Параметры xHTTP‑инбаунда в 3x‑ui:
Параметр | Значение |
|---|---|
Протокол | VLESS |
Listen | 127.0.0.1 |
Network | xhttp |
Mode | packet‑up |
Security | none |
Flow | пусто |
packet-up выбрал потому, что он лучше работает в нестандартных условиях — CDN, провайдеры с частичной поддержкой HTTP/2. stream-up быстрее, но требует полноценного H2 на всём пути.
WARP в исходящих
ChatGPT и часть других сервисов режут IP дата‑центров на уровне сети — смена протокола тут не поможет никак, проблема не в протоколе.
В 3x‑ui это решается прямо из панели: в разделе «Исходящие» есть тип WARP. Никакого wgcf, никакой ручной настройки WireGuard — создаётся в несколько кликов. WARP даёт IP близкий к геолокации VPS, для большинства сервисов этого хватает.
После создания исходящего WARP в разделе «Маршрутизация» добавьте правило:
Параметр | Значение |
|---|---|
Domain | geosite:openai и всё что нужно |
Outbound | warp |
Важный момент с DNS: убедитесь что DNS‑запросы к этим доменам тоже идут через WARP. Иначе резолвер хостера отдаёт ваш дата‑центровый адрес ещё до установки соединения.
Маршрутизация на сервере
Российский трафик лучше резать на клиенте (geoip:ru → direct) — меньше задержка, меньше нагрузка на сервер. На сервере остаются инфраструктурные правила.
Минимум, который должен быть:
Что | Куда | Зачем |
|---|---|---|
api‑тег | api outbound | Системное правило 3x‑ui, не трогать. |
geoip:private | blocked | Блокируем попытки достучаться до внутренней сети через туннель. |
bittorrent | blocked | Торренты портят репутацию IP. |
geosite:openai и др. | warp | Сервисы, блокирующие дата‑центры. |
остальное | direct | Обычный выход. |
Чтобы правила geosite:* работали, Xray должен знать имя домена, а не только IP. Включайте Sniffing на инбаундах — Xray достанет SNI из пакета сам. Небольшая нагрузка на CPU, но на практике незаметна.
BBR
Сразу после базовой настройки включите BBR — алгоритм управления перегрузкой TCP. Скорость становится стабильнее, меньше просадок под нагрузкой. Особенно заметно на xHTTP.
echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p
Проверить что применилось: sysctl net.ipv4.tcp_congestion_control должно вернуть bbr.
Мониторинг
ICMP‑пинг и TCP‑проверка порта 443 бесполезны. ТСПУ спокойно пропускает SYN‑пакеты — в мониторинге всё зелёное, а TLS handshake тихо дропается на эвристике. Пользователи уже не могут подключиться, а у вас все индикаторы ОК.
Нужно проверять реальное прохождение трафика — через сам Xray до внешнего ресурса.
На слабых серверах проще всего — cron каждые 5 минут:
#!/bin/bash
# Замените порт на ваш локальный SOCKS или HTTP прокси из 3x-ui
RESULT=$(curl -s -m 10 \
--proxy socks5://127.0.0.1:10809 \
-o /dev/null \
-w "%{http_code}" \
https://www.google.com 2>/dev/null)
if [ "$RESULT" != "200" ]; then
echo "$(date): туннель не отвечает, код: $RESULT" >> /var/log/xray-check.log
# сюда можно добавить curl к Telegram webhook
fi
Если сервер потянет — Uptime Kuma умеет пускать проверки через SOCKS5/HTTP прокси и шлёт в Telegram при деградации. Удобнее cron‑скрипта.
xray stats API для постоянного мониторинга на слабом VPS не стоит использовать — сбор метрик по многим клиентам в реальном времени сам создаёт нагрузку.
Безопасность панели
Панель 3x‑ui не должна быть доступна снаружи напрямую. Панель на 127.0.0.1, наружу — nginx с отдельным location. Пути панели и пути туннелей не должны пересекаться.
fail2ban ставится автоматически при установке через официальный скрипт.
x-ui.db — SQLite‑файл со всеми ключами и конфигами. Бэкап должен лежать не на этом же сервере.
Max IPs на пользователя — рекомендую 3. Мобильный клиент постоянно переключается между LTE и Wi‑Fi, при лимите 1–2 получаются ложные блокировки.
Обновление ядра без риска
Кнопка обновления в панели — это лотерея. Если в новом релизе сломали совместимость конфигов, сервис не поднимется и все пользователи отвалятся.
Скрипт с проверкой конфига и автооткатом:
#!/bin/bash
# Запускать от root.
# Новое ядро должно лежать в /tmp/xray-new.
XRAY_BIN="/usr/local/x-ui/bin/xray-linux-amd64"
TIMESTAMP=$(date +%Y%m%d_%H%M)
BACKUP="$XRAY_BIN.bak.$TIMESTAMP"
echo "[1/4] Проверяем конфиг новым бинарником..."
if ! /tmp/xray-new -test -config /usr/local/x-ui/bin/config.json; then
echo "Конфиг не прошёл проверку. Ничего не меняем."
exit 1
fi
echo "[2/4] Бэкап текущего бинарника → $BACKUP"
cp "$XRAY_BIN" "$BACKUP"
# Оставляем последние 3 бэкапа
ls -t "$XRAY_BIN".bak.* 2>/dev/null | tail -n +4 | xargs -r rm -f
echo "[3/4] Заменяем бинарник..."
chmod +x /tmp/xray-new
cp /tmp/xray-new "$XRAY_BIN"
echo "[4/4] Перезапуск..."
pkill -f "xray-linux-amd64" 2>/dev/null || true
sleep 2
systemctl restart x-ui
sleep 10
if ! pgrep -f "xray-linux-amd64" > /dev/null; then
echo "$(date): не запустился, откат" >> /var/log/xray-update.log
cp "$BACKUP" "$XRAY_BIN"
systemctl restart x-ui
echo "Откат выполнен."
exit 1
fi
echo "Готово."
Версии на которых проверено: 3x‑ui 3.6.0, Xray‑core v26.7.28, nginx 1.26.
Клиентские приложения
Из того что пробовал — лучше всего работают Happ и v2rayTUN. Хватает ссылки на подписку или ключа, без ручных настроек. Остальные либо не обновляются, либо требуют возни с каждым инбаундом отдельно.
Один момент: один и тот же конфиг не всегда работает одинаково у всех пользователей. Это не значит, что что‑то сломано — разные клиентские приложения, разные провайдеры, разные тарифы. Иногда помогает переключить транспорт в подписке.
VPS: на что смотреть
Из локаций, которые проверял — Польша стабильнее Нидерландов. У нидерландских хостингов периодически бывают конфликты с провайдерами на стороне хоста. Германия тоже нормальная.
Критерии при выборе:
возможность смены IP если попадёт в блэклисты;
без ограничений и лимитов;
чистая репутация IP хостера или реселлера.
Если что‑то из описанного не работает или работает, но по‑другому: пишите в комментарии, интересно сравнить.