zapret-kvn/sing-box.md
loop-uh a15055e19d sing-box TUN: dialerProxy + process routing (v2rayN architecture)
Реализована архитектура v2rayN для sing-box TUN с process-based routing:
- dialerProxy: xray → SS protect канал → sing-box direct → internet
- TunConfigBundle: единый объект с sing-box + xray конфигами
- Process routing: configurable default outbound (proxy/direct) + per-exe exceptions
- Protected processes: xray.exe, sing-box.exe, tun2socks.exe auto-bypass
- Service routes bug fix: теперь применяются в sing-box конфиге
- DNS: bootstrap UDP + proxy TCP (совместимо с sing-box 1.14+)
- Hot-swap: node switching без перезапуска TUN адаптера
- UI: TUN default outbound ComboBox + protected process guard

Требует sing-box >= 1.14 (исправлен баг direct outbound для inbound-initiated трафика).
Protect канал: chacha20-ietf-poly1305 (method:none несовместим между xray и sing-box).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 13:55:46 +03:00

236 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# sing-box TUN на Windows: проблемы и попытки
## Цель
Заменить tun2socks на sing-box TUN для поддержки маршрутизации по процессам (`process_name`).
tun2socks перехватывает весь трафик и пересылает на xray SOCKS — xray видит все соединения от `tun2socks.exe`, определение процесса невозможно.
## Хронология попыток
### Попытка 1: SOCKS bridge (sing-box TUN → SOCKS → xray)
**Архитектура:**
```
App → TUN (sing-box) → SOCKS:11808 → xray → xhttp → VPS
xray.exe bypass через process_name → direct
```
**Проблемы найденные и исправленные:**
1. `sniff` / `sniff_override_destination` в TUN inbound — **удалены в sing-box 1.13.0**. Мигрировано на `{"action": "sniff"}` в route rules.
2. `auto_detect_interface` ломает SOCKS → localhost — bind к физическому NIC вместо loopback. Исправлено через `inet4_bind_address: "127.0.0.1"`.
3. Нет `hijack-dns` в hybrid config — DNS не перехватывался. Добавлено.
4. Нет sniffing на xray SOCKS inbound — xray не видел домены, domain routing не работал. Добавлен sniffing с `routeOnly: true`.
**Результат:** Частично работало ("вроде работает"). Но:
- Много ошибок xhttp (connection upload closed) — нормальное поведение xhttp транспорта
- claude.exe (node.js) не работал через TUN — DNS через proxy chain (DoH → SOCKS → xray → xhttp) слишком медленный
- `process_name: xray.exe → direct` — хрупкий механизм
### Попытка 2: DNS через direct (без detour)
Сменили DNS на `{"type": "udp", "server": "8.8.8.8"}` без `detour`.
**Проблема:** `FATAL: start dns/udp[direct-dns]: detour to an empty direct outbound makes no sense` — sing-box 1.13 отвергает detour к пустому direct outbound.
Убрали detour полностью → DNS пакеты идут через OS default route → TUN → hijack-dns → DNS module → снова к 8.8.8.8 → **ROUTING LOOP** (700+ connections/sec).
### Попытка 3: dialerProxy (v2rayN-style архитектура)
**Архитектура:**
```
App → TUN (sing-box) → SS(chacha20):PORT_A → xray → xhttp → VPS
xray outbound → dialerProxy → SS:PORT_B → sing-box tun-protect → direct
```
**Проблемы:**
1. `method: "none"` несовместим между sing-box 1.13 и xray 26.2 — `failed to read 50 bytes`. Сменили на `chacha20-ietf-poly1305`.
2. **sing-box direct outbound НЕ МОЖЕТ выйти в интернет** когда TUN активен (даже для трафика от tun-protect inbound):
- `auto_detect_interface: true` — не работает
- `default_interface: "Ethernet"` — не работает
- `stack: "system"` — не работает
- `stack: "mixed"` — не работает
- Все попытки подключения через direct outbound дают `i/o timeout`
- Это значит трафик из tun-protect inbound → direct outbound → ловится TUN обратно → loop
**Вывод:** dialerProxy архитектура невозможна на данной системе из-за бага sing-box direct outbound на Windows.
### Попытка 4: Возврат на SOCKS bridge + TCP DNS через proxy
Вернулись на SOCKS bridge. DNS: `{"type": "tcp", "server": "8.8.8.8", "detour": "proxy"}` — TCP DNS через SOCKS → xray → xray резолвит.
**Результат:** Тот же routing loop (700+ connections/sec). `5.28.195.2:443 via outbound/direct[direct]: i/o timeout`. Даже `192.168.1.180:80 via direct: i/o timeout` — LAN тоже недоступен. DNS fix не помог — проблема не в DNS, а в sing-box direct outbound на этом Windows.
### Итоговый вердикт
**sing-box direct outbound сломан на Windows 10 IoT LTSC 2021 (build 19044)** с sing-box 1.13.3. Ни одна из попыток (auto_detect_interface, default_interface, stack types, DNS strategies) не решила routing loop. Проблема фундаментальная: direct outbound не может отправить трафик через физический NIC когда TUN активен — трафик ловится TUN обратно и зацикливается.
**Решение:** tun2socks по умолчанию + sing-box как экспериментальная опция.
## Ключевые проблемы sing-box на Windows
### 1. direct outbound не работает для non-TUN inbound трафика
Когда трафик приходит через SS/SOCKS inbound (не TUN), direct outbound не может отправить его в интернет — `auto_detect_interface` не привязывает сокет к физическому NIC. Трафик ловится TUN и зацикливается.
**Но**: direct outbound РАБОТАЕТ для трафика из TUN inbound с `process_name` match (xray.exe → direct). Причина неясна — возможно разный code path в sing-box для TUN-initiated vs inbound-initiated connections.
### 2. DNS routing loop
Без `detour` на DNS сервере: DNS пакеты → TUN → hijack-dns → DNS module → отправка к DNS серверу → TUN → loop. Нужен обязательный `detour: "proxy"` для DNS.
### 3. Deprecated/removed поля в 1.13
- `sniff`, `sniff_override_destination` в TUN inbound удалены. Нужны route rule actions.
- `detour` к пустому direct outbound запрещён.
### 4. SS method "none" несовместимость
`method: "none"` между sing-box 1.13 и xray 26.2 даёт `failed to read 50 bytes`. Нужен реальный cipher (chacha20-ietf-poly1305).
### 5. Нестабильность xhttp через double-proxy
Цепочка TUN → SOCKS → xray → xhttp → VPS нестабильна. xhttp создаёт множество параллельных стримов, часть обрывается. Для приложений с агрессивным timeout (node.js/claude) это критично.
## Сравнение tun2socks vs sing-box TUN
| Фича | tun2socks | sing-box TUN |
|------|-----------|--------------|
| Стабильность | Высокая | Низкая (Windows) |
| Process routing | Нет | Да (process_name) |
| DNS routing | Нет (xray handles) | Проблемная (loop risks) |
| Routing loop prevention | Маршруты через netsh | process_name / dialerProxy (не работает) |
| Совместимость с xhttp | Хорошая (прямой SOCKS) | Проблемная (double-proxy) |
| Настройка | Простая | Сложная (много подводных камней) |
### Попытка 5: dialerProxy с sing-box 1.14.0-alpha.5 (2026-03-24)
**Предпосылки:**
- Анализ исходного кода v2rayN показал архитектуру "protect SS канала" через `dialerProxy`
- Скачан sing-box 1.14.0-alpha.5 (pre-built binary)
- Цель: проверить исправлен ли баг SS inbound → direct outbound (не работал на 1.13.3)
**Архитектура v2rayN (эталон):**
```
App → TUN (sing-box) → relay outbound → xray SOCKS inbound
xray → proxy outbound → dialerProxy → "tun-protect-out" SS outbound → sing-box SS inbound → direct → internet
process_name: [xray.exe, sing-box.exe] → direct (защита от routing loop)
```
**Тест 1: SS inbound → direct outbound (chacha20-ietf-poly1305)**
Конфиг sing-box:
```json
{
"inbounds": [
{"type": "tun", "tag": "tun-in", "interface_name": "test_tun",
"address": ["172.19.0.1/30"], "auto_route": true, "strict_route": true, "stack": "mixed"},
{"type": "shadowsocks", "tag": "tun-protect", "listen": "127.0.0.1",
"listen_port": 19200, "method": "chacha20-ietf-poly1305", "password": "testpassword123"}
],
"outbounds": [{"type": "direct", "tag": "direct"}],
"route": {
"auto_detect_interface": true,
"rules": [
{"action": "sniff"},
{"process_name": ["sing-box.exe"], "outbound": "direct"},
{"inbound": ["tun-protect"], "outbound": "direct"},
{"ip_is_private": true, "outbound": "direct"}
]
}
}
```
Конфиг xray (SS outbound → sing-box SS inbound):
```json
{
"inbounds": [{"protocol": "socks", "listen": "127.0.0.1", "port": 11808,
"settings": {"auth": "noauth", "udp": true}}],
"outbounds": [{"protocol": "shadowsocks", "settings": {"servers": [
{"address": "127.0.0.1", "port": 19200, "method": "chacha20-ietf-poly1305", "password": "testpassword123"}
]}}]
}
```
Тест:
```bash
curl -x socks5h://127.0.0.1:11808 http://httpbin.org/ip
# Результат: {"origin": "109.252.184.208"}
```
**РЕЗУЛЬТАТ: ✅ РАБОТАЕТ!** SS inbound → direct outbound на sing-box 1.14.0-alpha.5 **исправлен**.
IP 109.252.184.208 — реальный IP провайдера (не proxy), трафик выходит через physical NIC минуя TUN.
**Тест 2: method:none совместимость (xray 26.2 ↔ sing-box 1.14)**
Тот же тест, но с `"method": "none", "password": ""` на обеих сторонах.
```bash
curl -x socks5h://127.0.0.1:11808 http://httpbin.org/ip
# Результат: curl: (7) Failed to connect to httpbin.org port 80 via 127.0.0.1 after 2036 ms
```
**РЕЗУЛЬТАТ: ❌ НЕ РАБОТАЕТ.** Баг `method:none` между xray и sing-box по-прежнему присутствует.
Тот же симптом что в Попытке 3 — xray отправляет пакет, sing-box не может его прочитать.
**Вывод:**
- **Баг direct outbound для inbound-initiated трафика ИСПРАВЛЕН в sing-box 1.14** (не работал на 1.13.3)
- `method:none` по-прежнему сломан между xray и sing-box — используем `chacha20-ietf-poly1305`
- Overhead шифрования на localhost пренебрежимо мал
- Архитектура v2rayN с dialerProxy + protect SS каналом теперь реализуема
**Тест 3: интеграция в приложение — первый запуск**
Ошибка sing-box 1.14 при старте:
```
FATAL: outbound DNS rule item is deprecated in sing-box 1.12.0 and will be removed in sing-box 1.14.0
```
**Причина:** DNS rule `{"outbound": ["direct"], "server": "bootstrap-dns"}` — deprecated в 1.12, удалён в 1.14.
Этот формат позволял назначить DNS сервер для outbound'а через DNS rules. В 1.14 нужно использовать `domain_resolver` прямо на outbound'е.
**Фикс:**
```diff
- "dns": { "rules": [{"outbound": ["direct"], "server": "bootstrap-dns"}] }
+ // Вместо DNS rule — field на самом outbound:
+ direct_out = {"type": "direct", "tag": "direct", "domain_resolver": "bootstrap-dns"}
+ // + default_domain_resolver в route:
+ "route": { "default_domain_resolver": "proxy-dns", ... }
```
**ВАЖНО для совместимости с sing-box 1.14+:**
- НЕ использовать `outbound` как match condition в DNS rules
- Использовать `domain_resolver` field на outbound'ах
- Использовать `default_domain_resolver` в route config
**Тест 4: полная интеграция в приложение (после фиксов)**
После исправления 3 багов:
1. `outbound` DNS rule → заменён на `domain_resolver` на outbound'ах
2. outbound tag `relay` → `proxy` (совпадает с routing rules)
3. Убран debug лог
**РЕЗУЛЬТАТ: ✅ РАБОТАЕТ!** Полная цепочка dialerProxy подтверждена:
- `outbound/socks[proxy]` — весь трафик приложений идёт через proxy
- protect канал: `tun-protect → 46.17.101.82:30443 → direct` — xray достигает VPS
- TLS sniff: определяет домены из SNI → domain routing работает
- DNS hijack: перехватывает DNS → proxy-dns через TCP
- QUIC sniff: определяет QUIC → routing по доменам
- Telegram (AyuGram.exe): подключается через proxy, сообщения ходят
**Ключевые баги при интеграции:**
1. `outbound` DNS rule deprecated в sing-box 1.12, удалён в 1.14 → FATAL при старте
2. outbound tag mismatch: routing rules генерируют `outbound: "proxy"`, а outbound назывался `"relay"` → `outbound not found: proxy`
3. Google service routes (`google.com → direct`) потенциально перехватывают Telegram MTProto (фейковый TLS SNI с google.com доменом)
---
## Рекомендация (обновлено 2026-03-24)
1. **tun2socks по умолчанию** — стабильный, проверенный, работает с xhttp
2. **sing-box TUN с dialerProxy** — теперь рабочий на sing-box ≥ 1.14, поддерживает process routing
3. Обязательно: sing-box 1.14+ (1.13.3 имеет баг direct outbound для inbound-initiated трафика)
4. Protect канал: `chacha20-ietf-poly1305` (method:none сломан между xray и sing-box)
5. **НЕ использовать** `outbound` DNS rule items — deprecated в 1.12, удалены в 1.14. Вместо этого: `domain_resolver` на outbound'ах
## Тестовая среда
- Windows 10 IoT Enterprise LTSC 2021 (build 19044)
- xray-core 26.2.6
- sing-box 1.13.3 → **1.14.0-alpha.5** (обновлено)
- Транспорт: VLESS + xhttp + Reality
- Прокси сервер: 46.17.101.82:30443