Localhost-атака: как Meta, Яндекс и шпионское ПО эксплуатируют loopback-интерфейс
Дата: 7 апреля 2026
Статус: Верифицировано — исследование USENIX Security 26, POC опубликован
Оригинал исследования: localmess.github.io
Научная статья: Bridges to Self: Silent Web-to-App Tracking on Mobile via Localhost (USENIX Security 26)
POC (Meta/Яндекс): github.com/localmess/localhost-abuse
POC (VLESS обход split tunneling): github.com/runetfreedom/per-app-split-bypass-poc
Оглавление
- Корневая проблема: архитектура loopback в ОС
- Яндекс: localhost-трекинг с 2017 года
- Meta (Facebook): WebRTC STUN SDP Munging
- Побочный эффект: утечка истории браузера
- VLESS/xray/sing-box: та же дыра, другой вектор
- Happ: бэкдор через xray API HandlerService
- Протокол SOCKS5: как работает аутентификация (RFC 1928/1929)
- xray-core: настройка аутентификации SOCKS5 inbound
- sing-box: настройка аутентификации SOCKS/mixed inbound
- Сводная таблица атак и защит
- Как защитить VPN-клиенты
- Статус браузеров и патчей
- Хронология событий
- Источники
1. Корневая проблема: архитектура loopback в ОС
Все описанные атаки — трекинг Meta, трекинг Яндекса, и уязвимость VLESS-клиентов — эксплуатируют одну и ту же фундаментальную архитектурную слабость: неконтролируемый доступ к loopback-интерфейсу (127.0.0.1).
Как устроен loopback
┌─────────────────────────────────────────────────────┐
│ Android / Windows │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ App A │ │ App B │ │ Browser │ │
│ │ (Яндекс) │ │ (Шпион) │ │ (Chrome) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ 127.0.0.1 (loopback) │ │
│ │ Общий для ВСЕХ процессов устройства │ │
│ │ НЕ маршрутизируется через VPN/TUN │ │
│ │ НЕ изолирован между профилями │ │
│ │ НЕ требует специальных разрешений │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Что ОС разрешает на loopback
| Действие | Android | Windows | iOS |
|---|---|---|---|
| Слушать порт на localhost | ✅ Любое приложение с INTERNET | ✅ Любой процесс | ✅ Ограничено фоновым режимом |
| Подключиться к чужому порту на localhost | ✅ Без ограничений | ✅ Без ограничений | ✅ Технически возможно |
| Сканировать все порты localhost | ✅ За секунды | ✅ За секунды | ⚠️ Ограничено фоном |
| Изоляция между профилями (Knox/Shelter) | ❌ Loopback общий | N/A | N/A |
| Изоляция VPN/TUN от loopback | ❌ Loopback вне VPN | ❌ Loopback вне TUN | ❌ |
| JavaScript из браузера → localhost | ✅ Без согласия | ✅ Без согласия | ✅ |
Почему loopback не изолирован
Это by design, а не баг ОС. Приложениям легитимно нужен localhost для:
- Межпроцессного взаимодействия (IPC)
- Локальных серверов разработки
- Коммуникации между компонентами одного приложения
Проблема в том, что никто не предусмотрел, что это станет вектором атаки для трекинга и обнаружения VPN.
2. Яндекс: localhost-трекинг с 2017 года
Архитектура атаки
┌─────────────────────┐ ┌──────────────────────────┐
│ Мобильный браузер │ │ Нативное приложение │
│ (Chrome/Firefox) │ │ Яндекса (Карты/Браузер) │
│ │ │ │
│ ┌────────────────┐ │ │ ┌─────────────────────┐ │
│ │ Яндекс.Метрика │ │ │ │ SDK Яндекс.Метрики │ │
│ │ JavaScript │──┼─────┼─▶│ Слушает TCP порты: │ │
│ │ │ │ HTTP│ │ 29009, 30102 (HTTP) │ │
│ │ │ │ на │ │ 29010, 30103 (HTTPS) │ │
│ │ │◀─┼─────┼──│ │ │
│ └───────┬────────┘ │200OK│ │ Отвечает: AAID + │ │
│ │ │+IDs │ │ зашифрованные ID │ │
│ ▼ │ │ └─────────────────────┘ │
│ Отправляет ID на │ │ │
│ mc.yango.com │ │ │
└─────────────────────┘ └──────────────────────────┘
Пошаговый процесс
Шаг 1. Пользователь открывает приложение Яндекса (Карты, Навигатор, Браузер, Поиск, Go). Приложение уходит в фон и запускает фоновый сервис, слушающий порты.
Шаг 2. Приложение обращается к startup.mobile.yandex.net для получения конфигурации:
{
"ports": [30102, 29009],
"first_delay_seconds": 259200
}Параметр first_delay_seconds задаёт задержку перед началом прослушивания (~3 дня после установки). Вероятно, для маскировки — не начинать слушать сразу после установки.
Шаг 3. Пользователь открывает браузер, заходит на сайт с Яндекс.Метрикой (~3 млн сайтов по BuiltWith, ~575K по HTTP Archive).
Шаг 4. JavaScript Яндекс.Метрики запрашивает зашифрованные параметры с серверов Яндекса.
Шаг 5. Скрипт отправляет HTTP/HTTPS-запросы на localhost:
http://127.0.0.1:29009/...https://yandexmetrica.com:30103/...← домен резолвится в127.0.0.1
Ключевой трюк: домен
yandexmetrica.comсконфигурирован резолвиться в127.0.0.1. Это позволяет использовать HTTPS (порты 29010, 30103) — запросы выглядят как обычные HTTPS к «настоящему» домену, но идут на localhost. Обнаружить это стандартными средствами практически невозможно.
Шаг 6. SDK Яндекс.Метрики в нативном приложении получает запрос и отвечает HTTP 200 OK с телом, содержащим Base64-закодированные бинарные данные:
- Android Advertising ID (AAID)
- Google Advertising ID
- UUID, специфичные для Яндекса
Шаг 7. JavaScript получает эти идентификаторы и отправляет их на mc.yango.com вместе с зашифрованными параметрами и информацией о посещённой странице.
Результат: Яндекс связывает эфемерную веб-сессию (кука, IP, User-Agent) с постоянным идентификатором устройства (AAID). Пользователь деанонимизирован на всех сайтах с Яндекс.Метрикой.
Проверенные приложения Яндекса
| Приложение | Package name | Тестовая версия | Порты |
|---|---|---|---|
| Яндекс.Карты | ru.yandex.yandexmaps | 23.5.0 | 29009, 30102 |
| Яндекс.Навигатор | ru.yandex.yandexnavi | 23.5.0 | 29009, 30102 |
| Яндекс.Браузер | com.yandex.browser | 25.4.1.100 | 29009, 30102 |
| Яндекс.Поиск | com.yandex.searchapp | 25.41 | 29009, 30102 |
| Метро в Европе | ru.yandex.metro | 3.7.3 | 29009, 30102 |
| Яндекс Go: Такси | ru.yandex.taxi | 5.24.1 | 29009, 30102 |
Что обходит этот метод
Метод работает даже если пользователь:
- ❌ Не залогинен в Яндексе в браузере
- ❌ Использует режим инкогнито
- ❌ Очистил куки и данные браузера
- ❌ Сбросил рекламный идентификатор Android
3. Meta (Facebook): WebRTC STUN SDP Munging
Архитектура атаки
┌─────────────────────┐ ┌──────────────────────────┐
│ Мобильный браузер │ │ Facebook / Instagram │
│ (Chrome/Edge) │ │ (нативное приложение) │
│ │ │ │
│ ┌────────────────┐ │ │ ┌─────────────────────┐ │
│ │ Meta Pixel JS │ │ │ │ Фоновый сервис │ │
│ │ │──┼─────┼─▶│ TCP: 12387, 12388 │ │
│ │ SDP Munging: │ │WebRTC│ │ UDP: 12580-12585 │ │
│ │ ice-ufrag = │ │STUN │ │ (STUN) │ │
│ │ _fbp cookie │ │ │ │ UDP: 12586-12591 │ │
│ │ │ │ │ │ (TURN) │ │
│ └───────┬────────┘ │ │ └─────────────────────┘ │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ Отправляет _fbp на │ │ GraphQL → graph. │
│ facebook.com/tr │ │ facebook.com/graphql │
│ + URL, событие, │ │ + _fbp + Device ID │
│ метаданные │ │ + Facebook Account ID │
└─────────────────────┘ └──────────────────────────┘
Техника SDP Munging
SDP Munging — это манипуляция полями SDP (Session Description Protocol) в WebRTC-соединении для передачи произвольных данных.
Meta Pixel вставляет значение куки _fbp в поле ice-ufrag SDP-предложения. При WebRTC handshake генерируется STUN Binding Request, который отправляется на localhost UDP-порты 12580-12585. Нативное приложение Facebook/Instagram слушает эти порты и извлекает _fbp из STUN-пакета.
Почему это невидимо:
- WebRTC STUN-трафик не отображается в Chrome DevTools
- Нет HTTP-запросов, которые можно было бы перехватить в инспекторе
- Сетевая активность происходит на уровне UDP, ниже HTTP-слоя
Эволюция техник Meta
| Метод | Начало | Конец | Порты | Обнаружимость |
|---|---|---|---|---|
| HTTP | Сентябрь 2024 | Октябрь 2024 | TCP 12387 | Средняя (видно в DevTools) |
| WebSocket | Ноябрь 2024 | Январь 2025 | TCP 12387 | Средняя |
| WebRTC STUN + SDP Munging | Ноябрь 2024 | Июнь 2025 | UDP 12580-12585 | Очень низкая |
| WebRTC TURN (без SDP Munging) | Май 2025 | Июнь 2025 | UDP 12586-12591 | Низкая |
Meta 4 раза сменила технику за 9 месяцев, каждый раз усложняя обнаружение.
О куке _fbp
- Third most popular first-party cookie в интернете (Web Almanac 2024)
- Присутствует на ~25% из топ-1М сайтов
- Срок жизни: 90 дней
- First-party cookie = разная на каждом сайте → нельзя использовать для кросс-сайтового трекинга
- НО: через localhost-атаку Meta связывает разные
_fbpс одним устройством → кросс-сайтовый трекинг становится возможен
Масштаб
| Регион | Сайтов с Meta Pixel (из 100K) | Без согласия пользователя |
|---|---|---|
| США | 17,223 | 13,468 (78.2%) |
| Европа | 15,677 | 11,890 (75.8%) |
| Регион | Сайтов с Яндекс.Метрикой (из 100K) | Без согласия пользователя |
|---|---|---|
| США | 1,312 | 1,095 (83.5%) |
| Европа | 1,260 | 1,064 (84.4%) |
Пошаговый процесс Meta
- Пользователь открывает Facebook/Instagram → приложение уходит в фон → слушает TCP 12387/12388 и UDP 12580-12585
- Пользователь открывает браузер → заходит на сайт с Meta Pixel (~5.8 млн сайтов)
- Meta Pixel JS читает куку
_fbp - JS создаёт WebRTC peer connection с SDP Munging:
ice-ufrag = <_fbp value> - STUN Binding Request с
_fbpв поле ice-ufrag летит на127.0.0.1:12580-12585 - Facebook/Instagram получают
_fbp - Приложение отправляет GraphQL на
graph.facebook.com/graphql:_fbp+ Device ID + Facebook Account ID - Meta связывает: веб-сессия ↔ устройство ↔ аккаунт Facebook
4. Побочный эффект: утечка истории браузера
Поскольку Яндекс использует обычные HTTP-запросы (не WebRTC), любое стороннее приложение, слушающее те же порты, может перехватить эти запросы и прочитать заголовок Origin, который содержит URL посещённого сайта.
Кто уязвим
| Браузер | Яндекс (утечка истории) | Meta (утечка истории) | Защита |
|---|---|---|---|
| Chrome | ✅ Уязвим | ✅ Уязвим | Chrome 137+ — блокировка портов и SDP Munging |
| Firefox | ✅ Уязвим | ❌ Не затронут | В разработке |
| Edge | ✅ Уязвим | ✅ Уязвим | Неизвестно |
| Brave | ❌ Защищён | ❌ Защищён | С 2022: blocklist + запрос согласия на localhost |
| DuckDuckGo | ⚠️ Минимально | ❌ Защищён | Blocklist (3 домена Яндекса отсутствовали — исправлено) |
Работает в режиме инкогнито: ДА. Инкогнито не влияет на доступ к localhost.
POC-демонстрация
Исследователи создали POC-приложение (github.com/localmess/localhost-abuse), которое:
- Слушает порты 29009, 30102 (как приложения Яндекса)
- Перехватывает HTTP-запросы от Яндекс.Метрики
- Извлекает
Originзаголовок - Отображает список посещённых сайтов в реальном времени
5. VLESS/xray/sing-box: та же дыра, другой вектор
Связь с Meta/Яндекс
Meta и Яндекс доказали: localhost на Android не изолирован, и это можно массово эксплуатировать. Уязвимость VLESS-клиентов — тот же фундаментальный баг, но другой вектор атаки.
| Аспект | Meta/Яндекс | VLESS-клиенты |
|---|---|---|
| Что на localhost | Трекинг-сервис приложения | SOCKS5-прокси без аутентификации |
| Кто атакует | JavaScript с веб-страницы | Шпионский модуль в приложении |
| Что получает атакующий | Device ID (AAID) + связь с аккаунтом | Выходной IP VPN-сервера |
| Цель | Деанонимизация + таргетированная реклама | Блокировка VPN-серверов |
| Фундаментальная проблема | Loopback не изолирован | Loopback не изолирован |
| Knox/Shelter помогает? | Нет | Нет |
| Инкогнито помогает? | Нет | N/A |
Как эксплуатируется VLESS
┌──────────────────┐
│ Шпионский модуль │ (Яндекс/WB/Ozon/гос.приложение)
│ в приложении │
└────────┬─────────┘
│ 1. Скан портов localhost (секунды)
▼
┌──────────────────────┐
│ 127.0.0.1:10808 │ SOCKS5 без аутентификации
│ (xray-core inbound) │
└────────┬─────────────┘
│ 2. SOCKS5 handshake (method 0x00 = NO AUTH)
│ 3. CONNECT ifconfig.me:80
▼
┌──────────────────┐
│ xray-core │ → VPN-сервер → ifconfig.me
│ outbound │ ← ответ: "185.xxx.xxx.xxx"
└──────────────────┘
│ 4. Шпион получает выходной IP
▼
РКН блокирует сервер
Почему per-app split tunneling не помогает
VpnService (TUN)
┌──────────────┐
Обычное приложение ──▶ │ tun2socks │ ──▶ xray SOCKS5 ──▶ VPN-сервер
└──────────────┘ ▲
│
Шпион ──▶ 127.0.0.1:10808 ────────────────────────┘
(минуя VpnService)
VpnService перехватывает трафик через TUN-интерфейс. Но подключение к 127.0.0.1 не проходит через TUN — это внутренний loopback. Split tunneling бессилен.
Почему Knox/Shelter/Island не помогают
Android Private Spaces изолируют файловую систему и VpnService, но loopback-интерфейс общий для всех профилей. Процесс из Knox видит 127.0.0.1:10808 основного профиля.
Контекст: методичка Минцифры РФ
Минцифры разослало аккредитованным IT-компаниям методичку по обнаружению VPN. Характерные порты из методички:
| Тип | Порты |
|---|---|
| SOCKS | 1080, 9000, 5555, 16000-16100 |
| HTTP | 80, 443, 3128, 3127, 8000, 8080, 8081, 8888 |
| Прозрачные Proxy | 80, 443, 4080, 7000/7044, 8082, 12345 |
| Tor | 9050, 9051, 9150 |
Стандартные порты xray (10808) и nekobox (2080) пока не указаны, но полный скан 65535 портов на localhost — секунды.
Список уязвимых VLESS-клиентов
| Клиент | Платформа | Ядро | SOCKS5 auth | Статус |
|---|---|---|---|---|
| Happ | iOS | xray | ❌ | 🔴 Особо опасен (API без auth) |
| v2RayTun | Android | xray | ❌ | 🟡 Обещали исправить |
| V2BOX | iOS/Android | xray | ❌ | 🟡 Уязвим |
| v2rayNG | Android | xray | ❌ | 🟡 Уязвим (порт 10808) |
| Hiddify | Android/iOS | sing-box | ❌ | 🟡 Уязвим |
| Exclave | iOS | xray | ❌ | 🟡 Уязвим |
| Npv Tunnel | Android | xray | ❌ | 🟡 Уязвим |
| Neko Box | Android | sing-box | ❌ | 🟡 Уязвим (порт 2080) |
| Husi | Android | sing-box | ✅ | 🟢 Можно настроить |
| SFA (sing-box) | Android | sing-box | ✅ | 🟢 Ручной JSON |
| saeeddev94/xray | Android | xray | ✅ | 🟢 F-Droid, ручной JSON |
6. Happ: бэкдор через xray API HandlerService
Клиент Happ — отдельная категория. Помимо уязвимого SOCKS5, он включает xray gRPC API с HandlerService БЕЗ аутентификации.
Сервисы xray API
| Сервис | Назначение | Опасность |
|---|---|---|
| StatsService | Статистика трафика, онлайн-пользователи | Низкая |
| LoggerService | Управление логированием | Низкая |
| HandlerService | Добавление/удаление inbound/outbound, дамп конфигов, управление пользователями | 🔴 Критическая |
| RoutingService | Управление маршрутизацией | Средняя |
| ReflectionService | Список доступных API | Средняя |
gRPC методы HandlerService
| Метод | Что делает |
|---|---|
AddInbound | Добавить новый inbound |
RemoveInbound | Удалить inbound |
AlterInbound | Изменить inbound |
AddOutbound | Добавить outbound |
RemoveOutbound | Удалить outbound |
AlterOutbound | Изменить outbound |
GetInboundUsers | Получить пользователей (включая ключи) |
Цепочка атаки
Шпион → скан портов → gRPC API (без auth)
→ ReflectionService → список методов
→ HandlerService → дамп outbound конфига
→ ключ шифрования + IP сервера + SNI
→ [+ вторая уязвимость конфигурации] → расшифровка трафика
Позиция Happ: заявили, что API нужен «для статистики». Это ложь — для статистики достаточно StatsService. При смене конфига Happ перезапускает xray целиком, а не использует HandlerService.
Рекомендация: немедленно удалить Happ. Заблокировать Happ/* по UserAgent на серверах подписок. Один пользователь с Happ компрометирует весь сервер.
7. Протокол SOCKS5: как работает аутентификация (RFC 1928/1929)
Зачем нужна аутентификация SOCKS5
Без аутентификации SOCKS5-прокси — это открытая дверь: кто угодно может подключиться и маршрутизировать через него трафик. В контексте VPN это означает, что шпионский модуль может:
- Обнаружить прокси сканированием портов
- Подключиться без учётных данных
- Узнать выходной IP VPN-сервера
- Гонять через прокси произвольный трафик
Аутентификация добавляет барьер: без знания логина/пароля подключение отклоняется.
Фаза 1: Согласование метода (RFC 1928)
Клиент → Сервер:
+-----+----------+----------+
| VER | NMETHODS | METHODS |
+-----+----------+----------+
| 0x05| 0x01 | 0x02 | ← «Я хочу SOCKS5, предлагаю метод 0x02 (пароль)»
+-----+----------+----------+
Сервер → Клиент:
+-----+--------+
| VER | METHOD |
+-----+--------+
| 0x05| 0x02 | ← «Принято, используем метод 0x02»
+-----+--------+
Методы аутентификации:
0x00— NO AUTHENTICATION REQUIRED ← уязвимый вариант0x01— GSSAPI0x02— USERNAME/PASSWORD ← безопасный вариант0xFF— нет подходящего метода (отказ)
Фаза 2: Аутентификация по логину/паролю (RFC 1929)
Клиент → Сервер:
+-----+------+----------+------+----------+
| VER | ULEN | UNAME | PLEN | PASSWD |
+-----+------+----------+------+----------+
| 0x01| 0x08 | "user123"| 0x0C | "pass456abc"|
+-----+------+----------+------+----------+
Сервер → Клиент:
+-----+--------+
| VER | STATUS |
+-----+--------+
| 0x01| 0x00 | ← 0x00 = успех, любое другое = отказ
+-----+--------+
Поля:
VER=0x01(версия подпротокола аутентификации)ULEN= длина логина (1-255 байт)UNAME= логинPLEN= длина пароля (1-255 байт)PASSWD= пароль
⚠️ Важно: логин и пароль передаются открытым текстом. RFC 1929: «Since the request carries the password in cleartext, this subnegotiation is not recommended for environments where ‘sniffing’ is possible and practical.» Но для localhost это не проблема — трафик не выходит за пределы устройства.
Фаза 3: Запрос (после успешной аутентификации)
Клиент → Сервер:
+-----+-----+------+------+----------+----------+
| VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+-----+-----+------+------+----------+----------+
| 0x05| 0x01| 0x00 | 0x01 | IP addr | port |
+-----+-----+------+------+----------+----------+
CMD:
0x01— CONNECT (TCP)0x02— BIND0x03— UDP ASSOCIATE
Проблема UDP ASSOCIATE
UDP ASSOCIATE (CMD = 0x03) создаёт UDP-ретранслятор. Но: после успешной TCP-аутентификации UDP-датаграммы не проходят повторную аутентификацию.
UDP-датаграмма (RFC 1928, Section 7):
+-----+------+------+----------+----------+----------+
| RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
+-----+------+------+----------+----------+----------+
| 2 | 1 | 1 | Variable | 2 | Variable |
+-----+------+------+----------+----------+----------+
В заголовке UDP-датаграммы нет поля для аутентификации. RFC 1928 допускает опциональное шифрование/целостность, но большинство реализаций (включая xray и sing-box) не реализуют per-packet auth для UDP.
Вывод: для полной защиты от localhost-атак UDP нужно отключать или блокировать фаерволом.
8. xray-core: настройка аутентификации SOCKS5 inbound
Уязвимая конфигурация (как есть сейчас)
{
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
}
}
]
}Проблемы:
"auth": "noauth"— любой процесс на устройстве может подключиться"udp": true— UDP тоже доступен без ограничений- Порт 10808 — стандартный, легко угадывается
Безопасная конфигурация
{
"inbounds": [
{
"tag": "socks-in",
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "password",
"accounts": [
{
"user": "xf_a8b3c2d1",
"pass": "7e4f91d0c3b8a2e5"
}
],
"udp": false
}
}
]
}Что изменилось:
"auth": "password"— требуется аутентификация"accounts"— массив учётных записей{user, pass}"udp": false— UDP отключён (убирает вектор атаки через UDP ASSOCIATE)
Поля конфигурации xray SOCKS inbound
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
auth | "noauth" / "password" | "noauth" | Режим аутентификации |
accounts | [{user, pass}] | — | Учётные записи (только при auth: "password") |
udp | boolean | false | Включение UDP ASSOCIATE |
ip | string | auto | IP для UDP-ответов |
userLevel | number | 0 | Уровень политик |
Рекомендации для xray-клиентов
- Генерировать credentials при каждом запуске — рандомные user/pass, не хардкодить
- Отключить UDP (
"udp": false) — UDP не аутентифицируется per-packet - Слушать только на 127.0.0.1 — никогда на
0.0.0.0 - Рандомизировать порт — не использовать стандартный 10808
- Не включать HandlerService в API — достаточно StatsService/LogService
9. sing-box: настройка аутентификации SOCKS/mixed inbound
Уязвимая конфигурация
{
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen": "0.0.0.0",
"listen_port": 2080
}
]
}Проблемы:
- Нет массива
users— аутентификации нет "listen": "0.0.0.0"— доступен из сети (ещё хуже чем localhost)- Порт 2080 — стандартный для nekobox
Безопасная конфигурация
{
"inbounds": [
{
"type": "mixed",
"tag": "mixed-in",
"listen": "127.0.0.1",
"listen_port": 2080,
"users": [
{
"username": "sb_d4c1a7f2",
"password": "9e2f5b83a1c7d0e4"
}
]
}
]
}Поля конфигурации sing-box SOCKS/mixed inbound
| Поле | Тип | Описание |
|---|---|---|
type | "socks" / "mixed" | mixed поддерживает SOCKS4/4a/5 + HTTP |
listen | string | Адрес прослушивания |
listen_port | number | Порт |
users | [{username, password}] | Учётные записи (без этого поля — без auth) |
set_system_proxy | boolean | Автоматическая системная прокси-настройка |
Разница SOCKS vs Mixed
| Возможность | type: "socks" | type: "mixed" |
|---|---|---|
| SOCKS4/4a | ✅ | ✅ |
| SOCKS5 | ✅ | ✅ |
| HTTP-прокси | ❌ | ✅ |
users (аутентификация) | ✅ | ✅ (для SOCKS и HTTP) |
set_system_proxy | ❌ | ✅ |
Позиция разработчика sing-box
Разработчик sing-box считает эту проблему «skill issue» клиентов: sing-box не создаёт mixed inbound автоматически — это делают конкретные клиенты и генераторы конфигов. Если не добавлять mixed inbound в конфиг, прокси не будет.
10. Сводная таблица атак и защит
| Механизм | Против Meta/Яндекс | Против VLESS-скана | Против Happ API |
|---|---|---|---|
| SOCKS5 auth (password) | N/A | ✅ Блокирует подключение | N/A |
| Отключение UDP | N/A | ✅ Убирает вектор | N/A |
| Рандомный порт | N/A | ⚠️ Замедляет, не блокирует | N/A |
| iptables/root | ✅ Можно заблокировать | ✅ Можно заблокировать | ✅ |
| Knox/Shelter/Island | ❌ Не помогает | ❌ Не помогает | ❌ |
| Режим инкогнито | ❌ Не помогает | N/A | N/A |
| Очистка куки | ❌ Не помогает | N/A | N/A |
| Brave Browser | ✅ Blocklist + consent | N/A | N/A |
| Chrome 137+ | ✅ Блокировка портов | N/A | N/A |
| Отключение HandlerService | N/A | N/A | ✅ Убирает API |
| Блокировка Happ по UserAgent | N/A | N/A | ✅ На сервере |
| Отдельное устройство | ✅ Физическая изоляция | ✅ | ✅ |
| Windows Firewall (process) | ✅ | ✅ | ✅ |
11. Как защитить VPN-клиенты
Для разработчиков клиентов
- SOCKS5 auth по умолчанию — генерировать рандомные credentials при каждом запуске, передавать их только доверенным приложениям
- Отключить UDP в SOCKS5 inbound — UDP ASSOCIATE не поддерживает per-packet auth
- Рандомизировать порт — не стандартные 10808/2080/1080
- Только 127.0.0.1 — никогда 0.0.0.0
- Не включать xray API HandlerService — для статистики хватит StatsService/LogService
- На Android с root: добавить iptables-правила, ограничивающие доступ к порту по UID процесса
Для пользователей Android
- Использовать клиенты с SOCKS5 auth: Husi, SFA, saeeddev94/xray
- Удалить Happ немедленно
- Держать российское ПО на отдельном устройстве
- Не полагаться на Knox/Shelter — loopback не изолирован
- С root:
iptables -I OUTPUT -p tcp -d 127.0.0.1 --dport 10808 -j DROPдля всех кроме VPN-клиента
Для пользователей Windows
- Windows Firewall: правила на блокировку доступа к портам 10808/10809 для всех процессов кроме xray.exe и доверенных
- В xray routing:
process nameдля разрешённых приложений - Рандомный порт вместо стандартного 10808
Для администраторов серверов
- Раздельные входной/выходной IP — утечка выходного не компрометирует входной
- CloudFlare WARP на выходе — маскировка выходного IP
- geoip:ru → block на сервере — шпион не сможет связать трафик
- Блокировка Happ по UserAgent
Happ/*
Маршрутизация
На клиенте:
geoip:ru → direct (российские IP напрямую)
geoip:private → direct (локальные сети)
остальное → proxy (через VPN)
На сервере:
geoip:ru → block (запретить выход на РФ)
остальное → freedom (разрешить)
12. Статус браузеров и патчей
Meta Pixel
| Дата | Событие |
|---|---|
| Сентябрь 2024 | Начало HTTP-коммуникации с localhost |
| Ноябрь 2024 | Переход на WebSocket, затем WebRTC STUN |
| Май 2025 | Добавлен WebRTC TURN (обход блокировки SDP Munging) |
| 26 мая 2025 | Chrome 137 — блокировка SDP Munging и абьюзимых портов |
| 3 июня 2025 | Meta полностью прекратила localhost-трекинг, код удалён |
Яндекс.Метрика
| Дата | Событие |
|---|---|
| Февраль 2017 | Начало HTTP-коммуникации с localhost |
| Май 2018 | Добавлен HTTPS (порты 29010, 30103) |
| Июнь 2025 | Яндекс сообщил о прекращении использования и удалении функции |
Браузеры
| Браузер | Статус | Детали |
|---|---|---|
| Chrome 137+ | ✅ Исправлено | Блокировка портов + SDP Munging |
| Brave 1.54+ | ✅ Защищён с 2022 | Blocklist + localhost consent |
| DuckDuckGo | ✅ Исправлено | Обновлён blocklist |
| Firefox 139 | 🟡 В разработке | Патч в процессе |
| Edge | ❌ Неизвестно | Chromium-based, должен следовать за Chrome |
VLESS-клиенты
На 7 апреля 2026 ни один массовый VLESS-клиент не добавил SOCKS5 аутентификацию, несмотря на уведомление 10 марта 2026.
13. Хронология событий
| Дата | Событие |
|---|---|
| Февраль 2017 | Яндекс начинает localhost-трекинг через HTTP |
| Май 2018 | Яндекс добавляет HTTPS-канал (yandexmetrica.com → 127.0.0.1) |
| 2022 | Brave добавляет защиту localhost (consent + blocklist) |
| Сентябрь 2024 | Meta начинает localhost-трекинг через HTTP |
| Ноябрь 2024 | Meta переходит на WebRTC STUN SDP Munging |
| 10 марта 2026 | runetfreedom уведомляет разработчиков VLESS-клиентов об уязвимости SOCKS5 |
| Апрель 2026 | Минцифры рассылает методичку по обнаружению VPN |
| 7 апреля 2026 | Публикация уязвимости VLESS-клиентов, ни один клиент не исправлен |
| 26 мая 2025 | Chrome 137 блокирует SDP Munging и абьюзимые порты |
| 3 июня 2025 | Meta полностью удаляет код localhost-трекинга |
| Июнь 2025 | Публикация исследования USENIX Security 26 (localmess.github.io) |
14. Источники
Исследование Meta/Яндекс (LocalMess)
- localmess.github.io — оригинал
- Bridges to Self — PDF статья USENIX Security 26
- POC: localhost-abuse
- The Register: Meta halts localhost tracking
- AdGuard: Meta and Yandex abuse localhost
- Android Police: researchers catch Meta
- Habr: перевод статьи
Уязвимость VLESS
- ntc.party: оригинальная публикация runetfreedom
- Habr: Критическая уязвимость VLESS клиентов
- POC: per-app-split-bypass
- XTLS BBS: Malicious Activity of Closed-Source Xray Clients
Документация протоколов
- RFC 1928 — SOCKS Protocol Version 5
- RFC 1929 — Username/Password Auth for SOCKS V5
- xray-core SOCKS inbound
- xray-core API
- sing-box SOCKS inbound
- sing-box Mixed inbound