mirror of
https://gitverse.ru/kpa39l/networking-proxy.git
synced 2026-09-29 09:15:02 +00:00
251 lines
9.8 KiB
Markdown
251 lines
9.8 KiB
Markdown
# 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": "<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" / "Сбой проверки интернет-соединения":
|
||
|
||
```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 <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 (новые соединения):**
|
||
```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 <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. |