«План Б»: как работает P2P-связь без серверов и интернета. Часть первая

Разбираем архитектуру децентрализованного чата на MQTT, ECDH и AES — и почему это может спасти связь в критической ситуации


Сегодня я наткнулся на любопытную статью на Хабре (впоследствии почему-то удалённую). Автор назвал проект «План Б» — одностраничное HTML-приложение для защищённой переписки, которое работает вообще без серверов. Никакой регистрации, никаких логов, никаких централизованных точек отказа. Просто файл, который можно открыть в браузере, договориться с собеседником о названии канала — и обмениваться сообщениями, которые никто не прочитает.


Первая мысль: очередной «крипто-мессенджер для параноиков». Но чем глубже я копал, тем больше понимал — это не просто игрушка. Это принципиально иной подход к архитектуре связи, который в определённых обстоятельствах может оказаться единственным рабочим вариантом.


Давайте разберёмся, как устроен «План Б», на каких протоколах он основан и почему эта архитектура заслуживает внимания даже за пределами сообщества privacy-энтузиастов.


---


Точки отказа современного интернета


Прежде чем говорить о решении, давайте поймём проблему. Все привычные мессенджеры (Telegram, WhatsApp, Signal) построены по клиент-серверной модели. Даже с E2E-шифрованием сервер остаётся критической точкой отказа:


1. Сервер можно заблокировать — по IP, по домену, на уровне провайдера

2. Сервер можно взломать — получить базы пользователей, метаданные

3. Сервер может лечь — под DDoS или технической нагрузкой

4. Сервер может передавать логи — по закону или доброй воле


Именно поэтому в последние годы активно развиваются децентрализованные протоколы. Но большинство из них (Matrix, ActivityPub) всё равно требуют как минимум один сервер для старта. «План Б» идёт дальше.


---

Архитектура: три кита «Плана Б»


Автор проекта использовал три проверенных стандарта IETF, упаковав их в один HTML-файл:


1. Транспорт — MQTT over WebSocket


В основе — протокол MQTT (Message Queuing Telemetry Transport). Он был придуман для телеметрии и IoT, но отлично подходит для децентрализованного чата.


MQTT работает по модели publish/subscribe. Клиенты подключаются к брокеру, подписываются на топики и публикуют сообщения. Брокер — это «глупый» ретранслятор. Он не хранит историю, не проверяет содержимое, не требует аутентификации.


