Files
networking-proxy/references/xray-reality-setup-2026-07.md
T
2026-09-06 13:51:04 +00:00

9.8 KiB
Raw Blame History

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)
  • Открыть сайт в браузере → ✅ должно работать

Сценарии:

  1. ping не идёт, но curl работает → VPN в порядке, это норма
  2. ping не идёт и curl не работает → проблема с TCP-маршрутизацией (см. "Диагностика" ниже)
  3. 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

Возможные проблемы

  1. XRay запущен, но порт 443 не отображается — сначала проверь ss. Если там только SSH (22) и exim (25), проверь, что XRay стартовал без ошибок. Причина часто — битый JSON (см. баг heredoc).
  2. Connection refused при curl — это нормально с локальной машины, если нет маршрута до сервера (там порт 443 открыт только на интерфейсе *:443). Проверять через nc.
  3. uuidgen: command not found — на минимальных Debian-образах uuidgen отсутствует. Использовать python3 -c 'import uuid; print(uuid.uuid4())'.
  4. Client "connect deadline exceeded" при работающем сервере — почти всегда блокировка порта оператором. Сменить порт или попробовать с Wi-Fi.