12 KiB
Спецификация Marafon Protocol (MFP) v1.0
Marafon Protocol это протокол логического уровня общего назначения и работает поверх любого транспортного. Также является базой для одноимённого ("Marafon") полнофункционального мессенджера.
Здесь описана спецификация базового протокола; спецификация версии протокола используемая в мессенджере будет размещена в другом репозитории.
Основной фокус при работе над сим проектом идёт на:
- Снижение оверхэдов, по сравнению с классическими решениями (Matrix, Discord, WhatsApp, пр. (Reject HTML+JSON, return to binary.)).
- Устойчивость к цензуре.
- Федеративность.
- Поддержка сквозного шифрования.
- Совместимость со всеми мажорными оверлейными сетями (Tor, I2P и yggdrasil).
- Расширяемость.
Поведение сервера и клиента
Сервер обязан:
- Оповещать клиент о всех ошибках, возникших во время его запроса, кроме:
- Связанных с безопасностью
- Оповещать сервер в федерации о всех ошибках, возникших во время его запроса, кроме:
- Связанных с безопасностью
- Связанных с внутренними неполадками
- По умолчанию отклонять все события, содержащие ложную подпись.
- Отдавать предпочтение данным других серверов, нежели клиентов.
- Отдавать предпочтение сетевым настройкам входящих соединений, нежели локальным (не считая лимиты).
Клиент обязан:
- Не сообщать серверу ни о каких ошибках на своей (клиентской) стороне.
- По умолчанию блокировать до решения юзера все события, содержащие ложную подпись.
- Явно уведомлять юзера при возникновении проблем с безопасностью, как минимум по умолчанию.
События, пакеты и их структура
Существует три уровня категорий событий:
- Надкатегория: Client2Server, Server2Client, Server2Server.
- Категория: например "Authentication", "User", "Message", т.д.
- Подкатегория: например "Login", "Create", "Delete", т.д.
Надкатегория никак не указывается в пакете, зависит от контекста и при упоминании - чаще всего опускается. Она также определяет структуру некоторых событий, которая может меняться в конкретных случаях. Остальные две являются шестнадцатеричными числами размерности указанной при хэндшейке.
Все категории вместе являются типом события. Значение типа - это шестнадцатеричное число, которое указывается в начале пакета.
Пакеты с событиями всех категорий, кроме явно оговорённых или принадлежащих к надкатегории Server2Client, содержат идентификатор серверной сессии, являющийся четырёхбайтным числом без знака (uint32_t
).
Пакеты с событиями всех категорий из надкатегории Client2Server, кроме явно оговорённых, содержат хэш полезной нагрузки, зашифрованный с помощью закрытого ключа подписи клиента.
Пакеты с событиями всех категорий, кроме явно оговорённых, содержат формат полезной нагрузки, занимающий ровно 1 байт (uint8_t
):
- 0x01: фиксированная схема.
- 0x02: "ячеистая" структура.
- Остальные значения зарезервированы.
Данные (AKA "полезная нагрузка") могут быть представлены в формате фиксированной схемы или в виде ячеек, которые являются расположенными последовательно парами "ключ-значение" и могут быть расположены в произвольном порядке относительно друг-друга. Все неизвестные ключи при парсинге игнорируются. Одна пара (AKA "ячейка") имеет следующий вид:
[key][data length][data]
Следовательно, полезная нагрузка в данном формате имеет вид:
[cell_1][cell_2][cell_3]...[cell_n]
Ключ и длинна данных являются шестнадцатеричными числами, размерность которых задаётся на этапе хэндшейка. Полезная нагрузка не может отсутствовать полностью (кроме особо-оговорённых случаев), а ключ не может являться нулём. Если значение конкретной пары пусто, то его длинна должна быть нулём.
Исходя из всего вышеописанного, итоговая примерная структура пакета выглядит следующим образом:
[category][subcategory][server session: 4B][payload hash: ?B][payload type: 1B][payload: >0B]
Размер пакета не нормирован и ответственность за его менеджмент остаётся на транспортном уровне. (Эталонная реализация MFP будет использовать общий универсальный интерфейс, который, в свою очередь, заворачивает все данные в релевантный протокол транспортного уровня)
Зарезервированные события
Некоторые категории событий зарезервированы под нужды базового протокола или просто для событий определённого рода. Второе носит рекомендательный характер; вы также можете использовать другие диапазоны для тех-же целей.
Все из зарезервированных типов помещаются в минимальную размерность типа события (т.е. по одному байту на категорию и подкатегорию). Ниже приведены диапазоны зарезервированных значений.
Зарезервировано для нужд протокола и запрещено к использованию в частных реализациях:
- Категория
0x01
- Все субкатегории: выделены для событий общей направленности.
- Категория
0x11
- Все субкатегории: выделены для событий ошибок и предупреждений протокольного уровня.
Рекомендуется к использованию при определённых случаях:
- Категории
0x12-0x1F
(включительно)- Все субкатегории: для событий ошибок и предупреждений.
Зарезервированные ключи ячеек
Скоро.
Соединение, аутентификация и сессии
Первичное подключение к серверу может выполнятся разными способами, в том числе подразумевающими маскировку траффика под существующие протоколы, но при использовании вне локальных сетей - должно сводиться к установке защищённого соединения.
Рукопожатие
См. файл HANDSHAKE.md
.
Аутентификация
Описываемый протокол предполагает наличие базовых механизмов аутентификации. Все они сводятся к проверке как цели, так и запрашивающего на предмет релевантного доступа.
Сессии и подпись
Каждый принятый сервером пакет, содержащий хэш полезной нагрузки, должен проверяться на соответствие подписи. Если сервер обнаруживает, что подпись неверна - сервер отвечает ошибкой, соединение разрывается, а администратор сервера и владелец учётной записи уведомляются об инциденте.
Каждый принятый клиентом пакет, содержащий хэш полезной нагрузки, может быть проверен на соответствие подписи. Если клиент обнаруживает, что подпись неверна - он должен оповестить пользователя.
Полезная нагрузка пакета может быть проверена на целостность сервером или клиентом с использованием подписанного хеша, но данная проверка может быть отключена, по усмотрению владельца сервера или пользователя клиента.
Если при проверке ID серверной сессии обнаруживается несоответствие - сервер отвечает ошибкой, соединение разрывается.