The Messenger of Everything

habr.png

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

Единым стандартом мог бы стать XMPP, но он, в отличии от E-Mail, появился относительно поздно и не успел набрать достаточную аудиторию, чтобы корпорации не могли уже от него отказаться. Ведь там быстро поняли, что без удержания аудитории внутри собственной экосистемы много не заработать. Да и кроме того, надо признать, у XMPP было достаточно недостатков из-за обилия расширений, многие из которых, несмотря на свою важность, оставались в экспериментальном статусе, а какие-то и вовсе дублировали друг друга.

Пожив в «новом дивном мире» десятка мессенджеров в смартфоне, и ощутив все недостатки такого положения дел, мы наконец готовы к чему-то новому.

И да, нам нужен новый стандарт!

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


Почему всё так плохо?

Но сначала, давайте разберёмся, почему бы просто всем не перейти на какой-то один уже популярный == централизованный мессенджер, будь то условный WhatsApp, или, скажем, Telegram, имеющий немалую аудиторию в России.

Безусловно, централизованное построение позволяет больше зарабатывать владельцам, и тем самым не только окупать разработку, но и вкладывать значительные деньги на рекламу и даже прославление практически отсутствующих функций, таких как, защищённость сервиса, например. Однако, вместе с этим, владелец может внезапно решить закрыть сервис, трактор переехать провод из дата-центра, или просто мессенджер может быть забанен на территории определенной страны. Не обязательно по политическим причинам, может быть, и по требованию условных правообладателей, может быть множество причин. Хорошо, если несмотря на ничтожный размер рынка, Telegram с переменным успехом продолжает работать в России, но это связано с личными счётами владельца, а в случае блокировки того же WhatsApp — вряд ли Facebook будет вкладывать значительные средства для обхода блокировок.

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

Хорошо, почему бы тогда не перейти на что-то федеративное. Например, тот же Matrix. Не буду говорить про HTTP Long Polling, плохую отказоустойчивость серверов и откровенную гиковость интерфейса клиентов — всё это решаемые задачи, пусть и не тривиальные (на глобальном уровне это ничего не меняет). Нравится, что разработчики учли опыт XMPP и разрабатывают единые спецификации вместо кучи независимых XEP-ов, но это лишь один из недостатков XMPP. Другой проблемой является классическое устройство федеративной сети, когда мы вынуждены выбрать какой-то сервер и доверять его владельцу, что он будет обеспечивать работоспособность сервера и не будет его закрывать. А в случае очередного выхода из строя дата-центра, мы окажемся отрезанными от мира, не имея возможности общаться с прошлого аккаунта на другом сервере. Даже если вы создадите новый аккаунт, и каким-то способом перенесёте на него список своих контактов со старого сервера, при общении вам придётся снова каким-то образом подтвердить, что это действительно вы, а не кто-то, представляющийся вами.

В этом случае, может быть, вовсе отказаться от серверов? Существует некоторое количество мессенджеров, основанных на безсерверной технологии. Частным случаем здесь выступает популярный в узких кругах Firechat, использующий mesh-сеть из wifi и bluetooth устройств для общения пользователей. Этот мессенджер действительно хорошо работает, когда все пользователи сконцентрированы, например, на площади. Но это довольно специфическая ситуация и даже если вообразить ситуацию, когда каждый житель планеты установит приложение — это создаёт массу других проблем от разрывов mesh-сети по географическим признакам и скорости обмена сообщениями с дальними пользователями, до объёмов необходимых хранимых данных на устройствах. Но, наверное, данный мессенджер выбивается из общей массы и в нашем сравнении лишний. Он скорее экспериментальный, чем ориентированный на конкретного пользователя.

Существуют и такие проекты, как Tox, пытающиеся реализовать мессенджер на технологии p2p. Такой подход позволяет не беспокоиться за сохранность сервера, и заблокировать такой мессенджер практически не представляется возможным. У Tox огромное множество проблем, но это очень интересный проект, имеющий свою нишу. Нет смысла перечислять конкретные недостатки Tox, ведь проект развивается и несмотря на то, что p2p сервисы значительно сложнее разрабатывать, если поставить такую задачу, можно придумать различные интересные архитектуры построения такой сети: со своими достоинствами и недостатками, различными требованиями к ширине интернет-канала и объёму пространства на устройстве, с супер-нодами, одновременным входом с разных устройств и даже доставкой сообщений offline. Но общим всегда будет значительная избыточность трафика по сравнению с клиент-серверной архитектурой и повышенный разряд аккумулятора на мобильных устройствах из-за необходимости постоянного удерживания большого числа соединений и различных вычислений.

