С чего всё началось

Всё началось с ограничений доступа. Discord заблокировали в 2024 году, YouTube сначала замедлили, а в феврале 2026 года, по сообщениям СМИ, он пропал из национальной системы доменных имён. Telegram деградировал постепенно: сначала перестали работать звонки, потом почти не грузились фото и видео, 10 февраля 2026 года Роскомнадзор официально объявил об ограничении, а в какой-то момент мессенджер вообще перестал загружать чаты и висел на «Подключение…».

Сообщество нашло рабочие решения: ByeDPI от hufrea, который на Android удобно запускать через форк ByeByeDPI от romanvht, и tg-ws-proxy для Telegram. Оба инструмента реально работают. Проблема одна: настроить их непросто. Сканирование в ByeByeDPI перебирает стратегии долго и приблизительно, потом нужно самому ставить стратегию, идти в YouTube проверять, заработал ли он, и возиться с DNS. И всё это у каждого провайдера и оператора по-своему. Отдельно нужно настраивать прокси для Telegram.

Я хотел сделать то, чем сможет пользоваться любой человек: без консоли, без гугления, без «а он вообще запустился?». Десктопный NetFix уже делает это для компьютера, а теперь появился NetFix Mobile: Android-приложение для телефонов и Smart TV.

Важный момент сразу. NetFix Mobile не изобретает методы обхода! Это оболочка, которая управляет готовыми open-source инструментами: ByeDPI для обхода DPI (Deep Packet Inspection), hev-socks5-tunnel для туннеля и tg-ws-proxy для Telegram. Моя часть: автоматический подбор рабочей конфигурации, работа с сетями, интерфейс и поддержка телевизоров. Код открыт.


Что внутри и как это работает

DPI — это оборудование провайдера, которое смотрит на начало соединения и по имени сайта в TLS (Transport Layer Security) решает, замедлить его или сбросить. ByeDPI — это локальный SOCKS-прокси, который по-разному разбивает и подделывает первые пакеты (--split, --disorder, --fake и другие), чтобы DPI не мог их распознать. Вот несколько приёмов из его арсенала, чтобы было понятно, что именно подбирает приложение:

  • --split разбивает запрос на части по указанной позиции, например в середине имени сайта;

  • --disorder отправляет части в обратном порядке;

  • --fake перед настоящим пакетом отправляет поддельный с маленьким TTL (time to live): он доходит до DPI, но не до сервера;

  • --tlsrec делит TLS-запрос на несколько записей.

Один и тот же приём у разных провайдеров работает по-разному, поэтому и существуют «магические строки». Подробности есть в README самого проекта.

На Android трафик направляют в этот прокси через VPN-режим системы (VpnService). Это не настоящий VPN: ничего не уходит на удалённый сервер, трафик не шифруется, IP не меняется. Пакеты из tun-интерфейса забирает hev-socks5-tunnel и передаёт в ByeDPI. Эту схему уже реализовал ByeByeDPI, у него есть и тест стратегий, и раздельное туннелирование приложений. NetFix Mobile работает по такому же принципу и автоматизирует выбор конфигурации.

В приложении два независимых сервиса:

  1. Обход DPI: VpnService + hev-socks5-tunnel + ByeDPI (C, через NDK).

  2. Telegram-прокси: ядро на Rust, вызывается из Kotlin через JNA (Java Native Access). Оно поднимает локальный MTProto-сервер на 127.0.0.1:порт, а Telegram подключается к нему сам.

Мешать их в один туннель смысла нет: Telegram-прокси работает не на уровне пакетов. Поэтому «режим работы» — это просто то, что запускает кнопка: только Telegram, только обход для YouTube и других сервисов или оба сразу. Для обхода DPI можно выбрать, какие приложения идут через туннель (по умолчанию только нужные: YouTube, Discord, Instagram, X и другие), а само приложение всегда исключено из туннеля, чтобы его собственный трафик не зациклился.


Автоподбор: воронка вместо ручного перебора

Ради этого я всё и делал. Стратегий десятки, и проверять их вручную долго. Доверять пингу нельзя: DPI часто пропускает рукопожатие TLS и режет сам поток. Страница открылась, а видео нет.

Поэтому для каждой стратегии приложение поднимает ByeDPI на свободном локальном порту, делает настоящие HTTPS-запросы к адресам через этот прокси и читает ответ до конца. Адрес считается доступным, только если пришёл весь заявленный объём:

val declaredLength = connection.contentLengthLong
var receivedLength = 0L
val buffer = ByteArray(8192)
while (true) {
    val read = connection.inputStream.read(buffer)
    if (read == -1) break
    receivedLength += read
}
return declaredLength <= 0L || receivedLength >= declaredLength

Чтобы не тратить время на заведомо плохие варианты, проверка идёт воронкой:

  • быстрый проход по небольшому набору адресов YouTube и Discord для всех стратегий (до 30 запросов параллельно);

  • пять финалистов проходят полный набор адресов с большим таймаутом;

  • десять лучших перепроверяются на конкретной сети, ранжируются, и приложение рекомендует лучшую.

