# 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: ```bash ssh root@host "cat > /path/config.json << 'EOF' { \"key\": \"value\" } EOF\" ``` Все кавычки в JSON теряются — на сервере оказывается: ```json { key: value } ``` XRay выдаёт ошибку: `invalid character 'l' looking for beginning of object key string` (ожидал кавычку, получил 'l' от `log`). **Причина:** Двойная обработка shell'ом: сначала локальный shell разбирает кавычки, потом передаёт через SSH, и quoted heredoc (`'EOF'`) не спасает — кавычки съедаются на одном из уровней. **Проверенное решение — scp:** ```bash # 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:** ```bash 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 надёжнее. ## Полный конфиг сервера (рабочий) ```json { "log": { "loglevel": "warning" }, "inbounds": [ { "port": 443, "protocol": "vless", "settings": { "clients": [ { "id": "", "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": "", "shortIds": [ "" ] } }, "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" / "Сбой проверки интернет-соединения": ```bash # 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 # сравни с тем, что в клиенте # 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 (новые соединения):** ```bash # На сервере — мониторинг порта 443 tcpdump -i any -n port 443 -c 10 -t # Пользователь в это время пробует открыть сайт # SYNs не видно → телефон не шлёт трафик (проблема с настройкой клиента) # Видно SYN→SYN-ACK→ACK → рукопожатие есть, проблема в XRay routing # Только FIN от старых сессий → старые сессии закрываются, новых нет ``` ## Ротация ключей Reality (при смене конфига или утечке) Периодическая смена ключей Reality повышает безопасность. Полный цикл: ```bash # 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: ```json "log": { "loglevel": "debug" } ``` После отладки вернуть `"warning"` — debug пишет очень много. В debug видны: - `accepted tcp:...` — входящие соединения - `accepted udp:...:53 [direct]` — DNS-запросы (если есть → клиент умеет резолвить) - `drain...` — завершение сессий - Ошибки рукопожатия и таймауты ## Полезные команды ```bash # Сгенерировать UUID python3 -c 'import uuid; print(uuid.uuid4())' # Сгенерировать ключевую пару Reality xray x25519 # Получить public key из private key xray x25519 -i # Прослушиваемые порты 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.