Перейти до вмісту
UGunixgram

Protocol

UnixProto

UnixProto — транспорт, на якому працює Unixgram. Він розв'язує одну задачу: доставити повідомлення туди й назад поганим каналом, не видаючи при цьому, що саме передається. Нижче — як це влаштовано.

Шлях повідомлення

Шлях повідомленняWebbrowserAndroidnativeCaddy:443 TLSGatewayGo · :5222UnixProtoWS :4001Unixgramapp :3000PostgreSQLRedisgw:push · unxp:pushwssreverse_proxytcpobfuscated2fan-outКаждый push публикуется в Redis, чтобы его увидели клиенты всех реплик — WIRE.md §1.7
Вебклієнт підключається через WebSocket крізь TLS-термінатор. Нативний застосунок може відкрити пряме TCP-з'єднання зі шлюзом, оминаючи HTTP цілком. Обидва шляхи сходяться на застосунку.

Стек транспорту

Стек транспортуПакетauth_key_id · nonce · ciphertextОбфускацияAES-256-CTR · необязательноТранспортlegacy · abridged · intermediate · padded · fullTCPпоток байтовТранспорт выбирается один раз по первым байтам соединения — WIRE.md §1.2
Знизу вгору: байти TCP, кадрування обраного транспорту, необов'язковий шар обфускації і, нарешті, пакет — єдине, що бачить прикладний рівень.

Рукостискання і сесія

Рукостискання і сесіяКлиентСерверclient_hello · X25519 pubserver_hello · X25519 pub · ECDSA подписьпроверка подписи по закреплённому ключуHKDF-SHA256 → auth_key · server_saltrpc · salt + msg_id (строго возрастает)resume · последний msg_id → досылка пропущенногоНезашифрованные вызовы отклоняются: GATEWAY_REQUIRE_ENCRYPTION = true — WIRE.md §1.5
Обмін ключами, перевірка підпису сервера за закріпленим ключем і відновлення сесії після обриву: клієнт надсилає номер останнього отриманого повідомлення, сервер досилає пропущене.

Два незалежні шари

Транспорт відповідає за те, як payload нарізаний у потоці TCP. Пакет відповідає за те, що всередині одного payload. Шари не знають один про одного: клієнт може обрати будь-який транспорт, і формат пакета від цього не зміниться.

П'ять транспортів

Транспорт обирається один раз, за першими байтами з'єднання. Різні варіанти дають різний компроміс між накладними витратами і тим, наскільки потік схожий на випадковий шум.

Обфускація

Потік цілком, разом із тегом транспорту, загортається в AES-256-CTR. Це не шифрування — ключ виводиться з самого рукостискання. Задача інша: прибрати впізнавані заголовки, за якими трафік класифікується як «месенджер».

Шифрований канал

Обмін ключами — X25519, далі HKDF-SHA256 дає 256-бітний auth_key. Усередині пакета лежить сіль, ідентифікатор повідомлення, метод і параметри. Сіль порівнюється за сталий час, а ідентифікатор зобов'язаний строго зростати — це захист від повтору. Незашифровані виклики сервер відхиляє.

Realtime поверх WebSocket

Другий контур — кадри MessagePack на окремому порту. Версія протоколу узгоджується одним числом під час рукостискання і може бути лише знижена. Клієнт, який просить надто стару версію, отримує термінальну відмову й переходить на резервний канал.

Доставка між репліками

Реєстр з'єднань живе в процесі, тому push, що надійшов на одну репліку, самі по собі не побачать клієнти інших. Кожне відправлення публікується в спільний канал Redis, і кожна репліка доставляє своїм клієнтам сама. Відправник чекає на власну копію назад — інакше локальні клієнти отримали б подію двічі.

Транспорти та їхні накладні витрати на пакет

ТранспортТегКадруванняНакладні
legacyuint32 BE довжина + тіло4 Б
abridged0xefдовжина/4 одним байтом; 0x7f + 3 Б LE для довгих1–4 Б
intermediate0xeeeeeeeeuint32 LE довжина + тіло4 Б
padded intermediate0xdddddddduint32 LE довжина + тіло + 0–15 випадкових байт4–19 Б
fullдовжина + seqno + тіло + CRC3212 Б