Для стратегий с подделкой SNI (Server Name Indication, -n {sni}) используется общий список доменов YouTube, чтобы результаты были сопоставимы между собой. Свою строку аргументов, найденную в чатах, можно вставить: она проверится и попадёт в рейтинг наравне с остальными. Результаты можно экспортировать и импортировать.


Wi-Fi и мобильная сеть: у каждой своя стратегия

У домашнего провайдера и мобильного оператора DPI часто разный, поэтому стратегия, идеально работающая дома, на улице может не работать вообще. Но как проверить мобильную сеть, когда телефон подключён к Wi-Fi? Система обычно отправляет весь трафик по Wi-Fi.

Решение в том, что у системы можно запросить конкретную сеть и проверять именно через неё:

val request = NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
    .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
    .build()
connectivityManager.requestNetwork(request, callback)

Флаг NOT_VPN нужен, чтобы проверка не пошла в наш же туннель. Если нужной сети сейчас нет, приложение ждёт до 90 секунд и подсказывает её включить. Результаты хранятся отдельно для Wi-Fi и мобильной сети, а при смене подключения рабочая стратегия переключается сама.


Telegram-прокси на Rust

С Telegram всё иначе: играть с пакетами нет смысла, нужен прокси, к которому подключается сам мессенджер. Ядро написано на Rust (модули proxy, crypto, ws, cfproxy, balancer): локально оно слушает 127.0.0.1:порт, а наружу ходит по WebSocket через Cloudflare. Из Kotlin вызывается через JNA: StartProxy, StopProxy, SetPoolSize, FlushPools.

Три вещи, которые сделали его удобным:

  • Пул заранее открытых соединений. Новое соединение к дата-центру открывается не мгновенно, и первые фото в Telegram «висели». Прокси держит несколько готовых соединений.

  • Смена сети. При переходе с Wi-Fi на мобильный интернет пул устаревает, поэтому приложение следит за сетью и сбрасывает его.

  • Чужой VPN. Если включён сторонний VPN, Cloudflare-маршрут только мешает. Приложение замечает TRANSPORT_VPN в сети, которая не принадлежит нам, и переключает прокси на прямой режим. Когда VPN выключается, всё возвращается назад.

Подключение к Telegram занимает один тап: приложение формирует ссылку tg://proxy, и Telegram сам предлагает включить прокси. Есть и ограничение: настройки прокси внутри Telegram из другого приложения менять нельзя, поэтому после остановки NetFix только напоминает отключить его вручную.


Smart TV и работа в фоне

Приложение работает и на Android TV. Интерфейс для пальца на пульте неудобен, поэтому для телевизора он собран заново на Compose: экраны в две колонки, плавающая панель навигации, которая сворачивается через 15 секунд, фокус не теряется при смене вкладок и закрытии шторок. После скана приложение предлагает проверить YouTube и помогает поставить SmartTube прямо с пульта.

В фоне работают foreground-сервисы с одним общим уведомлением, watchdog на WorkManager, плитка быстрых настроек и режим стабильного прокси для прошивок, которые агрессивно закрывают приложения. Главная кнопка показывает «Подключено» только когда сервисы реально подняты.


Интерфейс и нагрузка

Фон главного экрана — это анимированный глобус с дугами трафика, нарисованный на Canvas в Compose. Сначала он рисовался на каждом кадре и заметно грел телефон, поэтому пришлось заняться оптимизацией. Теперь анимация ограничена 30 кадрами в секунду и подстраивается под нагрузку: если устройство не успевает, кадры реже, а когда нагрузка спадает, частота возвращается. В фоне и под шторками она ставится на паузу. На эмуляторе нагрузка на процессор упала примерно с 70% до 33%, а медианное время кадра с 32 до 17 мс. Это замеры только эмулятора, на реальных телефонах цифры будут отличаться. Для слабых устройств есть переключатель, который включает упрощённый глобус без размытия.


Чего оно не умеет

  • Результат зависит от провайдера: подходящей стратегии для конкретного сервиса может не найтись.

  • Это не VPN: трафик не шифруется, IP-адрес не меняется.

  • Настройки Telegram приложение не меняет, прокси отключается в самом Telegram вручную.

  • Работа рядом с чужим VPN зависит от того, как он устроен.


Итог

NetFix Mobile — это Android-приложение для телефонов и Smart TV, которое одной кнопкой запускает обход блокировок для YouTube, Discord и других сервисов и локальный прокси для Telegram. Само находит рабочие настройки, запоминает их отдельно для Wi-Fi и мобильной сети и не требует понимать, что такое --disorder и TTL фейкового пакета. А тот, кто понимает, может вставить свою строку и посмотреть, как она себя покажет в рейтинге.

Исходный код: NetFix Mobile на GitHub

Обновления и обсуждение: Telegram-канал NetFix

Комментарии (0)