TL;DR для тех, кому лень читать
-
MAX (ex-TamTam) от VK при каждом открытии тайно определяет ваш внешний IP и VPN через 6 сервисов (Yandex, Amazon, Mail.ru и др.)
-
URL этих сервисов спрятаны в коде как массивы чисел — чтобы их нельзя было найти поиском и быстрым анализом сетевого трафика
-
Приложение проверяет доступность российских сервисов, включая gosuslugi.ru (Госуслуги интегрированы в MAX, но проверяется именно доступность, а не функции)
-
Определяет VPN и отправляет информацию на сервер. В коде звонков — виджет «Лучше без VPN» (найден в коде, динамически не проверял)
-
В коде присутствуют домены main.telegram.org и mmg.whatsapp.net — в текущей версии не используются, но сам факт их наличия рядом с активными проверками примечателен
-
Все данные привязаны к вашему аккаунту MAX (OK.ru ID): IP + оператор + VPN-статус + время
Если интересно — ниже подробный разбор. Если хочется увидеть сам код — листайте до «Часть 2».
Это первая статья в цикле
Я провожу полный аудит безопасности мессенджера MAX. Эта статья — про систему сбора IP и VPN-детект. Если тема зайдёт, дальше будет:
-
Тихий звонок: как сервер может инициировать вызов без звонка и UI
-
Ключевые слова через микрофон: в MAX встроены ASR (распознавание речи), идентификация голоса и детект ключевых слов — с моделями, которые доставляет сервер
-
End-to-end шифрование? Нет, не слышали: сообщения, контакты и токены хранятся в открытом виде
Предыстория
Я занимаюсь аудитом безопасности мобильных приложений. Недавно взялся за MAX — мессенджер от VK, который активно продвигают как «замену Telegram». Скачал APK из Google Play и RuStore, декомпилировал через JADX и начал копаться в коде.
При анализе сетевого трафика заметил странность: при каждом запуске приложение лезет на checkip.amazonaws.com. Это сервис Amazon, который возвращает твой внешний IP-адрес. Зачем мессенджеру знать мой IP через Amazon?
Потянул за ниточку — и нашёл не баг, а целую подсистему. Спроектированную, отлаженную, с защитой от обнаружения и гарантированной доставкой данных на сервер. Это не аналитика. Это инфраструктура сетевой слежки.
Часть 1: Что я нашёл
Здесь — суть без кода. Что делает приложение, зачем и чем это грозит.
1. Шесть сервисов, чтобы узнать ваш IP
Каждый раз, когда вы открываете MAX, приложение тайно определяет ваш внешний IP-адрес. Для этого у него есть 6 сервисов:
-
ipv4-internet.yandex.net — Яндекс
-
ipv6-internet.yandex.net — Яндекс
-
ifconfig.me — независимый
-
api.ipify.org — независимый
-
checkip.amazonaws.com — Amazon
-
ip.mail.ru — Mail.ru (VK Group)
Шесть штук — для одной задачи. Зачем столько? Для надёжности: если один сервис не ответит, сработает другой. Порядок каждый раз перемешивается случайным образом — так сложнее обнаружить запросы по сетевому паттерну.
Но самое интересное: адреса этих сервисов спрятаны в коде. Не как обычные строки вроде «https://ip.mail.ru/«, а как массивы чисел:
{104, 116, 116, 112, 115, 58, 47, 47, 105, 112, 46, 109, 97, 105, 108, 46, 114, 117, 47}
Каждое число — это ASCII-код буквы. 104 = «h», 116 = «t», и так далее. Получается https://ip.mail.ru/. Обычный поиск по коду (grep, strings) эти URL никогда не найдёт. Это не ошибка и не оптимизация — это намеренное сокрытие.
И ещё: приложение использует для запросов не стандартную библиотеку OkHttp (которую легко перехватить), а низкоуровневые raw-сокеты (java.net.Socket). Это обходит сетевые перехватчики, прокси и мониторинг трафика.
Для понимания: обычное приложение, которому нужен ваш IP для легитимных целей (например, геолокация для контента), делает один запрос через стандартную библиотеку. MAX делает 6 резервных запросов через скрытые URL по raw-сокетам. Это инженерия уровня малвари.
2. Пять проверок доступности: приложение определяет, в России ли вы
Параллельно со сбором IP приложение проверяет доступность пяти хостов — может ли ваш телефон до них «дотянуться»:
-
api.oneme.ru (VK Group) — свой API
-
gstatic.com (Google) — проверка доступности интернета
-
mtalk.google.com (Google) — push-уведомления
-
calls.okcdn.ru (VK Group) — CDN для звонков
-
gosuslugi.ru (Правительство РФ) — российский государственный сервис
Госуслуги в этом списке не случайность — в MAX интегрирована авторизация через ЕСИА (об этом в следующих статьях). Но проверка касается не авторизации, а базовой сетевой доступности: можно ли с вашего устройства достучаться до gosuslugi.ru? Результат — просто «да» или «нет» — уходит на сервер вместе с VPN-флагом и IP.
Зачем? Комбинация ответов даёт VK полную картину:
-
Госуслуги доступны + нет VPN + российский оператор = обычный пользователь в России
-
Госуслуги не доступны + есть VPN + российский оператор = пользователь обходит блокировки
-
Госуслуги не доступны, но другие иностранные сервисы доступны + нет VPN + неизвестный оператор = пользователь обходит блокировку + пользователь обходит проверку на VPN
Та же логика с другими хостами: gstatic.com и mtalk.google.com показывают, доступен ли Google (актуально для стран с фильтрацией как Китай ). Все пять проверок — это не «работает ли сервис», а снятие отпечатка вашей сетевой среды.
3. VPN-детект: MAX знает и докладывает
MAX определяет VPN через стандартный API Android. Ловит любой — NordVPN, WireGuard, OpenVPN корпоративный, встроенный.
Что происходит дальше: при каждом открытии приложения VPN-статус отправляется на сервер VK вместе с вашим IP и остальными данными. Это подтверждено и анализом кода, и наблюдением трафика. VK точно знает: пользуетесь ли вы VPN, в какой момент и с какого IP.
Кроме того, в коде найден виджет «Лучше без VPN» — панель, которая должна появляться во время звонков при включённом VPN. В ресурсах приложения есть строки на русском и английском. Динамически (на реальном устройстве) я это пока не воспроизводил, но код и ресурсы — на месте.
4. Полное досье при каждом открытии
Каждый раз, когда вы открываете MAX (или приложение просыпается в фоне), оно собирает и отправляет на сервер VK следующие данные:
-
Ваш ID аккаунта MAX (OK.ru ID) — из аккаунта
-
ID сессии — из приложения
-
Ключ авторизации — из HTTP-запроса
-
Внешний IP-адрес — через один из 6 IP-сервисов
-
Мобильный оператор — из SIM-карты (напр. «MTS»)
-
Тип соединения — WiFi / 4G / 5G
-
VPN включён? — через системный API
-
Доступность 5 сервисов — через сетевые проверки
-
Время — системные часы
Вот как выглядит пакет, который уходит на сервер (реконструкция из кода):
Кто: пользователь #123456789 (аккаунт MAX)
Когда: 2026-04-12, 14:30:00
IP: 185.xxx.xxx.xxx
VPN: ДА
Оператор: MTS
Связь: WiFi
Сервисы: gosuslugi.ru — да, Google — да, API MAX — да, CDN звонков — да, push — да
Это не анонимная аналитика. Каждая запись однозначно привязана к вашему аккаунту. А поскольку VK Group владеет OK.ru, VK.com и Mail.ru — аккаунт MAX связывается с профилем ВКонтакте, почтой и другими сервисами экосистемы.
Масштаб
У MAX 107 миллионов зарегистрированных пользователей и 77 миллионов ежедневной аудитории (данные VK, март 2026). С сентября 2025 приложение обязательно предустановлено на все Android-устройства, продаваемые в России и Беларуси.
Представьте: 77 миллионов человек открывают MAX каждый день. При каждом открытии — пакет с IP, VPN-статусом, оператором. Это десятки миллионов точек данных ежедневно: кто использует VPN, кто нет, с какого IP, через какого оператора, доступны ли заблокированные сервисы. В реальном времени.
Это не просто «аналитика одного приложения». Это инфраструктура мониторинга сетевой среды в масштабе целой страны. С каждой новой блокировкой РКН данные HOST_REACHABILITY становятся ценнее — они показывают, работает ли блокировка и кто её обходит.
5. Домены Telegram и WhatsApp в коде
В том же файле, где хранятся адреса активных сервисов, закодированы домены конкурентов: main.telegram.org и mmg.whatsapp.net.
В текущей версии они не используются.
Я не утверждаю, что проверка доступности Telegram «готова к мгновенной активации». Но сам факт — домены конкурентов лежат в одном файле с рабочей системой сбора данных — примечателен.
Отдельно: MAX проверяет, установлен ли Telegram на вашем устройстве — ищет три варианта приложения: основной, бета и веб-версию. Официально это для кнопки «Поделиться» (Telegram ставится первым в списке).
Подробности — в технической части ниже.
6. Сервер контролирует всё
Вся система слежки управляется одним серверным флагом через систему PMS (Push Management System) от VK. Это как remote config, только мощнее: PMS-значения доставляются через постоянное TCP-соединение и применяются мгновенно.
Что это значит на практике:
-
VK может включить сбор IP для всех пользователей одним переключателем
-
Может включить для конкретного пользователя (таргетированная слежка)
-
Может включить для когорты (A/B-тест, определённый оператор, определённый регион)
-
Может выключить перед проверкой (например, перед аудитом Google Play)
-
Всё это — без обновления приложения
Для этой функции даже выделен отдельный пул потоков с именем «host-reachability». Это не аналитика, прикрученная сбоку — это самостоятельная подсистема, спроектированная как отдельный компонент.
И ещё: данные никогда не теряются. Если отправка не удалась — 3 повтора. Если и после 3 раз не получилось — данные сохраняются в локальное хранилище и отправляются позже. При сворачивании приложения — принудительный flush всех накопленных событий. VK спроектировал это так, чтобы получить 100% собранных данных.
7. Правовая реальность
Я не буду спекулировать о том, передаёт ли VK эти данные спецслужбам. Вместо этого — факты.
VK/MAX — зарегистрированный «организатор распространения информации» по 149-ФЗ. По закону Яровой (374-ФЗ) он обязан хранить метаданные коммуникаций 1 год и предоставлять их по запросу. IP-адрес + userId + timestamp + VPN-статус — это именно те метаданные, которые подлежат хранению. А 276-ФЗ (поправки 2024) ужесточил ответственность за использование VPN для обхода блокировок — и HOST_REACHABILITY даёт точные доказательства: кто, когда и откуда использовал VPN.
При этом IP-адрес — это персональные данные по 152-ФЗ. Согласие на такой сбор у пользователя не запрашивается.
Важно: я не утверждаю, что VK злоупотребляет этими данными. Я утверждаю, что код собирает их, закон обязывает хранить и отдавать, а у пользователя нет возможности отказаться. Выводы — за вами.
Часть 2: Доказательства (для тех, кто хочет проверить)
Ниже — конкретный код из декомпилированного APK. Все ссылки на файлы и строки — из JADX-дизассемблера, версия APK 26.12.1.
2.1 Как спрятаны URL: обфускация через int[]
Файл: defpackage/f28.java:43
Вот как выглядит адрес https://ip.mail.ru/ в коде MAX:
// f28.java:53 x = new int[]{104, 116, 116, 112, 115, 58, 47, 47, 105, 112, 46, 109, 97, 105, 108, 46, 114, 117, 47};
Декодируем вручную:
104 → h 116 → t 116 → t 112 → p 115 → s 58 → : 47 → / 47 → / 105 → i 112 → p 46 → . 109 → m 97 → a 105 → i 108 → l 46 → . 114 → r 117 → u 47 → /
Результат: https://ip.mail.ru/
Все 16 URL в файле f28.java закодированы таким образом. Декодирование происходит лениво через rd4.java (cases 17-22 для IP-сервисов, 12-16 для проверок).
Это не минификация и не оптимизация. ProGuard обфусцирует имена классов и методов, но не превращает строковые литералы в массивы int. Это ручная работа разработчиков, цель которой — сделать URL невидимыми для инструментов статического анализа (grep, strings, jadx string search).
2.2 Сбор IP: w18.java
Файл: defpackage/w18.java:139-140
// Собираем все 6 IP-сервисов в список
List o1 = rz3.o1(sz3.U(
f28.o.getValue(), // Yandex IPv4
f28.q.getValue(), // Yandex IPv6
f28.s.getValue(), // ifconfig.me
f28.u.getValue(), // api.ipify.org
f28.w.getValue(), // checkip.amazonaws.com
f28.y.getValue())); // ip.mail.ru
// Перемешиваем — каждый раз случайный порядок
Collections.shuffle(o1);
Дальше — последовательный перебор: первый сервис, который вернул IP ≠ 127.0.0.1, побеждает. Остальные не опрашиваются.
Ключевой момент: запросы идут через java.net.Socket + ByteArrayOutputStream — это raw TCP, не OkHttp. OkHttp — стандартная HTTP-библиотека Android, которую легко перехватить через прокси (Burp Suite, Charles, mitmproxy). Raw-сокеты обходят всё это. Исследователь, настроивший прокси на устройстве, не увидит эти запросы в стандартных инструментах.
2.3 Сборка пакета данных: c28.java
Файл: defpackage/c28.java:100-116
ro9 ro9Var = new ro9();
// Результаты проверки доступности хостов: {hostname: true/false}
ro9Var.put(«hosts», vibVar);
// Мобильный оператор: «25001:MTS»
ro9Var.put(«operator», str);
// Тип соединения: WiFi (0) или мобильная сеть (1)
ro9Var.put(«connection_type», new Integer( nc4Var.g() ? nc4Var.b().a : 1));
// Внешний IP-адрес
if (str2 != null) {
ro9Var.put(«ip», str2); }
// Флаг VPN
if (((nc4) b19Var.getValue()).e()) {
ro9Var.put(«vpn», new Integer(1)); }
// Отправка: тип HOST_REACHABILITY, событие GET_HOST_REACHABILITY
lg9.h(lg9Var, «HOST_REACHABILITY», «GET_HOST_REACHABILITY», ro9Var.b(), 8);
Реконструированный JSON, который уходит на сервер:
{
«type»: «HOST_REACHABILITY»,
«event»: «GET_HOST_REACHABILITY»,
«userId»: 123456789,
«sessionId»: 987654321,
«time»: 1712847600000,
«params»: {
«hosts»: {
«api.oneme.ru«: true,
«gstatic.com«: true,
«calls.okcdn.ru«: true,
«gosuslugi.ru«: true,
«mtalk.google.com«: true
},
«operator»: «25001:MTS»,
«connection_type»: 0,
«ip»: «185.xxx.xxx.xxx«,
«vpn»: 1
}
}
Адрес назначения: api.ok.ru/api/log/externalLog (POST, gzip, аутентифицирован через session_key).
2.4 Гарантированная доставка
Файл: defpackage/lg9.java:49-103
Отправка → Ошибка? → Повтор 1 → Ошибка? → Повтор 2 → Ошибка? → Повтор 3 → Ошибка? → Сохранить в локальное хранилище (vgh) → Отправить позже при подключении
До 3 повторов (строка 66: intValue() > 3). После 3 неудач — данные сохраняются в локальное хранилище vgh (строки 68-77) для отправки позже. При сворачивании приложения — принудительный flush (r87.java:68.
Результат: ваши данные отправятся серверу VK в любом случае. Нет сети? Подождёт. Сервер упал? Повторит. Вы закрыли приложение? Дошлёт при следующем запуске. Система спроектирована так, что ни одно событие не теряется.
2.5 Виджет «Лучше без VPN» и аналитика VPN-событий
Файл: one/me/calls/ui/ui/call/panels/VpnPanelWidget.java, defpackage/dy1.java:46
// dy1.java:46 — VPN обнаружен во время звонка
VpnPanelWidget widget = new VpnPanelWidget();
// Добавляется в UI с тегом «call_vpn_panel_widget_tag»
Состояния VPN-уведомления
Файл: defpackage/l4j.java
l4j.a // ENABLED — VPN включён
l4j.b // DISABLED — VPN выключен
l4j.c // USER_IGNORED — пользователь закрыл предупреждение
l4j.d // UNKNOWN — не удалось определить
Аналитическое событие при показе баннера: BAD_CONNECTION_ALERT с типом VPN (m82.java:43.
2.6 Неактивные проверки доступности Telegram и WhatsApp
Файл: defpackage/rd4.java:87
case 15: return hb0.a(f28.l); // main.telegram.org
case 16: return hb0.a(f28.m); // mmg.whatsapp.net
Файл: defpackage/c28.java:150 — список активных проверок:
List U = sz3.U(
«api.oneme.ru«,
(String) f28.b.getValue(), // gstatic.com
(String) f28.f.getValue(), // calls.okcdn.ru
(String) f28.h.getValue(), // gosuslugi.ru
(String) f28.d.getValue()); // mtalk.google.com
f28.l (Telegram) и f28.m (WhatsApp) — есть в декодере rd4.java, но отсутствуют в активном списке c28.java. Более того, на уровне smali-байткода для этих полей нет move-result-object / sput-object — результат декодирования отбрасывается. Это мёртвый код или заготовка, но не работающая функциональность.
Также в f28 есть неактивные домены Huawei Push:
-
token-drcn.push.dbankcloud.com (DRCN = Data Region China North)
2.7 Когда это срабатывает
Основной триггер: каждый раз, когда приложение переходит в foreground (вы открыли MAX или вернулись к нему):
r87.java:82 → app foreground callback
→ проверяет PMS-флаг (e28.java:142-146)
→ если включён и нет активной проверки
→ запускает c28 (полный пайплайн)
Также: при логине (AccountInitializer), при фоновом пробуждении (one.me.background.wake.HostReachabilityChecker).
Даже до авторизации: код в y18.java:66-100 показывает, что сетевые проверки работают в разных режимах в зависимости от состояния сессии (не подключён / подключён / залогинен). Фингерпринтинг сети начинается до того, как пользователь вошёл в аккаунт.
Выводы
MAX — приложение, предустановленное на 100+ миллионов устройств — содержит систему, которая при каждом открытии:
-
Узнаёт ваш IP через 6 скрытых сервисов
-
Определяет, включён ли VPN
-
Проверяет, доступны ли российские и международные сервисы из вашей сети
-
Привязывает всё это к вашему реальному аккаунту
-
Гарантированно доставляет данные на сервер VK — без потерь, с повторами
Эта система управляется сервером и может быть включена для всех, для группы или для конкретного пользователя — без обновления приложения. Адреса сервисов намеренно спрятаны, запросы идут в обход стандартных сетевых библиотек.
Я различаю возможность в коде и подтверждённое использование. Серверный флаг может быть не включён для всех. Но код — вот он. Проверяйте.
Что дальше?
Сбор IP и VPN-детект — это верхушка айсберга. В коде MAX я нашёл ещё много интересного и планирую рассказать в следующих статьях.
Пишите в комментариях, что разобрать первым.
Техническая справка
Версия APK: 26.12.1 (6679) Разработчик: ООО «КОММУНИКАЦИОННАЯ ПЛАТФОРМА» (VK Group, Москва) Метод: статический анализ декомпилированного APK (JADX) SHA256: 47420c41b742e67daae85ee75e0aa76935736c7491bab9da942c012e2115ffa1
Примечание о названиях файлов: большинство классов в APK обфусцированы ProGuard — вместо осмысленных имён вроде HostReachabilityManager.java вы увидите f28.java, c28.java, w18.java. В JADX они попадают в defpackage/ (дефолтный пакет для классов без имени пакета). Это нормально для обфусцированного кода. Классы с нормальными именами (например, VpnPanelWidget.java) сохранили свои пути — я указываю полный путь там, где он есть.
Если нашли ошибку — пишите, исправлю. Я за точность, а не за хайп.