Как устроен одноразовый E2E‑чат без аккаунтов, истории сообщений и базы данных

Последние недели делал небольшой проект, который в итоге назвал 410.chat. Идея довольно простая. Иногда нужно поговорить с человеком напрямую, но совершенно не хочется ради этого обмениваться Telegram, номером телефона, почтой или создавать какой‑то постоянный контакт. Например, встретились где‑нибудь в комментариях, на форуме, в сообществе или на площадке объявлений. Нужно на пять минут уйти в приватный разговор — и всё. Обычно для этого мы всё равно идём в какой‑нибудь мессенджер и фактически открываем другому человеку постоянный способ связаться с собой. Мне стало интересно сделать наоборот: контакт, который существует только пока идёт конкретный разговор. Так появился 410.

За время, пока доводил первую версию до рабочего состояния, открыл исходный код проекта. Сейчас он целиком лежит на GitHub под AGPL-3.0: github.com/norenX/410-chat. То есть при желании можно не только посмотреть, как всё устроено, но и поднять свой экземпляр.

Как это выглядит

Открываешь: https://410.chat

Создаётся одноразовая ссылка. Её можно скопировать и отправить человеку обычным способом. А если второй человек находится рядом, теперь можно просто нажать Show QR и дать ему отсканировать приглашение телефоном. Это всё та же самая одноразовая ссылка — отдельной QR‑комнаты или второго типа приглашений нет. Когда второй человек заходит, начинается разговор. Дальше можно переписываться максимум 30 минут либо в любой момент уничтожить комнату вручную. После этого комнаты больше нет, а её URL возвращает настоящий:

HTTP 410 Gone

То же самое происходит, если после использования повторно отсканировать уже сработавший QR‑код. Собственно, отсюда и название.

Весь сценарий примерно такой:

create → share / QR → talk → destroy → 410 Gone

Никаких аккаунтов, имён пользователей и списка контактов.

Что происходит внутри

Сам проект довольно небольшой. Клиент — React/TypeScript. Сервер — Node.js + WebSocket. Базы данных для комнат и переписки нет вообще. Активные комнаты существуют только в памяти процесса. Там хранится состояние комнаты, подключённые участники, таймеры и служебная информация, необходимая для работы соединения. Истории сообщений на сервере нет. Когда клиент отправляет сообщение, сервер получает relay payload и передаёт его второму участнику. Сохранять массив сообщений или потом восстанавливать переписку из БД просто некуда. Когда разговор заканчивается, комната удаляется из in‑memory store. Если процесс сервера перезапустится — текущие комнаты тоже исчезнут. В данном случае это скорее свойство продукта, чем проблема.

Одноразовая ссылка

При создании комнаты получается ссылка примерно такого вида:

https://410.chat/r/...#secret=...

Секрет находится после #. То есть fragment браузер не отправляет серверу в первоначальном HTTP‑запросе. После того как второй человек воспользовался приглашением, оно считается использованным и повторно войти по нему уже нельзя. Сама неиспользованная ссылка тоже не живёт вечно. С QR я специально не стал придумывать никакую дополнительную серверную механику. QR содержит ровно эту же полную invite‑ссылку, включая #secret, и генерируется непосредственно в браузере. Никаких внешних QR API или сервисов для этого не используется. Полная ссылка с секретом не отправляется куда‑нибудь на сторонний генератор изображений — браузер сам строит SVG с QR‑кодом локально. Мне показалось, что это хорошо ложится в исходную идею проекта: не новая функция чата, а просто ещё один способ передать одноразовый контакт.

Шифрование

Сообщения шифруются в браузерах. При установлении соединения клиенты создают временные ключевые пары, после чего для сообщений используется XChaCha20-Poly1305. Сервер в нормальной работе занимается передачей зашифрованных данных между двумя браузерами и не получает ключи сессии или plaintext сообщений. При этом я специально не хочу писать что‑то вроде «абсолютно анонимный и неуязвимый мессенджер». Это веб‑приложение. Сервер всё равно видит сетевые метаданные: IP‑адреса подключений, время запросов и сам факт обмена трафиком. Кроме того, криптографический протокол никто независимо не аудитил. И поскольку JavaScript доставляется тем же сервером, компрометация сервера теоретически позволяет отдать клиенту изменённый код. То есть задача была не построить Signal. Задача была сделать небольшой сервис для одноразового разговора.

