Практическое руководство: защита VPN от localhost-атаки

Дата: 7 апреля 2026
Контекст: Уязвимость VLESS-клиентов + эксплуатация localhost Meta/Яндексом
Аудитория: Пользователи VPN, администраторы серверов, разработчики клиентов
Связанные заметки:


Оглавление

  1. Суть проблемы за 30 секунд
  2. Проверенные клиенты: кто уязвим, кто нет
  3. Что делать пользователям Android
  4. Что делать пользователям Windows
  5. Что делать пользователям iOS
  6. Что делать администраторам серверов
  7. Конфигурации: xray-core клиент
  8. Конфигурации: sing-box клиент
  9. Конфигурации: xray-core сервер
  10. Конфигурации: CloudFlare WARP на сервере
  11. Конфигурации: блокировка geoip:ru на сервере
  12. Конфигурации: маршрутизация «Всё кроме РФ» на клиенте
  13. Блокировка Happ на сервере подписок
  14. ГАЙД: v2rayNG — как защититься
  15. ГАЙД: NekoBox — как защититься
  16. ГАЙД: Clash/mihomo — как защититься
  17. Фаерволы на Android: что реально работает
  18. FAQ: hev-socks5-tunnel, Karing, Husi, v2rayN
  19. CVE-2023-43644: обход аутентификации sing-box
  20. Чеклист действий

1. Суть проблемы за 30 секунд

Все VPN-клиенты на базе xray/sing-box создают на телефоне/компьютере локальный SOCKS5-прокси без пароля. Любое приложение-шпион (Яндекс, WB, Ozon, гос.приложения) может:

  1. Найти этот прокси за секунды (скан портов localhost)
  2. Подключиться без пароля
  3. Узнать IP вашего VPN-сервера
  4. Передать 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.0xray10808❌ Нет в UI. ⚠️ Custom config — ненадёжно (v2rayNG может перезаписать inbound)🟡 УязвимПерейти на Husi; или AFWall+ (root)
Hiddify 4.1.1sing-box + xray?❌ Нет в UI🟡 УязвимПерейти на Husi/SFA
NekoBox 1.4.2sing-box 1.12.192080❌ Нет в UI. ⚠️ Custom JSON — возможно, но сбрасывается при обновлении🟡 УязвимПерейти на Husi; или удалить mixed inbound
Npv Tunnelxray?❌ Нет🟡 УязвимПерейти на Husi/SFA
v2RayTun 5.19.64xray?⚠️ Ядро поддерживает, UI — неизвестно🟡 Скорее уязвимУточнить у разработчика
Happxray?❌ + API HandlerService без auth🔴 УДАЛИТЬ НЕМЕДЛЕННОДамп ключей, IP, SNI
Karingsing-box3067⚠️ Ядро поддерживает, в UI нет настройки🟡 Скорее уязвимПроверить custom JSON
Exclavesing-box?✅ Да (через конфиг)🟢 Можно настроитьНастроить auth в конфиге
Husi 1.1.0sing-box (dun)?Да, есть в UI🟢 РекомендованВключить auth в настройках
SFA 1.13.6sing-box?✅ Да (JSON)🟢 Можно настроитьРучная правка JSON
saeeddev94/xrayxray?✅ Да (JSON + UI)🟢 Можно настроитьF-Droid, настроить auth
v2RayTun 5.20.67xray?❌ Нет в UI. Разработчик обещал фикс (март 2026), пока нет🟡 УязвимЖдать фикса или перейти. ⚠️ Шлёт домены подписок на свои сервера
ClashMeta Android 2.11.25mihomo✅ Да (YAML). По дефолту socks-port выключен (TUN-only) → прокси нет → нечего сканировать🟢 Безопасен по дефолтуЕсли включили socks-port — добавить auth + убрать skip-auth-prefixes
FlClashmihomo✅ Да (YAML). Аналогично — дефолт TUN-only🟢 Безопасен по дефолтуАналогично ClashMeta
Incy 2.0.8xray 26.3.27?⚠️ Ядро поддерживает, UI-настройка auth не документирована🟡 Вероятно уязвимНужна проверка — closed-source-подобный
anet 0.4.2Собственный (Rust/ASTP)Не применимо🟢 Не уязвимНет SOCKS5/HTTP прокси на localhost. Чистый TUN через собственный протокол

Windows / Desktop