В «Плане Б» используется публичный брокер HiveMQ через WebSocket Secure (wss://). Почему публичный? Потому что его не нужно поднимать самому. Это точка входа, которая работает «из коробки».


Что видит брокер?


· IP-адреса подключившихся клиентов

· Названия топиков (каналов)

· Тот факт, что кто-то кому-то что-то отправил


Чего не видит брокер?


· Содержимого сообщений (оно зашифровано)

· Идентификаторов пользователей (ключи генерируются локально)

· Истории переписки


2. Идентичность — отпечаток ключа вместо логина


В «Плане Б» нет понятия «логин» или «пароль». Идентификатор пользователя — это криптографический отпечаток (fingerprint) его асимметричного ключа.


При первом запуске браузер генерирует пару ключей ECDH (Elliptic Curve Diffie-Hellman) на кривой P-256. Публичный ключ становится «именем» пользователя, приватный остаётся в оперативной памяти.


Важно: ключи живут только в текущей сессии. Обновили страницу — получили новую идентичность. Автор сознательно пошёл на это ради безопасности: никакие ключи не пишутся на диск, их нельзя изъять при обыске или вытащить из дампа памяти после закрытия вкладки.


Можно модифицировать код и сохранять ключи в localStorage, тогда идентичность станет постоянной. Но базовый вариант — эфемерный.


3. Безопасность — ECDH + AES-GCM + TOFU


Самая интересная часть — как собеседники договариваются о шифровании.


Протокол рукопожатия (handshake):


1. Алиса подключается к каналу #secret

2. Она публикует сообщение HELLO со своим публичным ключом

3. Боб, подписанный на тот же канал, получает ключ Алисы

4. Боб вычисляет общий секрет по протоколу ECDH (умножает свой приватный ключ на публичный ключ Алисы)

5. Боб публикует свой публичный ключ

6. Алиса получает ключ Боба и тоже вычисляет общий секрет


Математика ECDH гарантирует: общий секрет получается одинаковым у обоих, но вычислить его, зная только публичные ключи и трафик, невозможно (проблема дискретного логарифма).


Что дальше?

Все последующие сообщения шифруются общим секретом через AES-GCM (Galois/Counter Mode). Это симметричное шифрование с аутентификацией — если злоумышленник попытается подменить сообщение, расшифровка не удастся.


TOFU (Trust On First Use):

При первом контакте ключ собеседника сохраняется (в памяти сессии). При повторном подключении сверяется отпечаток. Если ключ изменился — это сигнал о возможной MITM-атаке (человек посередине).


---

Код: как это выглядит на практике


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


Генерация ключей ECDH


```javascript

const keys = await crypto.subtle.generateKey(

{ name: "ECDH", namedCurve: "P-256" },

true,

["deriveKey", "deriveBits"]

);

```


Браузерный Web Crypto API делает всё сам. Мы даже не видим сырых байт — только объекты CryptoKey.


Вычисление общего секрета


```javascript

const sharedBits = await crypto.subtle.deriveBits(

{ name: "ECDH", public: peerPublicKey },

myPrivateKey,

256

);


const aesKey = await crypto.subtle.importKey(

"raw",

sharedBits,

{ name: "AES-GCM" },

true,

["encrypt", "decrypt"]

);

```


256 бит общего секрета превращаются в ключ для AES.


Шифрование сообщения


```javascript

const iv = crypto.getRandomValues(new Uint8Array(12));

const encrypted = await crypto.subtle.encrypt(

{ name: "AES-GCM", iv: iv },

aesKey,

encodedMessage

);

```


IV (инициализационный вектор) генерируется случайно для каждого сообщения и передаётся открыто вместе с зашифрованными данными.


---


Где «План Б» бессилен: честно о слабых местах


Автор не скрывает ограничений. Архитектура сознательно принесла в жертву некоторые аспекты ради простоты и доступности.


1. Метаданные видны брокеру


Публичный MQTT-брокер видит, кто и когда подключился к каналу. IP-адреса не скрыты. Для настоящей анонимности этого недостаточно.


Как можно улучшить: запускать клиент через Tor (в браузере — просто открыть страницу в Tor Browser). Тогда брокер увидит IP выходной ноды, а не реальный адрес.


2. Нет Perfect Forward Secrecy (PFS)


Если злоумышленник запишет весь трафик, а потом украдёт приватный ключ одного из участников, он сможет расшифровать все старые сообщения. В Signal, например, эта проблема решается протоколом Double Ratchet, который постоянно обновляет ключи.


Почему не реализовали: сложность. Для одностраничного демо статический ECDH — разумный компромисс.


3. Уязвимость к DoS-атакам


Поскольку брокер публичный, злоумышленник может просто зафлудить канал мусорными сообщениями. Клиент будет пытаться их расшифровывать (и проваливаться), тратя ресурсы.


Защита: на уровне приложения можно добавить проверку proof-of-work или белые списки ключей, но это усложнит код.


4. Нет офлайн-режима


Для работы нужен доступ к MQTT-брокеру через WebSocket. Если интернета нет — связи нет.


---

Где это может пригодиться?


Я задал этот вопрос сам себе и нашёл несколько сценариев, где «План Б» выглядит не игрушкой, а серьёзным инструментом.


Сценарий 1: Массовые блокировки


Представьте, что в стране заблокированы Telegram, WhatsApp, Signal. Публичные прокси и VPN тоже под давлением. «План Б» можно:


· Скачать один HTML-файл на флешку

· Раздать контактам

· Договориться о названии канала по телефону или при встрече

· Продолжить общение через любого публичного MQTT-брокера (их много, и блокировать все — задача нетривиальная)


Сценарий 2: Временные рабочие группы


Нужно быстро организовать защищённый чат для группы людей без регистрации и установки софта. Открыли страницу, ввели один и тот же канал — и готово. Никаких аккаунтов, никаких привязок к телефону.


Сценарий 3: Обход DPI на корпоративных сетях


MQTT over WebSocket часто не блокируется «по умолчанию», потому что используется в легитимных IoT-проектах. В корпоративной сети, где запрещены мессенджеры, такой трафик может проходить незамеченным.


Сценарий 4: Образовательные цели


На примере «Плана Б» можно наглядно показать, как работает ECDH, AES-GCM, TOFU и publish/subscribe архитектура. Всё в одном файле, всё работает в браузере, никаких серверов.


---


Как улучшить «План Б» до production-решения


Если воспринимать проект как proof-of-concept, то для реального использования нужно добавить:


1. Смена брокера — возможность указать свой MQTT-сервер (на случай блокировки публичных)

2. Сохранение ключей — опционально, для постоянной идентичности

3. История сообщений — локальное шифрованное хранилище (IndexedDB)

4. Поддержка файлов — передача через тот же канал с разбивкой на чанки

5. Уведомления — через Web Push или фоновую синхронизацию (сложно в браузере)


Но даже в текущем виде это работоспособная система.


---

Что дальше?


На основе авторской статьи на Хабре (а всё-таки она была) я расскажу во второй части, как улучшить этот проект:


· Добавить поддержку mesh-сетей (LoRa, Bluetooth)

· Реализовать обход DPI через обфускацию трафика

· Внедрить протокол Double Ratchet для PFS


Лично мне кажется, что главная ценность «Плана Б» — не в готовности к использованию, а в архитектурной прозрачности. Это как швейцарский нож: не самый удобный инструмент для каждой задачи, но в критической ситуации может спасти.


Будем следить за развитием ситуации с блокировкой и другими проблемами месенджеров в стране.


P.S.


Жду ваши мысли в комментариях. Использовали ли вы подобные децентрализованные системы? Видите ли сценарии для «Плана Б» в своей работе?

1
7 комментариев