Таким образом, хоть p2p и является интересной технологией, но окажется неэффективной при необходимости, скажем, отправить свои координаты спасателям, находясь где-то на дереве в тайге с почти отсутствующем интернет- соединением и 1% заряда аккумулятора.


Как это исправить?

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

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


Адресация

Каждый пользователь получает свой адрес в формате E-Mail, или XMPP, то есть никнейм@домен. Но в отличии от вышеупомянутых сервисов, указание домена не несёт такую же важную адресную роль в данной архитектуре.

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

В интернете домены стоят денег, что пусть не исключает массовую регистрацию, но значительно уменьшает её масштабы. В централизованных сервисах часто вход через привязку к мобильному телефону, что также не является исключающим фактором, но и сим-карты тоже не из воздуха берутся! И в связи с этим, кстати, интересно, как с этим собираются бороться в https://toxme.io/ — сервисе для Tox, позволяющем ассоциировать длинные ключи с коротким ником. Не вижу причин, почему они не могут быть заспамлены миллиардами мусорных никнеймов.
Кроме того, домен может иметь смысл для различных аккаунтов для дома и работы. Или для организации внутрикорпоративной сети.

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

С точки зрения серверного ПО, если запрашивается пользователь по его отпечатку ключа, сервер производит в своей таблице поиск соотнесённого с ним логина, если запрашивается сразу по логину, соответственно, этот шаг пропускается. Затем производится соответствие логина и адреса сервера, на который в данный момент времени делегирован аккаунт. Если таких записей нет — считается, что за аккаунт отвечает тот сервер, который указан после @ в логине.


Профиль пользователя

В клиентском приложении хранится профиль пользователя, представляющий:


  • Полный логин пользователя
  • Список дублирующих серверов
  • Публичный и приватный ключ пользователя
  • Информация о профиле, такая как список контактов, настройки чатов и профиля пользователя

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

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

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


Дополнение для браузеров

У многих продуктов уязвимая точка — это веб-приложение. И у этого решения, безусловно, масса недостатков. Такой чат не будет загружен, пока вы находитесь оффлайн, затем потребуется ожидать полной загрузки, а ещё адрес может быть заблокирован, или сервер может упасть. Вручную перебирать адреса — не особо хотелось бы.

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

В связи с этим я предлагаю отказаться от веб-приложения как такового, а предлагать установить дополнение для браузера, в котором все эти недостатки по определению отсутствуют.

Кроме того, отсутствие необходимости владельцам серверов настройки веб-клиента снизит порог входа для создание своего сервера. Каждому домохозяйству — по собственному серверу!


Транспорты

Кому нужен мессенджер, в котором не с кем общаться? Есть интересные проекты необычных мессенджеров, но проблема отсутствия аудитории не позволяет им набрать хоть какую-то популярность. В результате чаще всего мессенджеры с большой аудиторией получают ещё больше аудитории, а мессенджеры с малой — её теряют. И чаще всего это положение может изменить только значительные вложения в рекламу.
Ну и кроме того, такое положение вещей требует установки очередного мессенджера, когда нужно срочно связаться с кем-то, кого нет в других сетях.

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

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


Криптография

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

Здесь нет ничего нового, используются стандартные средства шифрования GPG.
Пока не решён вопрос с шифрованием в группах, но, вероятно, можно воспользоваться механизмом, используемым в Signal.


Что уже сделано

На данный момент нами уже создан сервер на Python с использованием Tornado, в котором реализованы базовые функции мессенджера, существует слегка замороженная веб-версия, которую следует преобразовать в дополнение для браузера, есть библиотека на Rust, на основе которой функционирует клиент с интерфейсом на QML.

Подключение к серверу осуществляется с использованием WebSockets, в котором данные по-умолчанию сериализуются в бинарный формат представления данных CBOR, но при установлении WebSockets соединения существует возможность запроса другого формата, скажем, protobuf.

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

→ Вот репозитории, в которых содержатся наши наработки

© Habrahabr.ru