КлиентЯдроПортSOCKS5 authСтатусЧто делать
v2rayN 7.20.2xray/sing-box10808✅ Да (JSON + UI)🟢 Можно настроитьВключить auth + Windows Firewall
Nekoraysing-box/xray?❌ Нет в UI🔴 Заброшен (2026)Перейти на Throne / v2rayN / Clash Verge Rev
Throne 1.1.1 (март 2026)sing-box (основной) + xray (для VLESS)2080⚠️ Дефолтный mixed нельзя отключить, но можно создать кастомный inbound с auth🟡 Уязвим по дефолту, можно настроитьСоздать кастомный inbound с auth; заблокировать дефолтный фаерволом
XrayFluentxray10808❌ Нет🟡 УязвимБудет исправлено
Karing (Windows)sing-box3067/3066⚠️ Ядро поддерживает, UI-настройка не подтверждена🟡 Вероятно уязвимПроверить custom JSON
Clash Verge Revmihomo✅ Да (YAML). По дефолту TUN-only, socks-port выключен🟢 Безопасен по дефолтуЕсли включили socks-port — добавить auth + убрать skip
ClashX Meta (macOS)mihomo✅ Да (YAML). Аналогично🟢 Безопасен по дефолтуАналогично
Incy (Desktop) 2.0.8xray 26.3.27?⚠️ Не документировано🟡 Нужна проверка

iOS

КлиентЯдроПортSOCKS5 authСтатусЧто делать
Happxray?❌ + API без auth🔴 УДАЛИТЬУдалено из российского App Store; в других регионах может быть доступно, но фикса не будет
V2BOX 5.3.4xray?❌ Нет подтверждения🟡 Скорее уязвимНет решения
RabbitHole 1.3.0? (closed-source)?⚠️ Неизвестно❓ Нужна проверкаClosed-source, поддерживает SOCKS5 — нужна проверка POC
ShadowrocketiOS VPN framework⚠️ Вероятно не применимо (iOS sandbox)🟢/❓ Скорее не уязвим, нужна проверка POCiOS 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: Немедленно

  1. Удалить Happ — HandlerService без аутентификации позволяет дампить ваши ключи и IP сервера. Один пользователь с Happ компрометирует весь сервер.

  2. Перейти на клиент с SOCKS5 auth:

  3. Включить аутентификацию в настройках клиента (см. конфиги ниже)

Приоритет 2: Серверная защита

  1. Попросить администратора сервера настроить раздельные IP (входной ≠ выходной)
  2. Убедиться что на сервере заблокирован geoip:ru на outbound
  3. Использовать маршрутизацию «Всё кроме РФ» на клиенте

Приоритет 3: Изоляция

  1. Российское ПО — на отдельное устройство. Knox/Shelter/Island НЕ изолируют loopback.
  2. Если есть 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 DROP

    UID приложения: 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

  1. Заблокировать доступ к порту 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 Firewall Block имеет приоритет по умолчанию, поэтому нужно настроить через GPO или использовать netsh с правильным порядком.

  2. Альтернатива — 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: Конфигурация клиента

  1. Включить SOCKS5 auth в конфиге (даже на Windows это полезно):

    В v2rayN: настройки → custom inbound config → изменить "auth": "noauth" на "auth": "password" + добавить "accounts".

  2. Использовать маршрутизацию «Всё кроме РФ»:

    В v2rayN 7.0+: Настройки → Региональные пресеты → Россия → Всё кроме РФ. Автоматически скачивает правила из runetfreedom/russia-v2ray-rules-dat.


5. Что делать пользователям iOS

Ситуация на iOS самая сложная:

  • Большинство клиентов удалено из App Store → обновлений не будет
  • Нет root → нет iptables
  • Нет возможности редактировать inbound JSON в большинстве клиентов

