Телега: анализ безопасности и приватности

Март 2026

Аннотация В данной работе представлен анализ Телеги — стороннего клиента Telegram, построенного на открытом исходном коде мессенджера. Рассматриваются архитектура приложения, модель безопасности, практики обработки данных и последствия для приватности конечных пользователей.

Полный технический анализ MITM в клиенте Telega

Утром 18 марта создатели приложения Telega активировали скрытую функциональность, позволяющую им перехватывать все данные между их приложением и сервером Telegram, пропуская их через свои сервера.

К сожалению, информации об этом мало, и поэтому была написана эта статья с подробным, повторяемым анализом данного механизма.

Те, кому не очень интересны технические детали, но хочется узнать о ситуации больше — читайте "TL;DR" в конце каждого параграфа.

Background о шифровании и клиент-серверном протоколе Telegram

Telegram имеет несколько серверов в разных регионах мира — у каждого по одному или несколько IP-адресов и внутри Telegram они называются DC (дата-центры). Например, у DC2 в Амстердаме, к которому относятся все пользователи из России, имеет IP-адрес 149.154.167.51. (источник)

Когда клиент Telegram устанавливает подключение к DC, он генерирует случайные параметры шифрования и передает их в зашифрованном виде с помощью алгоритма RSA — в клиент вшит публичный ключ, которым клиент шифрует данные, а затем сервер, с помощью соответствующего приватного ключа их расшифровывает.

Другими словами, клиент Telegram использует публичный, заранее известный ключ RSA для установления первичного шифрованного соединения с сервером, чтобы сгенерировать и договориться об общем, новом ключе шифрования (для AES). (источник)

TL;DR: в клиент Telegram вшиты IP-адреса серверов мессенджера и ключи шифрования для взаимодействия.

Как Telega вмешивается в это взаимодействие — подмена IP-адресов

Разберем последнюю на данный момент версию клиента Telega для Android (sha256 ca47b6..6d34f0) и распакуем через jadx.

Пишем в поиске по файлам dc-proxy и находим следующие куски кода: ru/dahl/messenger/dc/DCRestService.java:

public interface DCRestService {
    @GET("dc-proxy")
    Object getDcConfig(Continuation<? super DcConfig> continuation);
}

ru/dahl/messenger/data/rest/RestClient.java:

public static final String API_URL = "https://api.telega.info/v1/";

Можно сделать вывод, что приложение совершает HTTP GET запрос по ссылке https://api.telega.info/v1/dc-proxy, которая возвращает JSON-объект с параметром { "dc_version": 2 }, а так же массив dcs следующего формата:

{ "dcs": [{ "id": 2, "addresses": [{ "host": "130.49.152.41", "port": 443}] }] }

Где id имеет значение от 1 до 5 (соответствуя номерам DC Telegram), а все IP-адреса находятся в диапазоне 130.49.152.0/24 и принадлежат AS203502 JOINT STOCK COMPANY "TELEGA", которая была зарегистрирована 24 ноября 2025 года.

Интересный факт — единственный апстрим данной AS - AS47764 LLC VK (Mail.ru), и им же принадлежит соседняя подсеть 130.49.224.0/19. Это косвенно указывает на то, что Telega — дочерний проект VK. Непонятно, откуда у маленького стартапа из Казани средства на организацию своего AS и покупку целого /24 блока IP-адресов.

То есть, приложение получает IP-адреса контроллируемых Telega серверов, которые должны заменить адреса настоящих серверов Telegram.

Затем, вызывается метод applyDcVersion() из класса DCAuthHelper.java:

public final Object applyDcVersion(
    final int r17, // dcVersion (2)
    final java.util.List<ru.dahl.messenger.dc.entity.Datacenter> r18, // адреса серверов Telega
    final ru.dahl.messenger.dc.entity.DcOptions r19,
    final boolean r20,
    kotlin.coroutines.Continuation<? super kotlin.Unit> r21
)

Внутри этого метода, вероятно, идет вызов публичного метода ConnectionsManager.setDcVersion с новыми адресами:

// ConnectionsManager.java:1934-1935
public void setDcVersion(int version, int[] dcIds, String[] addresses, 
                          int[] ports, boolean[] flags, boolean usePfs, 
                          String[] transports) {
    native_setDcVersion(this.currentAccount, version, dcIds, addresses, 
                        ports, flags, dcIds.length, usePfs, transports);
}

На это косвенно указывает полу-декомпилированный код в DCAuthHelper.java:379, который проверяет, что значение dcVersion изменилось на нужное:

ConnectionsManager r7 = ConnectionsManager.getInstance(r7);
int r7 = r7.getDcVersion();
int r8 = this.$dcVersion;
if (r7 != r8) { /* not yet */ }

Итого мы получаем примерно такую цепочку вызовов: Схема цепочки вызовов

Обратите внимание: вызов AuthTokensHelper.clearLogInTokens() при смене режима не удаляет auth_key (ключ шифрования сессии), этим занимается другая функция, мы описали её ниже.

TL;DR: Клиент Telega подменяет IP-адреса серверов Telegram на свои собственные по "команде" с их сервера.

Подмена ключа шифрования RSA

Но без подмены ключа шифрования атака MITM невозможна. Чтобы найти RSA ключ Telega, нужно декомпилировать динамическую библиотеку libtmessages.49.so, которая хранится в этом же APK-файле. Именно эта библиотека реализует методы native_*, используемые в классе ConnectionsManager.

Открываем IDA Pro и скармливаем ей libtmessages.49.so, в данном случае вариант для arm64. Нажимаем Shift+F12, откроется список найденных текстовых строк. Ищем все ключи по заголовку "BEGIN RSA PUBLIC KEY" (Ctrl+F):

Ключ №1 по адресу 0x1576FFC:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAyr+18Rex2ohtVy8sroGPBwXD3DOoKCSpjDqYoXgCqB7ioln4eDCF
fOBUlfXUEvM/fnKCpF46VkAftlb4VuPDeQSS/ZxZYEGqHaywlroVnXHIjgqoxiAd
192xRGreuXIaUKmkwlM9JID9WS2jUsTpzQ91L8MEPLJ/4zrBwZua8W5fECwCCh2c
9G5IzzBm+otMS/YKwmR1olzRCyEkyAEjXWqBI9Ftv5eG8m0VkBzOG655WIYdyV0H
fDK/NWcvGqa0w/nriMD6mDjKOryamw0OP9QuYgMN0C9xMW9y8SmP4h92OAWodTYg
Y1hZCxdv6cs5UnW9+PWvS+WIbkh+GaWYxwIDAQAB
-----END RSA PUBLIC KEY-----

Ключ №2 по адресу 0x15788E1:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAum9pZNEIWVt6jQUm/qcP4na0RgWHfSls/TJwxYQTsruNyuVgdrBu
y7gbNcObgnxmjxohwRjkNCOASwfYOD5yZ0UUqlg+iK84cmS8HdSublM/Bvf4huqN
7RZ0GXQ8nGCZQFQ67ZqXS5R/4XNUmoj5kmhHOl7OU4ow3DXdjM3JEmvaVtacGoMW
BT2s1JtTt3bXVJmarBxt3g8yn+lmAs7aCZkVj0cdocHT7jOyPaCtvSC+pGThr7qA
aDEWl2q8Z4fH1hYF3xrm4vxraJq4fFIbuBLceMKfHsI7ahL4KLF/tYNNZzbfaE5s
4Z2HPiEI+78hAdxCWAnQd9Efj2Dbc6OM2wIDAQAB
-----END RSA PUBLIC KEY-----

Ключ №3 по адресу 0x1578A8B:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAyMEdY1aR+sCR3ZSJrtztKTKqigvO/vBfqACJLZtS7QMgCGXJ6XIR
yy7mx66W0/sOFa7/1mAZtEoIokDP3ShoqF4fVNb6XeqgQfaUHd8wJpDWHcR2OFwv
plUUI1PLTktZ9uW2WE23b+ixNwJjJGwBDJPQEQFBE+vfmH0JP503wr5INS1poWg/
j25sIWeYPHYeOrFp/eXaqhISP6G+q2IeTaWTXpwZj4LzXq5YOpk4bYEQ6mvRq7D1
aHWfYmlEGepfaYR8Q0YqvvhYtMte3ITnuSJs171+GDqpdKcSwHnd6FudwGO4pcCO
j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
-----END RSA PUBLIC KEY-----

