9.8 KiB
Session reference — XRay Reality настройка 2026-07-14
Окружение
- US VPS: vps03.nixg.ru (80.209.240.167), Debian 13 (trixie), root доступ
- RU VPS: cloud.ru (vps02, 87.242.100.206), пользователь estorozhenko
- Клиент: Android, v2rayNG (v2.2.6)
- SSH ключи: /mnt/yandex-disk/.ssh_box/hostkeyVPS
- Маскировка: reddit.com (SNI), fingerprint chrome
- Пинг US→RU: ~130ms
Баг heredoc — подробности
Проблема: При записи JSON-конфига через SSH с heredoc:
ssh root@host "cat > /path/config.json << 'EOF'
{ \"key\": \"value\" }
EOF\"
Все кавычки в JSON теряются — на сервере оказывается:
{
key: value
}
XRay выдаёт ошибку: invalid character 'l' looking for beginning of object key string (ожидал кавычку, получил 'l' от log).
Причина: Двойная обработка shell'ом: сначала локальный shell разбирает кавычки, потом передаёт через SSH, и quoted heredoc ('EOF') не спасает — кавычки съедаются на одном из уровней.
Проверенное решение — scp:
# 1. Напиши локально
write_file(path="/tmp/xray_config.json", content="...")
# 2. Скопируй через SCP
scp -i /path/key -o StrictHostKeyChecking=no /tmp/xray_config.json root@host:/usr/local/etc/xray/config.json
# 3. Перезапусти
ssh -i /path/key root@host "systemctl restart xray"
Альтернатива — Python json.dump() over SSH:
ssh root@host "python3 -c '
import json
config = { ... }
with open(\"/usr/local/etc/xray/config.json\", \"w\") as f:
json.dump(config, f, indent=2)
'"
Но с этим тоже были проблемы экранирования — scp надёжнее.
Полный конфиг сервера (рабочий)
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "<uuid>",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
"dest": "reddit.com:443",
"xver": 0,
"serverNames": [
"reddit.com",
"www.reddit.com"
],
"privateKey": "<privateKey>",
"shortIds": [
"<shortId>"
]
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
]
}
Рабочая ссылка для импорта в v2rayNG
Порт 443 (основной):
vless://cf4d32e5-9c19-460e-a5de-f881b01dcfe1@80.209.240.167:443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=reddit.com&fp=chrome&pbk=_ZuQgpScINJVuTRhifNX7cy9MikcNxQNq1vLOZa9ZBE&sid=f8701c8463b82974&type=tcp&headerType=none#XRay-Reality-US
Порт 8443 (если 443 блокируется оператором):
vless://cf4d32e5-9c19-460e-a5de-f881b01dcfe1@80.209.240.167:8443?encryption=none&flow=xtls-rprx-vision&security=reality&sni=reddit.com&fp=chrome&pbk=_ZuQgpScINJVuTRhifNX7cy9MikcNxQNq1vLOZa9ZBE&sid=f8701c8463b82974&type=tcp&headerType=none#XRay-Reality-US-8443
Диагностика "не подключается"
Когда клиент пишет "connect deadline exceeded" / "Сбой проверки интернет-соединения":
# 1. Сервер жив?
systemctl status xray
ss -tlnp | grep -E '443|8443'
# 2. Конфиг валиден?
xray run -test -config /usr/local/etc/xray/config.json
# 3. Публичный ключ совпадает?
xray x25519 -i <privateKey> # сравни с тем, что в клиенте
# 4. Сервер выходит в интернет?
curl -s -o /dev/null -w '%{http_code}' https://reddit.com
# 5. Внешняя доступность порта?
# с другого хоста:
nc -w 5 80.209.240.167 443 && echo "OK" || echo "BLOCKED"
# 6. Логи xray — есть ли accepted?
journalctl -u xray --since '30 min ago' --no-pager | grep 'accepted'
Если всё выше ок — проблема на стороне мобильного оператора (блокировка порта, а не IP).
Multi-port стратегия
При блокировке 443 порта мобильным оператором — добавить второй inbound на другой порт. Просто скопировать блок inbounds[0], заменив port. Перезапустить xray.
Дополнить ссылку для клиента: заменить @IP:443 на @IP:8443.
ICMP не работает через VLESS+Reality (важно для диагностки)
XRay VLESS с flow=xtls-rprx-vision не проксирует ICMP (ping/traceroute).
Проксируется только TCP и UDP.
Когда пользователь пишет "VPN подключился, но пинг не идёт / сайты не грузятся":
- ping 8.8.8.8 → ❌ не работает через XRay (ICMP)
- curl https://google.com → ✅ должно работать (TCP)
- curl -s ifconfig.me → ✅ покажет внешний IP сервера
- nslookup google.com → ✅ работает (UDP:53)
- Открыть сайт в браузере → ✅ должно работать
Сценарии:
- ping не идёт, но curl работает → VPN в порядке, это норма
- ping не идёт и curl не работает → проблема с TCP-маршрутизацией (см. "Диагностика" ниже)
- tcpdump показывает трёхстороннее рукопожатие (SYN→SYN-ACK→ACK) → соединение с сервером есть, проблему искать в DNS или outbound-маршрутизации
Live-диагностика через tcpdump (новые соединения):
# На сервере — мониторинг порта 443
tcpdump -i any -n port 443 -c 10 -t
# Пользователь в это время пробует открыть сайт
# SYNs не видно → телефон не шлёт трафик (проблема с настройкой клиента)
# Видно SYN→SYN-ACK→ACK → рукопожатие есть, проблема в XRay routing
# Только FIN от старых сессий → старые сессии закрываются, новых нет
Ротация ключей Reality (при смене конфига или утечке)
Периодическая смена ключей Reality повышает безопасность. Полный цикл:
# 1. Сгенерировать новую пару
xray x25519
# Вывод:
# PrivateKey: SEnziJbX3vDlWEQeGHHYXWa5DP3WXJrydkUJbUCh2FQ
# Password (PublicKey): 7PS-NrEqmF9_AcXrxjladd9zEAIxeE2LpfCAMsEQ_As
# 2. Сгенерировать новый shortId (8 байт hex)
openssl rand -hex 8
# Вывод: b11c31731d6d43d8
# 3. Обновить privateKey в serverNames и shortId в конфиге сервера
# 4. Перезапустить xray
systemctl restart xray
# 5. Передать клиенту:
# - PublicKey из шага 1
# - shortId из шага 2
# (UUID и адрес не меняются)
Режим debug в логах XRay
При проблемах с соединением временно включить debug:
"log": {
"loglevel": "debug"
}
После отладки вернуть "warning" — debug пишет очень много.
В debug видны:
accepted tcp:...— входящие соединенияaccepted udp:...:53 [direct]— DNS-запросы (если есть → клиент умеет резолвить)drain...— завершение сессий- Ошибки рукопожатия и таймауты
Полезные команды
# Сгенерировать UUID
python3 -c 'import uuid; print(uuid.uuid4())'
# Сгенерировать ключевую пару Reality
xray x25519
# Получить public key из private key
xray x25519 -i <privateKey>
# Прослушиваемые порты
ss -tlnp | grep xray
# Логи xray
journalctl -u xray --since '1 hour ago' --no-pager
Возможные проблемы
- XRay запущен, но порт 443 не отображается — сначала проверь ss. Если там только SSH (22) и exim (25), проверь, что XRay стартовал без ошибок. Причина часто — битый JSON (см. баг heredoc).
- Connection refused при curl — это нормально с локальной машины, если нет маршрута до сервера (там порт 443 открыт только на интерфейсе *:443). Проверять через
nc. - uuidgen: command not found — на минимальных Debian-образах uuidgen отсутствует. Использовать
python3 -c 'import uuid; print(uuid.uuid4())'. - Client "connect deadline exceeded" при работающем сервере — почти всегда блокировка порта оператором. Сменить порт или попробовать с Wi-Fi.