Что можно сделать

  1. Удалить Happ — самый опасный клиент, удалён из App Store, фикса не будет
  2. Использовать клиенты с поддержкой custom JSON — если такие ещё установлены
  3. Защита на стороне сервера — единственная реальная опция:
    • Раздельные входной/выходной 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Отключает UDPUDP 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 — сервер Cloudflare
  • reserved — обязательно [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 — настройка пресета

  1. Откройте v2rayN → НастройкиРегиональные пресеты
  2. Выберите Россия
  3. Выберите пресет «Все, кроме РФ» (RUv1-All except RF)
  4. Правила скачаются автоматически из:
    • GeoIP: runetfreedom/russia-v2ray-rules-dat
    • GeoSite: nicknameisthekey/russia-v2ray-custom-routing-list

Зачем маршрутизация «Всё кроме РФ» на клиенте

  1. Российские сайты открываются напрямую (быстрее, стабильнее)
  2. Шпионский модуль в приложении не может отправить данные через VPN (geoip:ru → direct)
  3. Нет заблокированных ресурсов на российских 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 configImport 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 не работает:

  1. В v2rayNG: Настройки → прокрутите вниз → поле Local SOCKS5 port
  2. Замените 10808 на нестандартный (например, 47293)
  3. HTTP-порт: аналогично замените 10809 на другой

Почему это слабая защита:

  • Скан всех 65535 портов — секунды
  • Но в методичке Минцифры перечислены конкретные порты, и многие POC/шпионы проверяют только известные
  • Это не защита, а усложнение — лучше чем ничего

Вариант C: Перейти на Husi (рекомендация)

Если для вас критична защита — перейти на Husi:

  1. Скачайте Husi: codeberg.org/xchacha20-poly1305/husi
  2. Экспортируйте ссылку из v2rayNG: долгое нажатие на сервер → Поделиться → скопируйте VLESS-ссылку
  3. В Husi: импортируйте VLESS-ссылку
  4. В настройках Husi: включите SOCKS5-аутентификацию (login/password)
  5. Проверьте 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-прокси вам не нужен. Можно попробовать отключить его:

  1. В custom config: удалите mixed inbound из inbounds
  2. Оставьте только 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: Смена порта

  1. В NekoBox: НастройкиBasic SettingsMixed Port
  2. Замените 2080 на нестандартный (например, 38741)
  3. Перезапустите

Та же оговорка: слабая защита, скан найдёт. Но лучше чем дефолтный 2080.

Вариант D: Переход на Husi

Husi — тоже sing-box клиент, конфиги совместимы:

  1. Скачайте Husi: codeberg.org/xchacha20-poly1305/husi/releases
  2. Экспортируйте конфигурации из NekoBox (подписки, VLESS-ссылки)
  3. Импортируйте в Husi
  4. Включите SOCKS5-аутентификацию в настройках Husi
  5. Проверьте 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 DROP

Nekoray (десктоп) — прекращён

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/8localhost обходит аутентификацию
Клиенты: ClashMeta Android, FlClash, Clash Verge Rev, ClashX Meta

Текущая ситуация

mihomo/Clash — единственное ядро с двумя важными преимуществами:

  1. По дефолту socks-port выключен (# socks-port: 7891 — закомментировано). Дефолтный режим — rule-based (правила маршрутизации), без локального SOCKS5-прокси. Шпиону нечего сканировать → безопасен из коробки.

  2. Аутентификация поддерживается нативно через 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

ПортТипОписание
7890HTTP(S)HTTP-прокси
7891SOCKS5SOCKS5-прокси
10801 (или 7892)MixedHTTP + SOCKS5 на одном порту
7892RedirectПрозрачный прокси
7893TProxyТолько 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-listener users.

Инструкция по клиентам

ClashMeta for Android (v2.11.25+):

  1. Откройте конфиг (Profile → Edit)
  2. Добавьте authentication и skip-auth-prefixes: []
  3. Или используйте listeners с users
  4. Сохраните и перезапустите

Clash Verge Rev (Windows/macOS/Linux):

  1. Профиль → правый клик → «Open File»
  2. Отредактируйте YAML
  3. Или: Settings → Merge Config → добавьте override

FlClash:

  1. Аналогично — редактирование YAML профиля
  2. Документация: flclash.cc

Известные CVE Clash/mihomo

CVEОписаниеЗатронуто
CVE-2024-5732Clash ≤ 0.20.1 Windows — обход аутентификации на Proxy Port (удалённый доступ)Clash (не mihomo)
CVE-2025-50505Clash Verge Rev — уязвимость APIClash 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.

Установка:

  1. Убедитесь что есть root (Magisk/KernelSU)
  2. Установите AFWall+ из F-Droid или GitHub
  3. Откройте → разрешите root-доступ
  4. Режим: 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: что хоть немного помогает

  1. AdGuard DNS — блокирует скрипты Meta Pixel и Яндекс.Метрики, которые могут обнаруживать VPN через localhost. Не защищает от прямого сканирования шпионским модулем, но убирает трекинг из браузера.

  2. Brave Browser — с 2022 года блокирует запросы к localhost из веб-страниц. Защищает от трекинга Meta/Яндекс через браузер, но не от нативного шпионского приложения.

  3. Отдельное устройство — физическая изоляция. Российское ПО на одном телефоне, 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 отдельно от подписок (SQLite guiN.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-приложение не смогло обнаружить прокси при включённой аутентификации. НО:

  1. Убедитесь что используется sing-box v1.4.5+ — в более ранних есть CVE-2023-43644 (обход auth)
  2. UDP ASSOCIATE всё равно не аутентифицируется per-packet — лучше отключить
  3. Аутентификация — не панацея, а барьер. Сложную атаку она не остановит

Q: В v2rayN на Windows можно включить SOCKS5 auth?

A: Да, начиная с v7.0+, через ручную правку конфига:

  1. Настройки → параметры ядра → кастомный inbound
  2. Изменить "auth": "noauth" на "auth": "password"
  3. Добавить "accounts": [{"user": "xxx", "pass": "yyy"}]
  4. Сохранить и перезапустить

Также в v2rayN 7.0+ есть пресет «Все, кроме РФ» в региональных настройках.

Q: Как v2rayN реализует «Все, кроме РФ»?

A: Настройки → Региональные пресеты → Россия. Скачивает правила из:

Правила: 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.

CVSS9.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)

Источники

Документация протоколов

Уязвимости и исследования

Клиенты

GeoIP/GeoSite правила

Серверные панели