Ключ №4 по адресу 0x1578C35:

-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA6LszBcC1LGzyr992NzE0ieY+BSaOW622Aa9Bd4ZHLl+TuFQ4lo4g
5nKaMBwK/BIb9xUfg0Q29/2mgIR6Zr9krM7HjuIcCzFvDtr+L0GQjae9H0pRB2OO
62cECs5HKhT5DZ98K33vmWiLowc621dQuwKWSQKjWf50XYFw42h21P2KXUGyp2y/
+aEyZ+uVgLLQbRA1dEjSDZ2iGRy12Mk5gpYc397aYp438fsJoHIgJ2lgMv5h7WY9
t6N/byY9Nw9p21Og3AoXSL2q/2IJ1WRUhebgAdGVMlV1fkuOQoEzR7EdpqtQD9Cs
5+bfo3Nhmcyvk5ftB0WkJ9z6bNZ7yxrP8wIDAQAB
-----END RSA PUBLIC KEY-----

Теперь скачаем последний релиз Telegram для Android с официального сайта (https://telegram.org/dl/android/apk), распакуем APK обычным архиватором, и скормим IDA Pro такую же библиотеку (sha256 5ebcea..0176c9) и сравним ключи.

Оказывается, в оригинальной библиотеке от Telegram есть только 3 из 4 ключей, которые зашиты в клиент Telega:

Адрес ключа в Telega Адрес ключа в Telegram SHA-256
0x1576FFC 0x15704DC 76f57758..4583493e
0x15788E1 - 7f7d5bd9..104f3fe1
0x1578A8B 0x1571CAE 2652db36..10beb77f
0x1578C35 0x1571E58 abaec5de..041348db

Хэш ключа генерировался следующей командой: openssl rsa -in pub.pem -pubin -outform DER 2>/dev/null | openssl dgst -sha256

В итоге выходит, что в Telega был добавлен ключ №2 по адресу 0x15788E1. Чтобы долго не копаться в сурсах библиотеки, устроим простой тест — попробуем установить соединение с сервером DC 2 от Telega и сервером DC 2 от Telegram, используя ключ, добавленный создателями Telega.

Попросим Claude Opus написать скрипт, который попытается инициировать первичное рукопожатие с сервером MTProto, непосредственно скрипт: mtproto_handshake_test.py. Можно попросить любой ИИ объяснить, как он работает.

Запустим этот скрипт сначала с адресом официального DC2 Telegram:

$ python3 mtproto_handshake_test.py 149.154.167.50    
Key fingerprint: 0x2c945714333b5ebd  (2048-bit)
Server:          149.154.167.50:443  (DC 2)

Server fingerprints: ['0xd09d1d85de64fd85', '0x0bc35f3509f7b7a5', '0xc3b42b026ce86b21']
Our fingerprint in list: False

RESULT: transport error -404
The server could not decrypt our payload.
⇒ Server does NOT hold the private key for this RSA key.

Скрипт сообщает, что сервер Telegram предлагает свои ключи, к которым ключ Telega не относится. При попытке установить соединение сервер отправляет ошибку транспорта -404, так как не может дешифровать наш запрос, зашифрованный неизвестный ему ключом.

Теперь то же самое, только с сервером DC2 Telega:

$ python3 mtproto_handshake_test.py 130.49.152.41                              
Key fingerprint: 0x2c945714333b5ebd  (2048-bit)
Server:          130.49.152.41:443  (DC 2)

Server fingerprints: ['0x2c945714333b5ebd']
Our fingerprint in list: True

RESULT: server_DH_params_ok
The server successfully decrypted our payload.
⇒ Server HOLDS the private key for this RSA key.

Сервер Telega предложил нам этот же ключ и успешно завершил рукопожатие.

TL;DR: В Telega добавлен дополнительный, четвертый публичный ключ RSA, который не принимает сервер Telegram, но принимает сервер Telega.

Что дает подмена сервера и ключа шифрования?

Как было описано в начале статьи, шифрование RSA между клиентом и сервером Telegram используется при рукопожатии (handshake) для генерации нового ключа шифрования, с помощью которого затем шифруется весь трафик.

Из-за того, что рукопожатие проводится один раз при первичном установлении соединения клиента и сервера (например, если пользователь только что установил себе клиент Telegram и еще даже не вошел в аккаунт), в Telega был встроен еще один механизм — по команде с сервера Telega клиент может инициировать выход из аккаунта, стирая все данные о связи с сервером, включая общий ключ шифрования.

Метод DCEventHandler.performSoftLogoutForAllAccounts:

public final void performSoftLogoutForAllAccounts() {
	try {
		int maxAccountCount = getBridge().getMaxAccountCount();
		for (int i = 0; i < maxAccountCount; i++) {
			if (getBridge().isClientActivated(i)) {
				getBridge().logout(i);
			}
		}
		Napier.d$default(Napier.INSTANCE, "DC Event: soft logout completed for all accounts", null, null, 6, null);
	} catch (Exception e) {
		Napier.e$default(Napier.INSTANCE, "DC Event: error during soft logout", e, null, 4, null);
	}
}

Метод TelegramBridge.logout:

public void logout(int i) {
	clearDismissedPromos();
	UserConfig.getInstance(i).clearConfig(); // удаляет сессию и ключ шифрования (auth_key)
	MessagesController.getInstance(i).performLogout(0); // отправляет серверу сигнал о выходе из аккаунта
	ConnectionsManager.getInstance(i).cleanup(true); // убивает все соединения
}

Данный механизм вызывается несколькими способами:

  1. Скрытым push-уведомлением от сервера Telega c полями type=dc_update_version и force_relogin=true (См. класс TelegaPushHandler)
  2. Скрытым push-уведомлением от сервера Telega c полями type=dc_force_switch и force_reconnect=true (См. класс TelegaPushHandler)
  3. При переходе по ссылке tg://dc_event?force_relogin=true или tg://dc_event?force_reconnect=true (См. класс DCDeepLinkHandler)
  4. Промо-баннер с предложением о "миграции" (См. классы PromoRestClient, DahlBannerCell, DCMigrationHelper)

Последний механизм показывает пользователю промо-баннер со следующим текстом:

Перезайдите в приложение, чтобы ускорить соединение

Мы переходим на выделенные серверы для максимальной скорости и стабильности звонков, чатов и загрузки медиа. Вам нужно только перезайти в свой аккаунт.

Мы не знаем, показывался ли данный баннер при активации MITM 18 марта, но по данному сообщению видно, что Telega ведёт себя как обычное вредоносное ПО — предлагает пользователю скорость и стабильность, а под капотом ворует данные от их аккаунтов Telegram и устанавливает постоянную "прослушку".

Так как Telega со своим dc-proxy контроллирует хэндшейк, это означает, что они могут провести классическую атаку MITM (Man-in-the-middle, "человек посередине") — договориться с клиентом об одном ключе шифрования, а с настоящим сервером Telegram о другом ключе шифрования, и, будучи посередине между клиентом и сервером, просматривать, сохранять и модифицировать весь трафик.

Схема MITM-атаки Telega|697

TL;DR: Telega может, без вашего ведома

  • Читать все входящие и исходящие сообщения в любом чате;
  • Просматривать всю историю сообщений в любом чате;
  • Подменять контент сообщений — например, блокировать неугодные каналы по причине "нарушения правил Telegram" (не Telega!);
  • Хранить все ваши данные и действия в Telegram и передавать их третьим лицам — особенно правоохранительным органам;
  • Выполнять абсолютно любые действия с вашим аккаунтом без вашего участия.

Отключение Perfect Forward Secrecy

PFS (Perfect Forward Secrecy — «совершенная прямая секретность») — это механизм защиты, который гарантирует: даже если кто-то однажды получит ваш ключ шифрования, он не сможет прочитать старые переписки.

В MTProto это реализовано так: вместо использования "долгосрочного", не меняющегося ключа auth_key, клиент и сервер генерируют временный ключ шифрования temp_auth_key примерно раз в 1-2 суток и шифруют весь трафик с помощью него.

В официальных клиентах Telegram флаг об использовании этой опции захардкожен в значение true во время сборки и не может быть изменён.

На контрасте, в приложении Telega этот флаг по умолчанию выключен, а его состояние контроллируется сервером Telega через тот же самый эндпоинт /dc-proxy.

Тот же метод https://api.telega.info/v1/dc-proxy имеет объект options, который может контролировать это (сейчас он пустой), но по умолчанию, если параметр use_pfs отсутствует, PFS выключен.

На это указывает флаг DcConfig.options.use_pfs (Boolean?, JSON: "use_pfs"), далее он используется в методе DCRepository.handleDcConfig():

DcOptions options = dcConfig.getOptions();
boolean usePfs = false; // ← выключено по умолчанию
if (options != null && options.getUsePfs() != null) {
	usePfs = options.getUsePfs().booleanValue();
}

Затем в методе DCAuthHelper.applyDcVersion():

boolean usePfs = dcOptions != null ? dcOptions.getUsePfs() : false;

ConnectionsManager.setDcVersion(
	dcVersion=2,
	dcIds, hosts, ports, ipv6,
	usePfs, // ← переключатель PFS
	transports
);

Метод ConnectionsManager.setDcVersion затем передает этот флаг в нативный метод native_setDcVersion.

TL;DR: В Telega по умолчанию отключена дополнительная защита Telegram от перехвата сообщений и ключей шифрования.

Отключение секретных чатов

Секретные чаты в Telegram представляют из себя чаты с End-to-End шифрованием, что позволяет даже серверу не знать содержимого сообщений. Ключи для секретных чатов никогда не покидают устройство.

Telega получает Remote Config через Firebase каждый час и обрабатывает в классе FeatureManager. Текущий Remote Config с сервера сейчас выглядит так — секретные чаты выключены флагом enable_sc = false :

{
  "entries": {
    "ads_control": "true",
    "autosubscribe_channel": "true",
    "chat_invite_friend_modal": "false",
    "chat_invite_sticky_banner": "false",
    "connection_no_vpn_mode": "true",
    "connection_settings": "true",
    "connection_stable_calls": "true",
    "contact_list_invite_friend": "true",
    "dialogs_invite_friend_button": "false",
    "enable_sc": "false",
    "group_video_calls": "false",
    "invite_friend": "false",
    "moderation_enabled": "false",
    "p2p_video_calls": "true",
    "parental_control_core": "true",
    "parental_control_menu_item": "false",
    "profile_invite_friend_item": "true",
    "settings_invite_friend_item": "true",
    "sidemenu_invite_friend": "true",
    "telega_calls": "true",
    "telega_group_calls_attach": "false",
    "telega_group_calls_chat": "false",
    "telega_p2p_calls": "true",
    "telega_wall": "true",
    "telegram_call_fallback": "false",
    "waitlist": "none",
    "waitlist_enabled": "true"
  },
  "state": "UPDATE",
  "templateVersion": "472"
}

Флаг enable_sc обрабатывается классом FeatureManager и он используется в логике обработки секретных чатов в следующих местах:

Метод SecretChatHelper.acceptSecretChat:

public void acceptSecretChat(final TLRPC.EncryptedChat encryptedChat) {
    if (this.acceptingChats.get(encryptedChat.id) == null && FeatureManager.currentInstance().isSCEnabled()) {
        // логика "принятия" запроса на начало секретного чата
    }
}

Так как FeatureManager.currentInstance().isSCEnabled() возвращает false, входящие секретные чаты тихо игнорируются клиентом Telega и пользователь об этом не узнает.

Помимо этого, Telega скрывает кнопку "Начать секретный чат" и игнорирует deep link ссылки на секретные чаты.

TL;DR: Telega может отключать секретные (end-to-end encrypted) чаты по команде со своего сервера — при этом по умолчанию они уже отключены. Обычный пользователь даже не узнает, если кто-то попытается написать ему в секретном чате.

Cистема "модерации"

Telega может влиять на контент внутри приложения даже без использования MITM-атаки, описанной выше. Внутри приложения есть функциональность "чёрных списков", которые работают отдельно от похожих механизмов в Telegram, и позволяет запретить пользователям Telega открывать определённые каналы, переписки с чат-ботами и даже личные сообщения с определёнными пользователями.

Раннее создатели Telega объяснили эту функциональность "родительским контролем" (якобы, родитель может запретить ребёнку открывать то, что запрещено), но просмотр исходного кода показывает, что "чёрные списки" существуют отдельно и применяются глобально для всех пользователей.

Как это работает:

  1. Настройка для каждого пользователя blacklist_filter_enabled (ключ JSON в TelegaUserConfig, полученный из собственного API настроек Telega, по умолчанию: false)
  2. При включении каждое открытие чата/профиля/истории вызывает:
    POST https://api.telega.info/v1/api/blacklist/filter
    Body: { "targets": [{ "type": "user|channel|chat|bot", "id": 123456 }] }
    Response: { "blacklisted": [{ "type": "user", "id": 123456 }] }
  3. Если цель в черном списке → отображается BlacklistedOverlay, контент полностью скрыт
  4. Результаты кэшируются локально в moderation_list SharedPreferences

При этом в BlacklistedOverlay отображается следующий текст:

Материалы недоступны Этот [чат/канал/бот] недоступен в связи с нарушениями правил платформы

создавая у пользователя впечатление, что контент был заблокирован администрацией Telegram (платформы), а не жуликами-админами Telega (всего лишь безобидный клиент от маленького стартапа из Казани).

Где конкретно применяется эта логика:

Местоположение Эффект
ChatActivity.checkIsBlacklisted блокирует открытие чата
ProfileActivity.checkIsBlacklisted блокирует просмотр профиля
PeerStoriesView.checkIsBlacklisted блокирует просмотр историй

Ключевые классы:

  1. ru.dahl.messenger.data.rest.ModerationService → Делает запрос HTTP POST api/blacklist/filter

  2. ru.dahl.messenger.data.repository.ModerationRepository → Локальный кэш + логика удаленной проверки

  3. ru.dahl.messenger.data.entity.BlacklistRequestObject → Формирует объект запроса { targets: [{ type, id }] }

  4. ru.dahl.messenger.data.entity.BlacklistResponseObject → Обрабатывает объект ответа { blacklisted: [{ type, id }] }

  5. ru.dahl.messenger.data.entity.TargetType → Перечисление: USER, CHANNEL, CHAT, BOT

  6. ru.dahl.messenger.data.entity.TelegaUserConfig → Конфигурация для каждого пользователя с blacklistFilterEnabled

  7. ru.dahl.messenger.ui.components.BlacklistedOverlay → Наложение UI экрана блокировки

TL;DR: Telega может удаленно скрывать любого пользователя, канал, чат или бота от всех пользователей Telega и создавать впечатление, что он заблокирован для всех администрацией Telegram.


Не пользуйтесь клиентом Telega — это Мах на минималках

Надеемся, эта статья послужит исчерпывающим доказательством того, что Telega — на самом деле не безобидный маленький стартап из Казани, а самое настоящее вредоносное ПО, в худшем случае имеющее связи и поддерживаемое государством.

Если кто-то из ваших близких и знакомых пользуется этим клиентом — настоятельно убедите их удалить его и завершить сессию в настройках аккаунта. Один пользователь Telega лишает приватности не только себя, но и всех своих собеседников без их согласия — они даже не знают об этом.

Использование Telega — это примерно то же самое, как если бы вы взяли телефон незнакомого человека, зашли на нем в свой аккаунт Telegram и отдали навсегда этот телефон обратно. А у этого человека есть родственник, который работает в полиции.

Для восстановления работоспособности Telegram пользуйтесь исключительно официальным клиентом и встроенной функцией прокси-серверов. Использование любого другого клиента Telegram точно также ставит ваши персональные данные, аккаунт и устройство под угрозу.

В каком-то смысле Telega даже хуже чем Мах — в государственном мессенджере у вас нет нескольких лет истории переписок со всеми вашими знакомыми, которые можно было бы прочитать, проанализировать, подписаны ли вы на "неугодные" каналы, а самое главное, при использовании Telega вы думаете, что все ваши данные надежно защищены — это же Telegram, а не Мах!

Обновления Все обновления, если таковые будут, публикуются в Telegram-канале.