Практическое руководство: защита VPN от localhost-атаки
Дата: 7 апреля 2026
Контекст: Уязвимость VLESS-клиентов + эксплуатация localhost Meta/Яндексом
Аудитория: Пользователи VPN, администраторы серверов, разработчики клиентов
Связанные заметки:
Оглавление
- Суть проблемы за 30 секунд
- Проверенные клиенты: кто уязвим, кто нет
- Что делать пользователям Android
- Что делать пользователям Windows
- Что делать пользователям iOS
- Что делать администраторам серверов
- Конфигурации: xray-core клиент
- Конфигурации: sing-box клиент
- Конфигурации: xray-core сервер
- Конфигурации: CloudFlare WARP на сервере
- Конфигурации: блокировка geoip:ru на сервере
- Конфигурации: маршрутизация «Всё кроме РФ» на клиенте
- Блокировка Happ на сервере подписок
- ГАЙД: v2rayNG — как защититься
- ГАЙД: NekoBox — как защититься
- ГАЙД: Clash/mihomo — как защититься
- Фаерволы на Android: что реально работает
- FAQ: hev-socks5-tunnel, Karing, Husi, v2rayN
- CVE-2023-43644: обход аутентификации sing-box
- Чеклист действий
1. Суть проблемы за 30 секунд
Все VPN-клиенты на базе xray/sing-box создают на телефоне/компьютере локальный SOCKS5-прокси без пароля. Любое приложение-шпион (Яндекс, WB, Ozon, гос.приложения) может:
- Найти этот прокси за секунды (скан портов localhost)
- Подключиться без пароля
- Узнать IP вашего VPN-сервера
- Передать IP в РКН → сервер заблокирован
Knox, Shelter, Island, режим инкогнито, split tunneling — НЕ помогают.
Скриншот POC-приложения с включённой SOCKS5-аутентификацией (Husi):
Per-app split tunnel bypass
Status: VPN not found ← прокси не обнаружен
Direct IP: xxx.xxx.xxx.xxx
IP via proxy: - ← не смог подключиться
Xray API: Not found ← API недоступен
Вывод: аутентификация работает — POC не смог пробиться через запароленный SOCKS5.
2. Проверенные клиенты: кто уязвим, кто нет
Android
| Клиент | Ядро | Порт | SOCKS5 auth | Статус | Что делать |
|---|---|---|---|---|---|
| v2rayNG 2.0.0 | xray | 10808 | ❌ Нет в UI. ⚠️ Custom config — ненадёжно (v2rayNG может перезаписать inbound) | 🟡 Уязвим | Перейти на Husi; или AFWall+ (root) |
| Hiddify 4.1.1 | sing-box + xray | ? | ❌ Нет в UI | 🟡 Уязвим | Перейти на Husi/SFA |
| NekoBox 1.4.2 | sing-box 1.12.19 | 2080 | ❌ Нет в UI. ⚠️ Custom JSON — возможно, но сбрасывается при обновлении | 🟡 Уязвим | Перейти на Husi; или удалить mixed inbound |
| Npv Tunnel | xray | ? | ❌ Нет | 🟡 Уязвим | Перейти на Husi/SFA |
| v2RayTun 5.19.64 | xray | ? | ⚠️ Ядро поддерживает, UI — неизвестно | 🟡 Скорее уязвим | Уточнить у разработчика |
| Happ | xray | ? | ❌ + API HandlerService без auth | 🔴 УДАЛИТЬ НЕМЕДЛЕННО | Дамп ключей, IP, SNI |
| Karing | sing-box | 3067 | ⚠️ Ядро поддерживает, в UI нет настройки | 🟡 Скорее уязвим | Проверить custom JSON |
| Exclave | sing-box | ? | ✅ Да (через конфиг) | 🟢 Можно настроить | Настроить auth в конфиге |
| Husi 1.1.0 | sing-box (dun) | ? | ✅ Да, есть в UI | 🟢 Рекомендован | Включить auth в настройках |
| SFA 1.13.6 | sing-box | ? | ✅ Да (JSON) | 🟢 Можно настроить | Ручная правка JSON |
| saeeddev94/xray | xray | ? | ✅ Да (JSON + UI) | 🟢 Можно настроить | F-Droid, настроить auth |
| v2RayTun 5.20.67 | xray | ? | ❌ Нет в UI. Разработчик обещал фикс (март 2026), пока нет | 🟡 Уязвим | Ждать фикса или перейти. ⚠️ Шлёт домены подписок на свои сервера |
| ClashMeta Android 2.11.25 | mihomo | — | ✅ Да (YAML). По дефолту socks-port выключен (TUN-only) → прокси нет → нечего сканировать | 🟢 Безопасен по дефолту | Если включили socks-port — добавить auth + убрать skip-auth-prefixes |
| FlClash | mihomo | — | ✅ Да (YAML). Аналогично — дефолт TUN-only | 🟢 Безопасен по дефолту | Аналогично ClashMeta |
| Incy 2.0.8 | xray 26.3.27 | ? | ⚠️ Ядро поддерживает, UI-настройка auth не документирована | 🟡 Вероятно уязвим | Нужна проверка — closed-source-подобный |
| anet 0.4.2 | Собственный (Rust/ASTP) | — | ✅ Не применимо | 🟢 Не уязвим | Нет SOCKS5/HTTP прокси на localhost. Чистый TUN через собственный протокол |
Windows / Desktop
| Клиент | Ядро | Порт | SOCKS5 auth | Статус | Что делать |
|---|---|---|---|---|---|
| v2rayN 7.20.2 | xray/sing-box | 10808 | ✅ Да (JSON + UI) | 🟢 Можно настроить | Включить auth + Windows Firewall |
| Nekoray | sing-box/xray | ? | ❌ Нет в UI | 🔴 Заброшен (2026) | Перейти на Throne / v2rayN / Clash Verge Rev |
| Throne 1.1.1 (март 2026) | sing-box (основной) + xray (для VLESS) | 2080 | ⚠️ Дефолтный mixed нельзя отключить, но можно создать кастомный inbound с auth | 🟡 Уязвим по дефолту, можно настроить | Создать кастомный inbound с auth; заблокировать дефолтный фаерволом |
| XrayFluent | xray | 10808 | ❌ Нет | 🟡 Уязвим | Будет исправлено |
| Karing (Windows) | sing-box | 3067/3066 | ⚠️ Ядро поддерживает, UI-настройка не подтверждена | 🟡 Вероятно уязвим | Проверить custom JSON |
| Clash Verge Rev | mihomo | — | ✅ Да (YAML). По дефолту TUN-only, socks-port выключен | 🟢 Безопасен по дефолту | Если включили socks-port — добавить auth + убрать skip |
| ClashX Meta (macOS) | mihomo | — | ✅ Да (YAML). Аналогично | 🟢 Безопасен по дефолту | Аналогично |
| Incy (Desktop) 2.0.8 | xray 26.3.27 | ? | ⚠️ Не документировано | 🟡 Нужна проверка | — |
iOS
| Клиент | Ядро | Порт | SOCKS5 auth | Статус | Что делать |
|---|---|---|---|---|---|
| Happ | xray | ? | ❌ + API без auth | 🔴 УДАЛИТЬ | Удалено из российского App Store; в других регионах может быть доступно, но фикса не будет |
| V2BOX 5.3.4 | xray | ? | ❌ Нет подтверждения | 🟡 Скорее уязвим | Нет решения |
| RabbitHole 1.3.0 | ? (closed-source) | ? | ⚠️ Неизвестно | ❓ Нужна проверка | Closed-source, поддерживает SOCKS5 — нужна проверка POC |
| Shadowrocket | iOS VPN framework | — | ⚠️ Вероятно не применимо (iOS sandbox) | 🟢/❓ Скорее не уязвим, нужна проверка POC | iOS sandbox ограничивает listening sockets |
Shadowrocket — использует iOS Network Extension (VPN framework). Основной режим — TUN через системный VPN. В отличие от Android-клиентов (v2rayNG, NekoBox), Shadowrocket не является прокси-сервером — он подключается К прокси-серверам. Однако верификация показала, что Shadowrocket может поддерживать SOCKS5-конфигурации на localhost. При этом iOS sandbox жёстко ограничивает фоновые listening-сокеты, доступные другим приложениям. Вердикт: скорее не уязвим из-за ограничений iOS, но для полной уверенности требуется проверка POC на реальном устройстве.
Exclave ранее указывался как iOS-клиент — это ошибка. Exclave (github.com/dyhkwong/Exclave) — это Android-клиент на базе sing-box, доступен на F-Droid. Поддерживает аутентификацию через конфиг.
RabbitHole — closed-source iOS/macOS клиент от RABBIT HOLE STUDIO LTD. Поддерживает VLESS, VMess, Hysteria2, SOCKS5 и др. Без публичного репозитория невозможно точно определить, создаёт ли он SOCKS5 на localhost. Требуется ручная проверка POC-приложением.
Incy — кроссплатформенный клиент на xray-core 26.3.27 (github.com/INCY-DEV/incy-platforms). v2.0.8 (7 апреля 2026). Поддерживает VLESS Reality, VMess, Trojan, SS, Hysteria2, WireGuard. Auth-статус на локальном inbound не документирован — нужна проверка.
Throne (github.com/throneproj/Throne) — преемник заброшенного Nekoray. Qt-based, sing-box + встроенный xray-core. v1.1.1 (март 2026). Дефолтный mixed inbound нельзя отключить, но можно: (1) перевесить на другой IP:port, (2) заблокировать фаерволом, (3) создать кастомный socks/mixed inbound с auth. Из обсуждения на ntc.party: «в Throne ситуация получше — можно создать кастомный инбаунд и закрыть его логопассом».
anet (github.com/ZeroTworu/anet) — полностью кастомный Rust VPN с собственным протоколом ASTP v0.5 (ChaCha20Poly1305/X25519/Ed25519). Не создаёт SOCKS5/HTTP прокси — только чистый TUN. Нишевый проект для «сети друзей» (624 звезды). К данной уязвимости не применим.
v2RayTun — xray-core, 16 млн скачиваний, open-source. Разработчик подтвердил уязвимость (март 2026) и обещал фикс, но на апрель 2026 фикса нет. ⚠️ Privacy concern: отправляет домены подписок на свои серверы при каждом запуске.
О hev-socks5-tunnel (используется в v2rayNG)
hev-socks5-tunnel — это легковесная реализация tun2socks. Сама библиотека поддерживает SOCKS5-аутентификацию (username/password). Но v2rayNG не включает auth при настройке туннеля — передаёт noauth. Проблема не в hev-socks5-tunnel, а в том, что v2rayNG не выставляет аутентификацию на inbound xray-core, к которому подключается туннель.
О Karing (sing-box)
Karing использует ядро sing-box. Создаёт local proxy на портах:
- HTTP/HTTPS:
127.0.0.1:3066 - SOCKS5:
127.0.0.1:3067
Karing использует sing-box core с тремя mixed-inbound портами: 3065, 3066, 3067. По умолчанию — без аутентификации.
Защита: в настройках каждого профиля необходимо отредактировать блок inbounds и добавить users с паролем ко всем трём inbound:
"inbounds": [
{
"type": "mixed",
"tag": "mixed_in_direct",
"set_system_proxy": false,
"users": [
{
"username": "local",
"password": "СЮДА_ДЛИННЫЙ_РАНДОМНЫЙ_ПАРОЛЬ"
}
],
"listen": "127.0.0.1",
"listen_port": 3065
},
{
"type": "mixed",
"tag": "mixed_in_proxy",
"set_system_proxy": false,
"users": [
{
"username": "local",
"password": "СЮДА_ДЛИННЫЙ_РАНДОМНЫЙ_ПАРОЛЬ"
}
],
"listen": "127.0.0.1",
"listen_port": 3066
},
{
"type": "mixed",
"tag": "mixed_in_rule",
"set_system_proxy": false,
"users": [
{
"username": "local",
"password": "СЮДА_ДЛИННЫЙ_РАНДОМНЫЙ_ПАРОЛЬ"
}
],
"listen": "127.0.0.1",
"listen_port": 3067
}
]Важно:
- Пароль должен быть одинаковым во всех трёх inbound (Karing использует один пароль для всех)
- Это нужно делать вручную для каждого профиля
- Подключение и стабильность работы это не затрагивает
- Без этой правки все три порта (3065-3067) открыты для любого приложения
⚠️ Важно: Karing использует нестандартные порты (3065-3067), которых нет в методичке Минцифры. Но скан всех портов localhost — дело секунд.
О Husi (подтверждённый фикс)
Husi (codeberg.org/xchacha20-poly1305/husi) — форк sing-box для Android с поддержкой SOCKS5-аутентификации в UI. Проверено: POC-приложение per-app-split-bypass не может обнаружить прокси при включённой аутентификации (скриншот выше).
⚠️ Критично: убедитесь что Husi использует sing-box версии 1.4.5 или выше — в более ранних версиях есть CVE-2023-43644 (обход аутентификации). См. раздел 19.
3. Что делать пользователям Android
Приоритет 1: Немедленно
-
Удалить Happ — HandlerService без аутентификации позволяет дампить ваши ключи и IP сервера. Один пользователь с Happ компрометирует весь сервер.
-
Перейти на клиент с SOCKS5 auth:
- Husi (рекомендован) — codeberg.org/xchacha20-poly1305/husi
- SFA (sing-box for Android) — ручная настройка JSON
- saeeddev94/xray — F-Droid — ручной JSON
-
Включить аутентификацию в настройках клиента (см. конфиги ниже)
Приоритет 2: Серверная защита
- Попросить администратора сервера настроить раздельные IP (входной ≠ выходной)
- Убедиться что на сервере заблокирован geoip:ru на outbound
- Использовать маршрутизацию «Всё кроме РФ» на клиенте
Приоритет 3: Изоляция
- Российское ПО — на отдельное устройство. Knox/Shelter/Island НЕ изолируют loopback.
- Если есть root: заблокировать доступ к SOCKS-порту через iptables:
# Разрешить только UID VPN-клиента (например, 10150) iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 10808 -m owner --uid-owner 10150 -j ACCEPT iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 10808 -j DROP # То же для UDP iptables -I OUTPUT -p udp -d 127.0.0.1 --dport 10808 -m owner --uid-owner 10150 -j ACCEPT iptables -I OUTPUT -p udp -d 127.0.0.1 --dport 10808 -j DROPUID приложения:
adb shell dumpsys package <package.name> | grep userId
Чего НЕ делать
- ❌ Не полагаться на смену порта — скан 65535 портов на localhost за секунды
- ❌ Не полагаться на Knox/Shelter/Island — loopback общий
- ❌ Не полагаться на split tunneling — шпион ходит напрямую на 127.0.0.1
- ❌ Не полагаться на режим инкогнито — не влияет на localhost
4. Что делать пользователям Windows
На Windows ситуация лучше, чем на Android: есть Windows Firewall с контролем по процессам.
Приоритет 1: Firewall
-
Заблокировать доступ к порту 10808/10809 для всех процессов кроме доверенных:
PowerShell (от администратора):
# Заблокировать ВСЕ подключения к SOCKS-порту New-NetFirewallRule -DisplayName "Block SOCKS5 10808" ` -Direction Outbound -LocalPort 10808 -Protocol TCP ` -Action Block -Profile Any # Разрешить только xray.exe New-NetFirewallRule -DisplayName "Allow xray SOCKS5" ` -Direction Outbound -LocalPort 10808 -Protocol TCP ` -Program "C:\path\to\xray.exe" -Action Allow -Profile Any # Разрешить браузеру (если нужен прямой SOCKS) New-NetFirewallRule -DisplayName "Allow Firefox SOCKS5" ` -Direction Outbound -LocalPort 10808 -Protocol TCP ` -Program "C:\Program Files\Mozilla Firefox\firefox.exe" ` -Action Allow -Profile Any # То же для HTTP-прокси порта New-NetFirewallRule -DisplayName "Block HTTP proxy 10809" ` -Direction Outbound -LocalPort 10809 -Protocol TCP ` -Action Block -Profile Any New-NetFirewallRule -DisplayName "Allow xray HTTP" ` -Direction Outbound -LocalPort 10809 -Protocol TCP ` -Program "C:\path\to\xray.exe" -Action Allow -Profile AnyВажно: правила
Allowдолжны быть выше правилBlockпо приоритету. В Windows FirewallBlockимеет приоритет по умолчанию, поэтому нужно настроить через GPO или использоватьnetshс правильным порядком. -
Альтернатива — xray routing с process name:
В конфиге xray-core на клиенте можно ограничить, какие процессы могут использовать прокси:
{ "routing": { "rules": [ { "type": "field", "processName": ["firefox", "chrome", "msedge", "telegram"], "outboundTag": "proxy" }, { "type": "field", "processName": ["yandex", "vk", "ozon"], "outboundTag": "block" } ] } }Ограничение:
processNameработает только для локальных подключений (тот же хост). Формат:"firefox"(без .exe) или"C:\\Program Files\\app.exe"(абсолютный путь).
Приоритет 2: Конфигурация клиента
-
Включить SOCKS5 auth в конфиге (даже на Windows это полезно):
В v2rayN: настройки → custom inbound config → изменить
"auth": "noauth"на"auth": "password"+ добавить"accounts". -
Использовать маршрутизацию «Всё кроме РФ»:
В v2rayN 7.0+:
Настройки → Региональные пресеты → Россия → Всё кроме РФ. Автоматически скачивает правила из runetfreedom/russia-v2ray-rules-dat.
5. Что делать пользователям iOS
Ситуация на iOS самая сложная:
- Большинство клиентов удалено из App Store → обновлений не будет
- Нет root → нет iptables
- Нет возможности редактировать inbound JSON в большинстве клиентов
Что можно сделать
- Удалить Happ — самый опасный клиент, удалён из App Store, фикса не будет
- Использовать клиенты с поддержкой custom JSON — если такие ещё установлены
- Защита на стороне сервера — единственная реальная опция:
- Раздельные входной/выходной IP
- WARP на выходе
- geoip:ru → block на сервере
Особенность iOS
Исследователи LocalMess отмечают: iOS технически уязвима к тому же вектору (loopback не изолирован), но фоновые приложения iOS жёстко ограничены — им сложнее запускать постоянные фоновые сканеры. Это не защита, а лишь усложнение атаки.
6. Что делать администраторам серверов
Приоритет 1: Раздельные IP
Если у сервера один IP — выходной IP = входной IP. Утечка выходного = потеря сервера.
Решение: два IP-адреса.
- Входной IP (для подключения клиентов) → inbound слушает на нём
- Выходной IP (для исходящего трафика) → freedom outbound через
sendThrough
{
"outbounds": [
{
"protocol": "freedom",
"sendThrough": "203.0.113.46",
"tag": "freedom-out"
}
]
}Если второй IP недоступен → используйте WARP (раздел 10).
Приоритет 2: WARP на выходе
CloudFlare WARP маскирует выходной IP. Даже если шпион узнает выходной IP через SOCKS5, он получит IP Cloudflare, а не вашего сервера.
Приоритет 3: Блокировка geoip:ru на outbound
Шпионский модуль, пробравшийся через SOCKS5, отправит запрос на российский сервер (для передачи вашего IP в РКН). Если заблокировать исходящий трафик на geoip:ru, шпион не сможет связаться со своим сервером через ваш VPN.
Приоритет 4: Блокировка Happ
На сервере подписок заблокировать UserAgent Happ/*. Один пользователь с Happ = компрометация всего сервера (ключи, SNI, входной IP).
Приоритет 5: Мониторинг
Отслеживать нетипичные запросы через прокси:
ifconfig.me,ipinfo.io,whatismyip.com,api.ipify.org- Массовые запросы на российские IP
- Паттерны, характерные для сканирования
7. Конфигурации: xray-core клиент
Безопасный inbound (SOCKS5 с аутентификацией)
{
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "password",
"accounts": [
{
"user": "xfl_a8b3c2d1",
"pass": "p_7e4f91d0c3b8a2e5f6"
}
],
"udp": false
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"],
"routeOnly": true
}
},
{
"tag": "http-in",
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {
"accounts": [
{
"user": "xfl_a8b3c2d1",
"pass": "p_7e4f91d0c3b8a2e5f6"
}
]
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls"],
"routeOnly": true
}
}
]
}Описание полей
| Поле | Значение | Почему |
|---|---|---|
"auth": "password" | Включает аутентификацию | Шпион не сможет подключиться без логина/пароля |
"accounts" | [{user, pass}] | Рандомные credentials — генерировать при каждом запуске |
"udp": false | Отключает UDP | UDP ASSOCIATE не аутентифицирует per-packet (RFC 1928) |
"listen": "127.0.0.1" | Только localhost | Никогда 0.0.0.0 — иначе прокси доступен из сети |
"sniffing" | Определение протоколов | Нужно для правильной маршрутизации |
Почему UDP отключён
Протокол SOCKS5 (RFC 1928, Section 7) аутентифицирует только TCP-соединение. Команда UDP ASSOCIATE создаёт UDP-ретранслятор, но сами UDP-датаграммы не содержат поля аутентификации:
UDP-датаграмма SOCKS5:
+-----+------+------+----------+----------+----------+
| RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+-----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+-----+------+------+----------+----------+----------+
↑ Нет поля для логина/пароля
xray-core и sing-box не реализуют per-packet аутентификацию для UDP. Поэтому при включённой SOCKS5-аутентификации UDP нужно отключать.
Без UDP — что перестанет работать?
- ❌ DNS через SOCKS UDP (решение: использовать DNS over HTTPS/TLS)
- ❌ QUIC через SOCKS UDP (решение: fallback на TCP)
- ✅ Обычный веб-браузинг работает (TCP)
- ✅ Telegram работает (TCP fallback)
- ✅ Стриминг работает (TCP)
«Но ведь пароль передаётся открытым текстом — шпион его перехватит?»
Нет. Это частый вопрос, основанный на предупреждении из RFC 1929: «Since the request carries the password in cleartext, this subnegotiation is not recommended for environments where ‘sniffing’ is possible.»
Но это предупреждение про сетевой сниффинг (Wi-Fi, Ethernet), а не про localhost.
На Android без root приложение НЕ может перехватить чужой TCP-трафик на localhost:
| Действие | Без root | Почему |
|---|---|---|
| Подключиться к чужому порту localhost | ✅ Может | Именно это и есть уязвимость |
| Читать чужой TCP-трафик на localhost | ❌ Не может | Нет raw socket без CAP_NET_RAW |
| Снифать loopback (tcpdump) | ❌ Не может | Требует root |
| Читать fd/память другого процесса | ❌ Не может | Android sandbox, разные UID |
| Видеть что порт открыт (/proc/net/tcp) | ✅ Может | Номера портов видны, данные — нет |
┌─────────────────────────────────────────────────┐
│ Android Kernel │
│ │
│ VPN Client (UID 10150) │
│ ├── TCP → 127.0.0.1:10808 │
│ └── "user=abc pass=xyz" ← plaintext │
│ ↑ │
│ Ядро: только UID 10150 видит эти данные │
│ │
│ Шпион (UID 10200) │
│ ├── connect() к :10808 ✅ → нужен пароль → ❌ │
│ └── read() чужого сокета → НЕВОЗМОЖНО │
└─────────────────────────────────────────────────┘
С root — да, всё плохо: tcpdump -i lo port 10808 -A увидит пароль. Но если у шпиона root, ему не нужен SOCKS5 — он читает конфиг-файлы напрямую, дампит память, контролирует iptables. Root = game over независимо от auth.
Вывод: SOCKS5 auth на localhost защищает от прямого подключения (основной вектор атаки). Перехват plaintext пароля между процессами без root невозможен. Для дополнительной безопасности: генерировать рандомный пароль при каждом запуске (чтобы не утёк из файла/лога).
8. Конфигурации: sing-box клиент
Безопасный inbound (mixed с аутентификацией)
{
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen": "127.0.0.1",
"listen_port": 2080,
"users": [
{
"username": "sb_d4c1a7f2",
"password": "p_9e2f5b83a1c7d0e4"
}
],
"set_system_proxy": false
}
]
}Без inbound вообще (если не нужен локальный прокси)
Если клиент использует только TUN-режим и вам не нужен локальный SOCKS5-прокси, удалите mixed inbound полностью. sing-box не создаёт его автоматически — это делают клиенты.
{
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"inet4_address": "172.19.0.1/30",
"auto_route": true,
"strict_route": true,
"stack": "system"
}
]
}Без mixed/socks inbound шпиону нечего сканировать на localhost.
Разница type: “socks” vs type: “mixed”
"socks" | "mixed" | |
|---|---|---|
| SOCKS4/4a | ✅ | ✅ |
| SOCKS5 | ✅ | ✅ |
| HTTP proxy | ❌ | ✅ |
users (auth) | ✅ | ✅ |
| Рекомендация | Если нужен только SOCKS | Если нужен SOCKS + HTTP |
9. Конфигурации: xray-core сервер
Безопасный серверный конфиг (VLESS + Reality + WARP + блокировка РФ)
{
"log": {
"loglevel": "warning"
},
"api": {
"tag": "api",
"services": ["StatsService"]
},
"stats": {},
"policy": {
"levels": {
"0": {
"statsUserUplink": true,
"statsUserDownlink": true
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true,
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443,
"protocol": "vless",
"settings": {
"clients": [
{
"id": "ваш-UUID",
"email": "user@example.com",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none"
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"show": false,
"dest": "www.microsoft.com:443",
"xver": 0,
"serverNames": ["www.microsoft.com", "microsoft.com"],
"privateKey": "ВАШЕ_ЗНАЧЕНИЕ_ИЗ_xray_x25519",
"shortIds": ["", "abcdef12"]
}
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
},
"tag": "vless-reality-in"
},
{
"listen": "127.0.0.1",
"port": 62789,
"protocol": "dokodemo-door",
"settings": {
"address": "127.0.0.1"
},
"tag": "api-in"
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
},
{
"protocol": "wireguard",
"settings": {
"secretKey": "ВАШЕ_WARP_PRIVATE_KEY",
"address": ["172.16.0.2/32", "fd01:5ca1:ab1e:823e::/128"],
"peers": [
{
"publicKey": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=",
"allowedIPs": ["0.0.0.0/0", "::/0"],
"endpoint": "engage.cloudflareclient.com:2408"
}
],
"reserved": [0, 0, 0],
"mtu": 1280
},
"tag": "warp-out"
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"inboundTag": ["api-in"],
"outboundTag": "api"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "block",
"ruleTag": "block-private"
},
{
"type": "field",
"ip": ["geoip:ru"],
"outboundTag": "block",
"ruleTag": "block-russia-ip"
},
{
"type": "field",
"domain": ["regexp:\\.ru$", "regexp:\\.рф$"],
"outboundTag": "block",
"ruleTag": "block-russia-domains"
},
{
"type": "field",
"protocol": ["bittorrent"],
"outboundTag": "block",
"ruleTag": "block-torrent"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "warp-out",
"ruleTag": "default-to-warp"
}
]
}
}Что делает каждое правило маршрутизации
| Правило | Что блокирует/перенаправляет | Зачем |
|---|---|---|
geoip:private → block | Частные IP (10.x, 192.168.x, 127.x) | Шпион не сможет «вернуться» на локалку через прокси |
geoip:ru → block | Российские IP | Шпион не свяжется с РКН через ваш VPN |
category-gov-ru → block | Госсайты РФ | Госсервисы не получат трафик через прокси |
regexp:\.ru$ → block | Все .ru домены | Дополнительная защита |
bittorrent → block | Торренты | Экономия ресурсов, правовая безопасность |
| default → warp-out | Весь остальной трафик | Маскировка выходного IP через WARP |
О API-сервисах
"services": ["StatsService"]Включён только StatsService для мониторинга трафика. НЕ включать:
- ❌
HandlerService— позволяет дампить конфиги (уязвимость Happ) - ❌
RoutingService— позволяет менять маршрутизацию - ❌
ReflectionService— позволяет обнаружить доступные API
10. Конфигурации: CloudFlare WARP на сервере
Зачем
Если шпион всё-таки узнает выходной IP через SOCKS5, он получит IP Cloudflare WARP, а не вашего сервера. Ваш реальный IP остаётся скрытым.
Получение WARP-ключей
Способ 1: wgcf
# Установка
curl -fsSL git.io/wgcf.sh | sudo bash
# Регистрация
wgcf register
wgcf generate
# Файл wgcf-profile.conf содержит:
# PrivateKey = ВАШЕ_WARP_PRIVATE_KEY
# PublicKey = bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=
# Address = 172.16.0.2/32, fd01:5ca1:ab1e:823e::/128
# Endpoint = engage.cloudflareclient.com:2408Способ 2: warp-go (если wgcf не работает)
wget -N https://gitlab.com/fscarmen/warp/-/raw/main/warp-go.sh
bash warp-go.shКонфиг WireGuard outbound для xray
{
"protocol": "wireguard",
"settings": {
"secretKey": "ЗНАЧЕНИЕ_ИЗ_PrivateKey",
"address": [
"172.16.0.2/32",
"fd01:5ca1:ab1e:823e::/128"
],
"peers": [
{
"publicKey": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=",
"allowedIPs": ["0.0.0.0/0", "::/0"],
"endpoint": "engage.cloudflareclient.com:2408"
}
],
"reserved": [0, 0, 0],
"mtu": 1280
},
"tag": "warp-out"
}Параметры:
secretKey— приватный ключ из WARP-регистрацииaddress— IP-адреса туннеля (IPv4 + IPv6)peers[0].publicKey— публичный ключ Cloudflare (фиксированный)endpoint— сервер Cloudflarereserved— обязательно[0, 0, 0](или значения из wgcf)mtu— 1280 для максимальной совместимости
Маршрутизация: весь трафик через WARP
{
"routing": {
"rules": [
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "warp-out"
}
]
}
}Маршрутизация: только определённый трафик через WARP
{
"routing": {
"rules": [
{
"type": "field",
"domain": ["openai.com", "netflix.com", "spotify.com"],
"outboundTag": "warp-out"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "direct"
}
]
}
}11. Конфигурации: блокировка geoip:ru на сервере
Полная блокировка (рекомендуется)
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:ru"],
"outboundTag": "block"
},
{
"type": "field",
"domain": [
"geosite:category-gov-ru",
"regexp:\\.ru$",
"regexp:\\.рф$"
],
"outboundTag": "block"
}
]
},
"outbounds": [
{
"protocol": "blackhole",
"tag": "block"
}
]
}Расширенная блокировка (с кастомными списками)
Проект runetfreedom/russia-v2ray-rules-dat предоставляет актуальные списки:
{
"routing": {
"rules": [
{
"type": "field",
"ip": ["ext:geoip_RU.dat:ru-block"],
"outboundTag": "block"
},
{
"type": "field",
"domain": ["ext:geosite_RU.dat:ru-block"],
"outboundTag": "block"
}
]
}
}Файлы geoip_RU.dat и geosite_RU.dat нужно скачать и поместить в директорию ресурсов xray (обычно рядом с geoip.dat).
Зачем блокировать geoip:ru на СЕРВЕРЕ
Если шпион на устройстве пользователя подключится к SOCKS5-прокси и попытается передать выходной IP на российский сервер (например, api.rkn.gov.ru), запрос уйдёт через VPN-сервер. Если на сервере geoip:ru → block, запрос будет заблокирован — шпион не сможет передать данные.
Без этой блокировки шпион может анализировать паттерн трафика, сопоставлять его с логами провайдера и вычислить ваш входной IP.
12. Конфигурации: маршрутизация «Всё кроме РФ» на клиенте
xray-core клиент
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": ["geosite:category-ru"],
"outboundTag": "direct",
"ruleTag": "ru-sites-direct"
},
{
"type": "field",
"ip": ["geoip:ru"],
"outboundTag": "direct",
"ruleTag": "ru-ip-direct"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct",
"ruleTag": "private-direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy",
"ruleTag": "default-proxy"
}
]
},
"outbounds": [
{
"protocol": "vless",
"tag": "proxy",
"settings": {
"vnext": [{
"address": "ВАШ_СЕРВЕР",
"port": 443,
"users": [{
"id": "ВАШ_UUID",
"encryption": "none",
"flow": "xtls-rprx-vision"
}]
}]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"fingerprint": "chrome",
"serverName": "www.microsoft.com",
"publicKey": "ВАШ_PUBLIC_KEY",
"shortId": ""
}
}
},
{
"protocol": "freedom",
"tag": "direct"
}
]
}sing-box клиент (v1.8+)
{
"route": {
"rules": [
{
"rule_set": ["geoip-ru", "geosite-ru"],
"outbound": "direct"
},
{
"rule_set": "geoip-private",
"outbound": "direct"
}
],
"rule_set": [
{
"tag": "geoip-ru",
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-ru.srs"
},
{
"tag": "geosite-ru",
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-category-ru.srs"
},
{
"tag": "geoip-private",
"type": "remote",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-private.srs"
}
],
"final": "proxy"
}
}sing-box v1.8+ использует
rule_setвместо устаревшихgeoip/geositeполей.
v2rayN — настройка пресета
- Откройте v2rayN → Настройки → Региональные пресеты
- Выберите Россия
- Выберите пресет «Все, кроме РФ» (RUv1-All except RF)
- Правила скачаются автоматически из:
- GeoIP:
runetfreedom/russia-v2ray-rules-dat - GeoSite:
nicknameisthekey/russia-v2ray-custom-routing-list
- GeoIP:
Зачем маршрутизация «Всё кроме РФ» на клиенте
- Российские сайты открываются напрямую (быстрее, стабильнее)
- Шпионский модуль в приложении не может отправить данные через VPN (geoip:ru → direct)
- Нет заблокированных ресурсов на российских IP (блокировки реализованы иначе)
13. Блокировка Happ на сервере подписок
Почему это критично
Happ включает xray API HandlerService без аутентификации. Через него можно:
- Дампить полный outbound-конфиг (ключи, IP, SNI)
- Узнать входной IP сервера (не только выходной)
- Потенциально расшифровать трафик
Один пользователь с Happ компрометирует ВЕСЬ сервер.
xray-core НЕ умеет фильтровать по UserAgent
xray-core не имеет встроенной возможности проверять HTTP UserAgent в VLESS/VMess inbound. Фильтрацию нужно делать на уровне сервера подписок (nginx/caddy).
Nginx: блокировка Happ по UserAgent
# /etc/nginx/conf.d/block-happ.conf
map $http_user_agent $is_happ {
default 0;
~*Happ 1;
~*Happ/ 1;
}
server {
listen 443 ssl http2;
server_name sub.example.com;
# SSL конфигурация...
# Блокировка Happ
if ($is_happ) {
return 403 "Access denied";
}
location /api/subscribe {
# ваша конфигурация подписок
proxy_pass http://127.0.0.1:8080;
}
}Caddy: блокировка Happ по UserAgent
sub.example.com {
@happ_blocked header_regexp User-Agent "(?i)Happ"
respond @happ_blocked 403
reverse_proxy /api/subscribe localhost:8080
}3x-ui: блокировка (если подписки через панель)
Если вы используете 3x-ui и раздаёте подписки через встроенный API — поставьте nginx/caddy перед панелью как reverse proxy и добавьте UserAgent-фильтр.
14. ГАЙД: v2rayNG — как защититься
Статус: v2rayNG 2.0.0 (апрель 2026) — SOCKS5-аутентификация НЕ поддерживается через UI
Текущая ситуация
v2rayNG — самый популярный xray-клиент на Android. Он создаёт локальный SOCKS5-прокси на 127.0.0.1:10808 без аутентификации. В UI приложения нет настройки для включения auth. Последняя версия (2.0.0 от 4 апреля 2026) эту проблему не исправляет.
Разработчики уведомлены 10 марта 2026 — на 7 апреля фикса нет.
Вариант A: Custom Config (частичная защита)
v2rayNG поддерживает импорт полного xray JSON-конфига. Можно попробовать включить auth через custom config:
Шаг 1. Создайте файл config.json на телефоне (через любой текстовый редактор):
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "socks-in",
"port": 10808,
"listen": "127.0.0.1",
"protocol": "socks",
"settings": {
"auth": "password",
"accounts": [
{
"user": "myuser_r4nd0m",
"pass": "mypass_s3cur3_x7k9"
}
],
"udp": false
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"],
"routeOnly": true
}
},
{
"tag": "http-in",
"port": 10809,
"listen": "127.0.0.1",
"protocol": "http",
"settings": {
"accounts": [
{
"user": "myuser_r4nd0m",
"pass": "mypass_s3cur3_x7k9"
}
]
}
}
],
"outbounds": [
{
"protocol": "vless",
"tag": "proxy",
"settings": {
"vnext": [
{
"address": "ВАШ_СЕРВЕР_IP",
"port": 443,
"users": [
{
"id": "ВАШ_UUID",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "reality",
"realitySettings": {
"fingerprint": "chrome",
"serverName": "www.microsoft.com",
"publicKey": "ВАШ_PUBLIC_KEY",
"shortId": ""
}
}
},
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:ru"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}Шаг 2. В v2rayNG: нажмите + → Custom config → Import custom config from locally → выберите файл.
Шаг 3. Нажмите на импортированный конфиг, чтобы активировать его. Нажмите V для подключения.
⚠️ Важное ограничение Custom Config
v2rayNG может перезаписать ваши inbound-настройки своими дефолтными. Это известная проблема:
- GitHub Issue #275: «Which parts of custom configs are honored?» — ответ: v2rayNG частично перезаписывает inbounds
- GitHub Issue #646: «Custom configurations don’t work properly»
- На практике v2rayNG может проигнорировать
"auth": "password"и выставить"noauth"
Как проверить: после подключения запустите POC-приложение. Если показывает «VPN not found» / «IP via proxy: -» → auth работает. Если показывает IP → auth перезаписан.
Вариант B: Смена порта (слабая защита)
Если custom config не работает:
- В v2rayNG: Настройки → прокрутите вниз → поле Local SOCKS5 port
- Замените
10808на нестандартный (например,47293) - HTTP-порт: аналогично замените
10809на другой
Почему это слабая защита:
- Скан всех 65535 портов — секунды
- Но в методичке Минцифры перечислены конкретные порты, и многие POC/шпионы проверяют только известные
- Это не защита, а усложнение — лучше чем ничего
Вариант C: Перейти на Husi (рекомендация)
Если для вас критична защита — перейти на Husi:
- Скачайте Husi: codeberg.org/xchacha20-poly1305/husi
- Экспортируйте ссылку из v2rayNG: долгое нажатие на сервер → Поделиться → скопируйте VLESS-ссылку
- В Husi: импортируйте VLESS-ссылку
- В настройках Husi: включите SOCKS5-аутентификацию (login/password)
- Проверьте POC — должен показать «VPN not found»
Вариант D: v2rayNG + AFWall+ (требует root)
Если у вас root:
# Узнать UID v2rayNG
dumpsys package com.v2ray.ang | grep userId
# Например: userId=10150
# Разрешить только v2rayNG подключаться к порту 10808
iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 10808 -m owner --uid-owner 10150 -j ACCEPT
iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 10808 -j DROP
iptables -I OUTPUT -p udp -d 127.0.0.1 --dport 10808 -m owner --uid-owner 10150 -j ACCEPT
iptables -I OUTPUT -p udp -d 127.0.0.1 --dport 10808 -j DROP
# То же для HTTP-порта
iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 10809 -m owner --uid-owner 10150 -j ACCEPT
iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 10809 -j DROPПравила iptables сбрасываются при перезагрузке. Используйте AFWall+ для автоматического применения при старте.
Сводка по v2rayNG
| Метод | Эффективность | Сложность | Root? |
|---|---|---|---|
| Custom config с auth | ⚠️ Может не работать (v2rayNG перезаписывает) | Средняя | Нет |
| Смена порта | 🟡 Слабая (скан все равно найдёт) | Лёгкая | Нет |
| Переход на Husi | ✅ Подтверждённая защита | Средняя | Нет |
| AFWall+ iptables | ✅ Полная защита | Сложная | Да |
| Отдельное устройство | ✅ Полная изоляция | — | Нет |
15. ГАЙД: NekoBox — как защититься
Статус: NekoBox 1.4.2 (февраль 2026) — SOCKS5-аутентификация НЕ поддерживается через UI Ядро: sing-box 1.12.19-neko-1 (CVE-2023-43644 исправлена) Nekoray (десктоп): прекращён, не поддерживается с 2026 года
Текущая ситуация
NekoBox создаёт mixed inbound (SOCKS4/4a/5 + HTTP) на 127.0.0.1:2080 без аутентификации. В UI нет настройки SOCKS5 auth. Порт 2080 нестандартный (не в методичке Минцифры), но это не защита — скан все равно найдёт.
Вариант A: Custom sing-box JSON (лучший вариант без root)
NekoBox позволяет кастомизировать sing-box конфигурацию. Нужно добавить аутентификацию в mixed inbound:
Шаг 1. В NekoBox: Настройки → Config Override (или Custom Config)
Шаг 2. Добавьте в секцию inbounds поле users:
{
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen": "127.0.0.1",
"listen_port": 2080,
"users": [
{
"username": "neko_x8f2a1",
"password": "p_k3m9v7c4b6n1"
}
],
"sniff": true,
"sniff_override_destination": false
}
]
}Шаг 3. Сохраните и перезапустите NekoBox.
Шаг 4. Проверьте POC-приложением:
- «VPN not found» = auth работает ✅
- Показывает IP = auth не применился ❌
⚠️ Важное ограничение
NekoBox генерирует sing-box JSON автоматически из UI-настроек. При обновлении конфигурации (смена сервера, обновление подписки) кастомные inbound могут быть перезаписаны. Проверяйте auth после каждого изменения.
Вариант B: Удалить mixed inbound полностью
Если вы используете NekoBox только в TUN-режиме (весь трафик через VPN), локальный SOCKS5-прокси вам не нужен. Можно попробовать отключить его:
- В custom config: удалите mixed inbound из
inbounds - Оставьте только TUN inbound:
{
"inbounds": [
{
"type": "tun",
"tag": "tun-in",
"inet4_address": "172.19.0.1/30",
"auto_route": true,
"strict_route": true
}
]
}Без mixed inbound шпиону нечего сканировать на localhost — прокси не существует.
Ограничение: некоторые приложения (Telegram, Firefox с ручной настройкой прокси) могут требовать SOCKS5-прокси напрямую. Без mixed inbound они не смогут подключиться через VPN.
Вариант C: Смена порта
- В NekoBox: Настройки → Basic Settings → Mixed Port
- Замените
2080на нестандартный (например,38741) - Перезапустите
Та же оговорка: слабая защита, скан найдёт. Но лучше чем дефолтный 2080.
Вариант D: Переход на Husi
Husi — тоже sing-box клиент, конфиги совместимы:
- Скачайте Husi: codeberg.org/xchacha20-poly1305/husi/releases
- Экспортируйте конфигурации из NekoBox (подписки, VLESS-ссылки)
- Импортируйте в Husi
- Включите SOCKS5-аутентификацию в настройках Husi
- Проверьте POC
Миграция: автоматического инструмента нет. Подписки импортируются через ссылки. Routing-правила придётся настроить заново.
Вариант E: AFWall+ iptables (требует root)
# Узнать UID NekoBox
dumpsys package moe.nb4a | grep userId
# Например: userId=10200
# Разрешить только NekoBox на порт 2080
iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 2080 -m owner --uid-owner 10200 -j ACCEPT
iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 2080 -j DROP
iptables -I OUTPUT -p udp -d 127.0.0.1 --dport 2080 -m owner --uid-owner 10200 -j ACCEPT
iptables -I OUTPUT -p udp -d 127.0.0.1 --dport 2080 -j DROPNekoray (десктоп) — прекращён
Nekoray (десктопная версия) больше не поддерживается с 2026 года. Разработчик: «不再维护,自寻替代品» (больше не обслуживается, ищите альтернативы).
Альтернативы на десктопе:
- v2rayN (Windows) — пресет «Все, кроме РФ», ручная правка JSON
- sing-box CLI (все платформы) — полный контроль конфигурации
- XrayFluent (Windows) — будет исправлен
Сводка по NekoBox
| Метод | Эффективность | Сложность | Root? |
|---|---|---|---|
| Custom JSON с users | ⚠️ Работает, но может сброситься при обновлении | Средняя | Нет |
| Удаление mixed inbound | ✅ Нет прокси = нечего сканировать | Средняя | Нет |
| Смена порта | 🟡 Слабая | Лёгкая | Нет |
| Переход на Husi | ✅ Подтверждённая защита | Средняя | Нет |
| AFWall+ iptables | ✅ Полная защита | Сложная | Да |
16. ГАЙД: Clash/mihomo — как защититься
Ядро: mihomo (Clash Meta) — поддерживает SOCKS5 auth нативно
Проблема: по дефолтуskip-auth-prefixesвключает127.0.0.1/8→ localhost обходит аутентификацию
Клиенты: ClashMeta Android, FlClash, Clash Verge Rev, ClashX Meta
Текущая ситуация
mihomo/Clash — единственное ядро с двумя важными преимуществами:
-
По дефолту
socks-portвыключен (# socks-port: 7891— закомментировано). Дефолтный режим — rule-based (правила маршрутизации), без локального SOCKS5-прокси. Шпиону нечего сканировать → безопасен из коробки. -
Аутентификация поддерживается нативно через YAML-конфиг — проще чем в xray/sing-box.
НО: если вы сами включили socks-port (раскомментировали строку), возникают два сценария:
- Без
authentication→ прокси полностью открыт → уязвим - С
authentication, но дефолтнымskip-auth-prefixes: [127.0.0.1/8]→ localhost обходит пароль → всё ещё уязвим
Поле skip-auth-prefixes по дефолту содержит 127.0.0.1/8 и ::1/128 — это by design, localhost считается «доверенной» зоной. Для защиты от шпионского ПО нужно убрать localhost из skip-auth-prefixes.
Фундаментальное отличие от xray/sing-box
| xray/sing-box клиенты | mihomo/Clash клиенты | |
|---|---|---|
| SOCKS5 по дефолту | ✅ Всегда включён | ❌ Выключен (TUN-only) |
| Auth по дефолту | noauth (открыт) | N/A (порт не открыт) |
| Риск из коробки | 🔴 Высокий | 🟢 Низкий |
| Если включить socks-port | Открыт без auth | Открыт без auth (аналогично) |
| Нативная поддержка auth | Да, но через JSON | Да, через YAML (проще) |
Вывод: если вы используете Clash/mihomo в дефолтном TUN-режиме без socks-port — вы не уязвимы. Проблема возникает только если вы сами включили SOCKS5-порт.
Дефолтные порты mihomo
| Порт | Тип | Описание |
|---|---|---|
7890 | HTTP(S) | HTTP-прокси |
7891 | SOCKS5 | SOCKS5-прокси |
10801 (или 7892) | Mixed | HTTP + SOCKS5 на одном порту |
7892 | Redirect | Прозрачный прокси |
7893 | TProxy | Только Linux/Android |
Уязвимая конфигурация (дефолт)
# ❌ УЯЗВИМО: localhost обходит auth
port: 7890
socks-port: 7891
mixed-port: 10801
authentication:
- "user:password"
# Вот в чём проблема — дефолтные значения:
skip-auth-prefixes:
- 127.0.0.1/8
- ::1/128Даже с authentication шпион с localhost подключится без пароля через skip-auth-prefixes.
Безопасная конфигурация (Вариант 1: глобальная)
port: 7890
socks-port: 7891
mixed-port: 10801
allow-lan: false # Не слушать на 0.0.0.0
bind-address: 127.0.0.1 # Только localhost
authentication:
- "clash_x8f2a:p_k3m9v7c4b6"
# ✅ КРИТИЧНО: убрать localhost из skip-auth-prefixes
skip-auth-prefixes: [] # Пустой массив = auth для ВСЕХ⚠️ Побочный эффект: некоторые приложения (Telegram, браузеры с настроенным прокси) могут потребовать ввод логина/пароля для подключения к локальному прокси. Если используете TUN-режим — это не проблема.
Безопасная конфигурация (Вариант 2: per-listener)
Более гибкий подход — настроить auth на уровне отдельных listeners:
listeners:
- name: socks-local
type: socks
port: 7891
listen: 127.0.0.1
users:
- username: clash_local
password: s3cur3_p4ss_x7k9
- name: mixed-local
type: mixed
port: 10801
listen: 127.0.0.1
udp: true
users:
- username: clash_local
password: s3cur3_p4ss_x7k9
- name: http-local
type: http
port: 7890
listen: 127.0.0.1
users:
- username: clash_local
password: s3cur3_p4ss_x7k9⚠️ Верификацией установлено: per-listener
usersперезаписывает глобальныйauthentication, но может НЕ перезаписыватьskip-auth-prefixes. Глобальныйskip-auth-prefixesприменяется на уровне сети и может обходить даже per-listener auth. Рекомендация: всегда устанавливатьskip-auth-prefixes: []глобально, даже при использовании per-listenerusers.
Инструкция по клиентам
ClashMeta for Android (v2.11.25+):
- Откройте конфиг (Profile → Edit)
- Добавьте
authenticationиskip-auth-prefixes: [] - Или используйте
listenersсusers - Сохраните и перезапустите
Clash Verge Rev (Windows/macOS/Linux):
- Профиль → правый клик → «Open File»
- Отредактируйте YAML
- Или: Settings → Merge Config → добавьте override
FlClash:
- Аналогично — редактирование YAML профиля
- Документация: flclash.cc
Известные CVE Clash/mihomo
| CVE | Описание | Затронуто |
|---|---|---|
| CVE-2024-5732 | Clash ≤ 0.20.1 Windows — обход аутентификации на Proxy Port (удалённый доступ) | Clash (не mihomo) |
| CVE-2025-50505 | Clash Verge Rev — уязвимость API | Clash Verge Rev |
| mihomo-party macOS | Привилегированный UNIX-сокет /tmp/mihomo-party-helper.sock с world-rw правами, без аутентификации → перехват трафика | mihomo-party < 1.8.1 |
Безопасность API mihomo
# config.yaml
external-controller: 127.0.0.1:9090
secret: "ваш_секретный_токен"⚠️ Важно: API-аутентификация через
Authorization: Bearer {secret}НЕ проверяется при подключении через Unix-сокет или Windows named pipe. Защита — только file permissions (0600).
Сводка по Clash/mihomo
| Метод | Эффективность | Сложность |
|---|---|---|
authentication + skip-auth-prefixes: [] | ✅ Полная защита | Лёгкая (3 строки YAML) |
Per-listener users | ✅ Полная, гибкая | Средняя |
| Только смена порта | 🟡 Слабая | Лёгкая |
| TUN без SOCKS-прокси | ✅ Нет прокси = нечего сканировать | Средняя |
Вывод: Clash/mihomo — лучшая ситуация из всех ядер. Auth поддерживается нативно, фикс — 3 строки в YAML. Нужно только убрать 127.0.0.1/8 из skip-auth-prefixes.
17. Фаерволы на Android: что реально работает
Без root: почти ничего
| Приложение | Блокирует localhost? | Почему |
|---|---|---|
| NetGuard (VPN-based) | ❌ Нет | Android VPN API не перехватывает localhost-трафик. VPN видит только трафик через сетевые интерфейсы, а loopback (127.0.0.1) — внутренний |
| RethinkDNS (VPN-based) | ❌ Нет | Та же причина — VPN API не покрывает localhost |
| Blokada (VPN-based) | ❌ Нет | Аналогично |
| AdGuard (VPN-based) | ❌ Нет (localhost) | Но блокирует скрипты Meta Pixel/Яндекс.Метрики на уровне DNS/HTTP — полезно против трекинга |
Почему VPN-based фаерволы не помогают:
┌─────────────────────────────────────────────────────┐
│ Android │
│ │
│ Приложение A ──→ 127.0.0.1:10808 ──→ xray/sing-box│
│ ↑ │
│ │ ← Это localhost, не проходит через VPN API │
│ │ │
│ NetGuard/RethinkDNS (VPN) перехватывают ТОЛЬКО: │
│ eth0, wlan0, rmnet0 (реальные интерфейсы) │
│ ↓ │
│ Приложение B ──→ google.com ──→ [VPN перехватывает]│
└─────────────────────────────────────────────────────┘
Loopback-интерфейс — внутренний, он не маршрутизируется через VPN-тоннель. VPN API от Google by design не перехватывает localhost.
С root: AFWall+ (iptables)
AFWall+ (github.com/ukanth/afwall) использует iptables напрямую в ядре Linux, минуя Android VPN API. Это единственный способ заблокировать localhost-доступ на Android.
Установка:
- Убедитесь что есть root (Magisk/KernelSU)
- Установите AFWall+ из F-Droid или GitHub
- Откройте → разрешите root-доступ
- Режим: Whitelist (разрешить только выбранным)
Настройка кастомных правил:
В AFWall+: Меню → Set custom script → добавьте:
# Защита SOCKS5-порта v2rayNG (10808)
# Разрешить только UID v2rayNG (замените 10150 на реальный UID)
iptables -I "afwall" -p tcp -d 127.0.0.1 --dport 10808 -m owner --uid-owner 10150 -j ACCEPT
iptables -I "afwall" -p tcp -d 127.0.0.1 --dport 10808 -j REJECT
# Защита HTTP-порта v2rayNG (10809)
iptables -A "afwall" -p tcp -d 127.0.0.1 --dport 10809 -m owner --uid-owner 10150 -j ACCEPT
iptables -A "afwall" -p tcp -d 127.0.0.1 --dport 10809 -j REJECT
# Защита mixed-порта NekoBox (2080)
# (замените 10200 на реальный UID NekoBox)
iptables -A "afwall" -p tcp -d 127.0.0.1 --dport 2080 -m owner --uid-owner 10200 -j ACCEPT
iptables -A "afwall" -p tcp -d 127.0.0.1 --dport 2080 -j REJECTКак узнать UID приложения:
# Через adb
adb shell dumpsys package com.v2ray.ang | grep userId
# userId=10150
adb shell dumpsys package moe.nb4a | grep userId
# userId=10200Или в AFWall+ UI: каждое приложение показывает свой UID в скобках.
Важно: правила iptables сбрасываются при перезагрузке. AFWall+ автоматически применяет кастомный скрипт при каждом старте — поэтому используйте именно AFWall+, а не ручные iptables.
Без root: что хоть немного помогает
-
AdGuard DNS — блокирует скрипты Meta Pixel и Яндекс.Метрики, которые могут обнаруживать VPN через localhost. Не защищает от прямого сканирования шпионским модулем, но убирает трекинг из браузера.
-
Brave Browser — с 2022 года блокирует запросы к localhost из веб-страниц. Защищает от трекинга Meta/Яндекс через браузер, но не от нативного шпионского приложения.
-
Отдельное устройство — физическая изоляция. Российское ПО на одном телефоне, VPN на другом. Loopback не пересекается между устройствами.
18. FAQ: hev-socks5-tunnel, Karing, Husi, v2rayN
Q: Как включить auth, если я не владелец подписки?
A: Владение подпиской НЕ имеет значения. SOCKS5-аутентификация на local inbound — это чисто клиентская настройка. Она защищает локальный прокси на ВАШЕМ устройстве от других приложений. Сервер подписки об этом даже не знает.
СЕРВЕР (владелец подписки) ВАШЕ УСТРОЙСТВО (вы контролируете)
┌──────────────────────┐ ┌──────────────────────────────┐
│ VLESS Reality inbound│◄──────────│ xray outbound (VLESS) │
│ Вы НЕ контролируете │ туннель │ │
└──────────────────────┘ │ SOCKS5 inbound ← ВОТ ЭТО │
│ localhost:10808 ВАШЕ │
│ auth: password ← МЕНЯТЬ ТУТ │
└──────────────────────────────┘
Реальная проблема: при обновлении подписки некоторые клиенты перегенерируют конфиг и могут сбросить ваши кастомные inbound-настройки. Но это зависит от клиента:
- v2rayN (Windows) ✅ — хранит inbound-настройки (
Config.Inbound) вguiNConfig.jsonотдельно от подписок (SQLiteguiN.db). Auth не сбрасывается при обновлении подписки. Архитектура подтверждена через DeepWiki и исходный код. - Clash/mihomo ✅ —
authenticationиskip-auth-prefixesв глобальной секции config.yaml.proxy-providers(подписки) обновляют только список прокси, не трогая глобальный конфиг. Clash Verge Rev дополнительно защищает глобальные настройки через Merge-профили. - Husi (Android) ⚠️ — вероятно сохраняет auth в настройках приложения, но документально не подтверждено. Рекомендуется проверить auth после каждого обновления подписки.
- v2rayNG (Android) ⚠️ — custom config проблематичен. Известные проблемы: нет документации какие секции custom config реально применяются — пользователи вынуждены спрашивать (#275 — «How to use custom config feature?»), краши при кастомных DNS-конфигурациях (#1911 — «V2ray Crash When using custom config»), игнорирование кастомных DNS при включённом local DNS (#3670). Прямых доказательств перезаписи auth при обновлении подписки не найдено, но стабильность custom config не гарантирована — не рекомендуется как единственный метод защиты. Надёжнее перейти на Husi.
Q: Нужно ли просить админа сервера что-то менять?
A: Для защиты local inbound — нет. Но для полной защиты рекомендуется попросить админа:
- Настроить раздельные входной/выходной IP (или WARP)
- Заблокировать geoip:ru на outbound
- Заблокировать Happ по UserAgent
Q: v2rayNG использует hev-socks5-tunnel — в нём та же уязвимость?
A: hev-socks5-tunnel — это библиотека tun2socks, которая сама по себе поддерживает SOCKS5-аутентификацию (username/password). Уязвимость не в библиотеке, а в том что v2rayNG не включает аутентификацию на SOCKS5 inbound xray-core. hev-socks5-tunnel подключается к xray-core inbound 127.0.0.1:10808 с noauth — и шпион может сделать то же самое.
Чтобы исправить:
- v2rayNG должен добавить
"auth": "password"в xray inbound - И передать те же credentials в конфиг hev-socks5-tunnel
- Пока этого нет — v2rayNG уязвим
Q: Karing уязвим?
A: Скорее всего да. Karing использует ядро sing-box и создаёт три mixed inbound на 127.0.0.1:3065, 127.0.0.1:3066, 127.0.0.1:3067. В UI Karing нет настройки SOCKS5 auth. Защита возможна через ручную правку JSON-конфига — добавить users с паролем ко всем трём inbound. Подробная инструкция с JSON-примером — см. раздел 2, «О Karing (sing-box)».
Порты 3065-3067 нестандартные (не в методичке Минцифры), но скан всех портов — секунды.
Q: Husi — действительно безопасен?
A: Husi — единственный Android-клиент с подтверждённой SOCKS5-аутентификацией в UI. POC-приложение не смогло обнаружить прокси при включённой аутентификации. НО:
- Убедитесь что используется sing-box v1.4.5+ — в более ранних есть CVE-2023-43644 (обход auth)
- UDP ASSOCIATE всё равно не аутентифицируется per-packet — лучше отключить
- Аутентификация — не панацея, а барьер. Сложную атаку она не остановит
Q: В v2rayN на Windows можно включить SOCKS5 auth?
A: Да, начиная с v7.0+, через ручную правку конфига:
- Настройки → параметры ядра → кастомный inbound
- Изменить
"auth": "noauth"на"auth": "password" - Добавить
"accounts": [{"user": "xxx", "pass": "yyy"}] - Сохранить и перезапустить
Также в v2rayN 7.0+ есть пресет «Все, кроме РФ» в региональных настройках.
Q: Как v2rayN реализует «Все, кроме РФ»?
A: Настройки → Региональные пресеты → Россия. Скачивает правила из:
- runetfreedom/russia-v2ray-rules-dat — geoip
- nicknameisthekey/russia-v2ray-custom-routing-list — geosite
Правила: geoip:ru → direct, geosite:ru → direct, всё остальное → proxy.
19. CVE-2023-43644: обход аутентификации sing-box
Критическая уязвимость
CVE-2023-43644 — Missing Authentication for Critical Function в sing-box SOCKS5 inbound.
| CVSS | 9.1 (Critical) |
| Затронуто | sing-box < 1.4.5, sing-box < 1.5.0-rc.5 |
| Исправлено | sing-box ≥ 1.4.5, sing-box ≥ 1.5.0-rc.5 |
| Суть | Атакующий может обойти SOCKS5-аутентификацию специально сформированным запросом |
| Источник | GHSA-r5hm-mp3j-285g |
Техническая суть
В функции HandleConnection0 (файл protocol/socks/handshake.go) обработка запросов продолжалась даже после неудачной аутентификации. Не проверялся код статуса аутентификации.
Кого затрагивает
- Husi — если использует старую версию sing-box (до 1.4.5)
- Karing — если использует старую версию sing-box
- SFA — если использует старую версию sing-box
- Все клиенты на базе sing-box с SOCKS5 inbound
Как проверить версию
В sing-box клиенте: настройки → о программе → версия ядра. Должна быть ≥ 1.4.5.
Рекомендация
Даже если вы включили SOCKS5 auth — обновите sing-box. На старых версиях аутентификация обходится.
20. Чеклист действий
Для пользователей
- Удалить Happ (если установлен)
- Перейти на клиент с SOCKS5 auth (Husi, SFA, saeeddev94/xray)
- Включить аутентификацию на SOCKS5 inbound
- Отключить UDP в SOCKS5 (или убедиться что не критично)
- Включить маршрутизацию «Все, кроме РФ» на клиенте
- Российское ПО — на отдельное устройство (Android)
- На Windows: настроить Firewall по процессам
- Убедиться что sing-box ≥ 1.4.5 (если на sing-box)
Для администраторов серверов
- Настроить раздельные входной/выходной IP (или WARP)
- Заблокировать geoip:ru на outbound
- Заблокировать geoip:private на outbound
- Заблокировать .ru/.рф домены на outbound
- Заблокировать Happ по UserAgent на сервере подписок
- Убрать HandlerService из API (оставить только StatsService)
- Убрать ReflectionService из API
- Включить WARP как outbound (маскировка выходного IP)
- Мониторить запросы к ifconfig.me/ipinfo.io через прокси
Для разработчиков клиентов
- Включить
"auth": "password"по умолчанию - Генерировать рандомные credentials при каждом запуске
- Отключить UDP в SOCKS5 или реализовать per-packet auth
- Рандомизировать порт (не стандартные 10808/2080/1080)
- Слушать только на
127.0.0.1(никогда0.0.0.0) - Не включать HandlerService в xray API
- Обновить sing-box до ≥ 1.4.5 (CVE-2023-43644)
Источники
Документация протоколов
- RFC 1928 — SOCKS Protocol Version 5
- RFC 1929 — Username/Password Auth for SOCKS V5
- xray-core SOCKS inbound
- xray-core Routing
- xray-core Freedom outbound
- xray-core WireGuard outbound
- xray-core API
- xray-core WARP guide
- sing-box SOCKS inbound
- sing-box Mixed inbound
- sing-box Route rules
Уязвимости и исследования
- CVE-2023-43644 — sing-box SOCKS5 auth bypass
- localmess.github.io — Meta/Яндекс localhost-трекинг
- Habr: Критическая уязвимость VLESS клиентов
- POC: per-app-split-bypass
Клиенты
GeoIP/GeoSite правила
- runetfreedom/russia-v2ray-rules-dat
- nicknameisthekey/russia-v2ray-custom-routing-list
- Loyalsoldier/v2ray-rules-dat