From bb02709be3e2cbabd816d3ed1d80ff5cf9db505e Mon Sep 17 00:00:00 2001 From: evgeny Date: Tue, 3 Nov 2026 19:33:45 +0100 Subject: [PATCH] Plan staged isolation of group service access --- doc/group_isolation_plan.txt | 218 +++++++++++++++++++++++++++++++++++ doc/tasks.md | 4 + 2 files changed, 222 insertions(+) create mode 100644 doc/group_isolation_plan.txt diff --git a/doc/group_isolation_plan.txt b/doc/group_isolation_plan.txt new file mode 100644 index 000000000..22a224858 --- /dev/null +++ b/doc/group_isolation_plan.txt @@ -0,0 +1,218 @@ +Межгрупповой доступ: план завершения изоляции +Дата: 03.11.2026 +Статус: проект исправления; этапы ниже ещё не реализованы. + +1. Цель и исходное состояние + +На одном ядре могут существовать несколько CHAT-групп и UTUN. Узел, допущенный +только в A, не должен получать данные, менять состояние или запускать операции B. +Проверка должна работать на уже открытом общем ETCP и после отзыва членства. +Наличие транспорта, маршрута, TOPO_GROUP_NODE или записи в общем node_registry +не является разрешением на API группы. + +MEDIA_DELIVERY уже использует обязательную криптографию router, проверку +topo_group_chat_allowed и закрытие запрещённых каналов через revalidate_group. +Для него есть негативный сетевой тест на двух группах общего ETCP. +Последний полный прогон после этого изменения: 239/239; это НЕ проверка изоляции +остальных протоколов. Новые замечания ниже пока основаны на чтении кода. + +Основные подтверждённые места для исправления/проверки: + - radio_recv/broadcast_recv: выбор группы без проверки допуска входящего соседа; + - conn_mgr_router_recv_handler/cm_open: существование группы/узла вместо допуска; + - TCP/UDP/ICMP proxy и routing_pkt_from_etcp_cb: отсутствует входной фильтр группы; + - topo_group_peer_allowed: для не-CHAT возвращает разрешение; + - MEMBER_FILES/GROUP_AVATAR и ряд других сервисов: проверка данных внутри + callback не задаёт обязательную подпись router HELLO/ACK/CLOSE и других controls; + - multicast mc_report_recv: проверяет форму и дескриптор группы, но не членство + отправителя; raw mc_recv проверяет принятого соседа, но не свежий допуск из БД; + - ADMIN_KEY: канал берётся из payload без равенства router group; соответствие + приватных ключей ключам канала проверяется, поэтому произвольная подмена ключа + этим замечанием не доказана; + - NAT_DETECTION group_node: топология и подписанный снимок не заменяют членство; + - member_in_channel означает наличие любой строки. Его использование в DM, + mailbox и MEMBERS требует разбора по назначению; массовая замена недопустима. + +2. Решение + +Развивать существующие механизмы, без второго универсального слоя авторизации. + +2.1. Групповые routed API + +Использовать etcp_router_require_crypto и etcp_router_set_authorize. Для CHAT +базовый допуск уже реализован в topo_group_chat_allowed: живая группа и активное +локальное членство self и peer (source=0, deleted=0, admitted=1). +Криптографически проверяется конечный source из router, а не ETCP next hop. +SIGNED обязателен для данных и controls; существующие требования ENCRYPTED +сохраняются. Controls без payload подписываются без шифрования пустого тела. + +Политика проверяется до создания состояния и вызова receive_ready/обработчика, +при отправке, повторе, доставке очередей и loopback. Ошибка чтения допуска означает +отказ. Callback политики остаётся чистым: чтение состояния, без мутаций/callbacks. +Проверки прав конкретной операции остаются в сервисах: owner файла, storage, +supernode, подпись автора, приглашение, адресат, идентификатор текущего запроса. +Если payload содержит канал, он обязан совпадать с авторизованным router group. +При регистрации проверять ошибки установки обеих политик и убирать частичную +инициализацию. Отдельный новый framework или реестр дублей SQL не требуется. + +Не требовать READY как доказательство членства. Особенно это недопустимо для +CONN_MGR: он помогает создать соединение. Его локальный open и входящие команды +проверяют допуск до загрузки узла в группу, cm_ensure_entry, таймеров и NCD. +Повторная проверка нужна при выборе посредника, retry и публикации готового пути. +Для сервисов, работающих и с CHAT, и с UTUN, выбор политики определяется типом +реальной группы; неизвестный тип не получает автоматического разрешения. + +2.2. Raw групповые пакеты + +RADIO/BROADCAST/MULTICAST не проходят через router. Проверять входящий +аутентифицированный ETCP_CONN и текущий допуск его peer именно к группе пакета. +Для рассылки по соседям также нужна принятая живая сессия этой группы на этом conn. +Общий проверяющий код размещать рядом с топологией групп; не копировать SQL +в каждый протокол. Проверять до dedup, очередей, callbacks и пересылки. +Исходящие/отложенные отправки также фильтруют адресатов по текущему допуску. + +Такая проверка закрывает доступ постороннего соседа. Она не превращает поле src +внутри raw RADIO/MULTICAST в сквозную подпись автора. Его нельзя использовать +как доказательство личности для привилегированной операции. Подмену src внешним +узлом проверять тестом вместе с отказом самому соседу. Защита от подделки автора +уже допущенным участником требует отдельного подписанного формата и не должна +выдаваться за результат простого фильтра членства. + +STREAM имеет собственные сессии и проверки участников; применять к нему правило +допуска до побочных действий, сохраняя его транспортный жизненный цикл. Проверки +соседства RADIO нельзя автоматически навязать прямому STREAM поверх общего NCD. + +2.3. UTUN + +Проверки group_id == TOPO_GROUP_UTUN недостаточно: чужой CHAT-узел может указать +это значение. [allowed_keys] сейчас управляет входящим транспортом; allow_all=1 +нужен, в частности, для новых CHAT-узлов и не должен открывать TUN/NAT/proxy. + +Предлагаемая политика: отдельный список публичных ключей UTUN, например секция +[utun_allowed_keys]. По умолчанию внешний доступ закрыт; self допускается при +работающем UTUN-сервисе. Не импортировать автоматически транспортные allowed_keys, +все [client] или записи BGP. Список проверяется по проверенной идентичности узла, +одинаково для UDP/STCP/REALITY и routed источника за промежуточным узлом. +Явно открытый UTUN, если он нужен продукту, должен включаться отдельной настройкой +UTUN; транспортный allow_all не является этой настройкой. + +Это изменение конфигурационного контракта: на каждом принимающем UTUN-узле +понадобится допуск конечных участников, а не только ближайшего сервера. Простой +список ключей выбран для первого исправления; подписанное распределённое членство +UTUN означало бы отдельный протокол управления и существенно больший объём. + +Одной политикой UTUN закрыть BGP JOIN/обмен, CONN_MGR, NAT_DETECTION, DATA, +NAT и обе стороны TCP/UDP/ICMP proxy. У routed API обязательна проверенная подпись +source, иначе проверка списка ключей по подставленному node_id не имеет смысла. +NAT/proxy сохраняют собственные ограничения provider/via, ожидаемого peer и потока. +При изменении допуска закрывать соответствующие логические операции и сокеты, +сохраняя общий транспорт, необходимый CHAT. Учесть start/stop и применение конфига. + +2.4. Bootstrap, синхронизация и личные данные + +Routed JOIN обслуживает A-C, уже состоящих в канале; ему применим групповой допуск +и защита controls. Новый J входит через raw CHAT_SYNC/GROUP_INVITE. Исключения +разрешают только конкретную команду добавления с проверенным invite/add_key, +целевой идентичностью, каналом, attempt и сроком действия. Временного членства нет. + +MEMBERS/Merkle может требоваться до admitted=1 для получения подписанного состава +и восстановления допуска. Сохранить отдельное разрешение синхронизации MEMBERS, +привязанное к проверенной идентичности и конкретному каналу/сценарию восстановления. +Не выдавать через него обычный DB_SYNC сообщений и другие групповые API. Простое +наличие строки, placeholder или tombstone нельзя молча объявить достаточным правом: +каждый разрешённый bootstrap/recovery случай должен иметь отдельный тест. + +Для DM/CALL/DEVGROUP/FILE_TRANSFER разделять право пользоваться маршрутом группы +и право на личную беседу, вызов или объект. Сохранить проверки адресата и E2E, +снимка устройств/эпохи и истории. Смена общей группы для маршрута не должна менять +личность собеседника или права на вложение. Отзыв доступа к A останавливает A, +но допускает новое согласование через B, если оба участника допущены в B. +Ранее сохранённая локальная личная история не удаляется при отзыве маршрута. + +2.5. Отзыв и владение + +После commit изменения допуска использовать существующий revalidate_group. +Проверить все пути: deleted, admitted, source, изменение group_policy, удаление +self, остановка/удаление группы. Отмена сервиса адресуется по (group, peer, service) +и его идентификатору операции. Не закрывать общий ETCP или чужой NCD handle. +Убирать запрещённые router/service очереди, таймеры, ожидания, подписки и retries; +для отложенных callbacks и завершения workers повторно проверять актуальное право +до выдачи результата или записи. Уже переданные в транспорт/полученные данные +нельзя отозвать задним числом; проверяется прекращение новых действий после отзыва. + +3. Этапы реализации + +Этап 1. Стенд и общий контракт доступа + Расширить подход test_media_delivery_integration: реальные ядра, SQLite, + подписанные участники, две группы и один физический ETCP. Инъекция должна идти + ниже локального запрета отправителя, иначе тест проверит лишь клиентскую защиту. + Зафиксировать отрицательные воспроизведения RADIO/BROADCAST, CONN_MGR и proxy. + Добавить осмысленные логи отказа и очистки: service, group, source, next_hop, + команда/операция, фаза проверки, причина; без приватных ключей/содержимого файлов. + Критерий: в старом коде наблюдаем конкретный запрещённый эффект, после исправления + он отсутствует; нормальное действие в разрешённой группе проходит. + +Этап 2. Routed CHAT и управление соединениями + Подключить политику у MEMBER_FILES, GROUP_AVATAR, RADIO_CALL, ATTACHMENT_KEYS, + ADMIN_KEY и routed JOIN. ADMIN_KEY дополнительно связывает канал с router group. + CONN_MGR проверяет вход, local open, кандидатов и отложенные переходы состояния. + NAT_DETECTION и MULTICAST_REPORT получают допуск конечного источника и подпись + controls; STREAM routed — согласованную с его действующими проверками политику. + MEDIA_DELIVERY остаётся контрольным образцом и регрессией. + Критерий: чужой/отозванный peer не создаёт сессий, файлов, запросов подключения, + NAT-проб и отчётов; unsigned HELLO/ACK/CLOSE не воздействуют на разрешённый канал. + +Этап 3. Raw групповые обмены и отзыв + Общий фильтр группового соседа для RADIO/BROADCAST/MULTICAST; проверка перед + локальной доставкой, dedup, forwarding и возобновлением отложенной отправки. + Проверить STREAM raw и очистку его flows/relay при отзыве. Проверить BGP, + DB_SYNC, CHAT_SYNC и Merkle по отдельным bootstrap/обычным командам. + Критерий: подстановка чужого group/src не доставляет callback, не загрязняет + dedup и не порождает пересылку; удаление участника прекращает текущую передачу. + +Этап 4. Независимый допуск UTUN + Реализовать отдельную конфигурацию доступа, отказ по умолчанию и применение + политики из п. 2.3 во всех входах UTUN, включая DATA/TUN и клиентские proxy replies. + Обновить sample, документацию и тестовые конфиги явным допуском нужных узлов. + Критерий: CHAT-only peer с валидным транспортом не использует UTUN даже указав + правильный UTUN group_id; разрешённый routed клиент работает через посредника. + Проверить UDP/STCP/REALITY и существующие proxy/NAT/load тесты, включая нагрузку + после введения подписи. Не заменять проверку членства наличием маршрута. + +Этап 5. Личные сервисы, bootstrap и полная матрица + Проверить DM, DM_MAILBOX, DM_MEDIA, FILE_TRANSFER, CALL/CALL_AUDIO/CALL_VIDEO, + CALL_VIDEO_CONTROL и DEVGROUP; обязательные controls и групповые/предметные права. + Завершить тесты raw JOIN/invite, MEMBERS recovery и серверного add_key. + Сопоставить каждый ID из etcp_api.h с реализованной политикой и сетевым тестом. + NTP_TIME/NCD_CONTROL/SVC_ROUTE — общие транспортные службы: проверить их границы + отдельно. Не навязывать им фиктивное CHAT-членство. Проверить отсутствие обхода + через raw DATA/неизвестный ID и явно включаемую BLE_PROBE instrumentation. + Критерий: по каждому ID есть разрешённый сценарий, отказ либо документированный + транспортный/bootstrap контракт; без строки «не проверено» для групповых API. + +После каждого этапа: целевые тесты и ./check.sh; изменения фиксировать отдельными +логически завершёнными коммитами. Этапы 2/3 не означают готовность этапов 4/5. +Успешный общий набор без новых отрицательных сценариев не закрывает задачу. + +4. Обязательная матрица регрессий + + 1) Участник только A обращается к API B через существующий ETCP. + 2) Тот же peer использует API A успешно на этом же транспорте. + 3) Подмена group/source/service и несовпадение канала payload с router header. + 4) Подписанный чужим peer пакет и unsigned/поддельные HELLO/CHALLENGE/CONFIRM, + ACK/BUSY/CLOSE: проверка не ограничивается флагом SIGNED без верификации. + 5) Доступ отзывается только на принимающем узле после открытия сессии; отправитель + продолжает с прежней эпохой, передаёт новые пакеты и пробует открыть канал снова. + 6) Отзыв при backpressure, reorder, retransmit, активном файле, worker и callback. + 7) Удаление self, остановка/удаление B, последующее повторное добавление участника. + 8) A остаётся рабочей; общий ETCP и NCD handle другого владельца остаются живы. + 9) Разрешённый конечный отправитель через посредника: endpoint не принимает + next_hop за source; транзит не выполняет предметный API конечного узла. + 10) Поздний пакет/результат старой операции не относится к новой группе/операции + при совпавшем числовом stream/transfer ID. Учесть существующие границы epochs. + 11) Для запрета проверяется побочный эффект: callback/БД/файл/сокет/таймер/NCD, + а не только отсутствие ответа. Логи объясняют точную причину отказа. + 12) Положительные JOIN, MEMBERS recovery, DM через другую общую группу и разрешённый + UTUN проходят. Локальные loopback-вызовы соблюдают ту же предметную политику. + +Задача завершена только после реализации всех этапов и этой матрицы для каждого +относящегося к ней сервиса. Сам этот документ не подтверждает устранение пробелов. diff --git a/doc/tasks.md b/doc/tasks.md index 73ee41cc4..bd7f862bc 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -13,6 +13,10 @@ но не задают обязательную подпись control-пакетов в router. Нужны отдельные воспроизведения на общем ETCP, проверка подмены источника, отзыва доступа и соседней группы; правила JOIN/invite и личных DM учитывать отдельно. На этом этапе перечисленные дополнительные сценарии проверены чтением кода, сетевые регрессии ещё не добавлены. + План исправления и критерии по пяти этапам: [group_isolation_plan.txt](group_isolation_plan.txt). + Дополнительно включены DATA/TUN, MULTICAST_REPORT, ADMIN_KEY, NAT_DETECTION и аудит допуска DM/mailbox; + отдельный доступ UTUN не должен наследовать transport allow_all. MEMBERS recovery и первичный JOIN требуют + отдельных правил. План зафиксирован; новые этапы ещё не реализованы, вывод о полной изоляции преждевременен. [+] **Панель устройств групповой лички: свои и собеседника** — 03.11.2026. Общий снимок текущего состава закреплённых сторон, включая offline и fallback-устройство.