Код открыт

Именно из‑за всех этих оговорок мне в какой‑то момент стало казаться неправильным оставлять реализацию закрытой. Поэтому сейчас код 410 полностью открыт: github.com/norenX/410-chat

Там есть клиент, WebSocket‑сервер, реализация lifecycle комнат, E2EE, Docker‑конфигурация, тесты и описание модели безопасности. Проект можно запустить локально или поднять свой экземпляр. Это, конечно, само по себе не является доказательством безопасности — особенно для самописного криптографического протокола. Но по крайней мере теперь утверждения о том, что комнаты живут в RAM, сервер не хранит историю сообщений, а QR генерируется локально, можно проверить не только по моему описанию.

Зачем вообще ещё один чат

Вот это сейчас для меня самый интересный вопрос. Технически сделать чат оказалось не особенно сложно. Гораздо сложнее понять, существует ли самостоятельный сценарий temporary contact. Не «анонимный мессенджер». Не новый Telegram.

А просто возможность сказать:

вот ссылка, давай поговорим здесь, а потом у нас не останется постоянного канала связи друг с другом.

Мне такой сценарий кажется вполне естественным. Особенно когда второй человек находится рядом: открыл страницу, показал QR, поговорили — и после окончания разговора этот QR уже ничего не даёт. Но возможно, для большинства людей гораздо проще просто дать Telegram и потом при необходимости заблокировать человека. Собственно, поэтому и решил показать проект людям. Пока 410 специально остаётся маленьким. Я не хочу добавлять туда профили, контакты, историю, групповые комнаты и постепенно превращать его в ещё один обычный мессенджер.

Смысл как раз в ограничениях.

Одна ссылка. Два человека. Один разговор. После него — 410 Gone.

Если кому‑нибудь интересно поковырять:

https://410.chat

Исходники:

https://github.com/norenX/410-chat

Особенно интересно мнение по самой идее. Есть ли ситуации, когда вы бы предпочли такую штуку обычному мессенджеру? Ну и если будете тестировать — можно ломать lifecycle: открывать ссылку в нескольких вкладках, обновляться в неподходящий момент, отключать сеть, пытаться зайти повторно после уничтожения комнаты, сканировать уже использованный QR и так далее.

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


  1. ganqqwerty
    26.08.2026 14:58

    Не знаю как у кого, а у меня обратная проблема. Познакомился с чуваком, обменялся контактами, связался по делу, а потом ничего.


    1. TEXHOPYK
      26.08.2026 14:58

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

      С некоторыми людьми «навсегда» обрубал — нет ресурсов на общение. Потом восстановил.

      В одном сообществе, разбросанным на сотни чатов в Телеге и я получал помощь и давал поддержку много-много раз, получал подарки или дарил сам, вытаскивал из тяжёлых ситуаций. Находился в отношениях с девушками… Слушал предсмертные голосовые и успокаивал родственников после… Оказалось, что я оффлайн перемещаюсь на страницу чатов вточности таким же, какой в оффлайне. Мною люди интересуются чаще, чем я другими, и в сети так же. Как в оффлайне интересен женщинам, так же и в онлайне часто пишут в личку. Это приятно, потому что застенчивый, хотя по мне этого не видно.

      Иногда человека приходится жестко банить везде, где только можно, в чате, мессенджерах, телефоне, — потащил мои ресурсы попусту. Но я не нахожу применения сценарию 410.chat — общение на 30 минут и разбежались.

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

      Забанить нетрудно, а для анонимности (мнимой) есть левые аккаунты в мессенджерах.

      Это может взлететь где-нибудь в андеграунде, даркнете, но там нужны гарантии безопасности.

      Но некоторые продукты мне трудно понять. От почти всего, что Цукерберг делает, подташнивает, как и Ти ктока с Твиттером или как там его. 410 тоже непонятен, но кто не означает, что это что-то нерабочее.