Консоль модерации
Каждая версия каждого сета ждёт модератора, прежде чем попасть в каталог. Решение принимается в консоли. Она входит в бинарник b4hub, раздаётся по пути /admin с того же адреса, что и сам хаб, и доступна на английском и русском языках.
Консоль принадлежит хабу, а не зеркалу: у зеркала нет базы модерации, и оно не принимает решений, поэтому консоли у него нет. Разница описана в разделе Запуск хаба.
Одну вещь консоль называет иначе, чем роутер. То, что роутер называет отчётом «работает» или «не работает», в консоли называется голосом. Жалоба называется жалобой в обоих местах. Дальше на этой странице используются слова самой консоли, чтобы названия совпадали с тем, что на экране.
Вход
Пароль - это B4HUB_ADMIN_PASSWORD из окружения сервиса. Учётных записей и ролей нет; модератор - тот, у кого есть пароль.
| Сессия | Cookie в пределах /admin, действует семь дней |
| Смена пароля | Сразу завершает все открытые сессии |
| Попытки входа | Десять с адреса за каждые пятнадцать минут, верных и неверных, дальше отказ с указанием времени |
| Откуда принимаются действия | Из самой консоли; запрос на модерацию, пришедший не из неё, отклоняется |
Cookie помечается как secure, когда запрос пришёл по TLS или нёс заголовок X-Forwarded-Proto: https, который должен выставлять обратный прокси.
Без заданного пароля консоль открывается, но не работает: на странице входа написано, что модерация не настроена, а вход и любое действие модератора отклоняются. Тогда модерировать можно только командой b4hub moderate на хосте, как описано в конце страницы.
Страницы
| Страница | Для чего |
|---|---|
| Обзор | Что требует внимания, что опубликовано и что представляет собой этот хаб |
| Очередь | Версии, ждущие решения |
| Сеты | Всё решённое: в каталоге, устаревшие, не публикуемые, скрытые и отклонённые |
| Ключи | Участники, которых видел хаб, их активность и отметки на них |
| Зеркала | Хабы, объявившие себя зеркалами этого, и их состояние |
| Отзывы | Все голоса с весом, который они несут, и входящие жалобы |
| Каталог | Опубликованные файлы, история сборок и операции, которые публикуют заново |
| Статистика | Активность по дням, распределение опубликованных оценок и откуда приходят голоса |
| Журнал | Каждое действие на хабе: кто и когда его выполнил |
| Настройки | Суточные и часовые лимиты, сохранённые причины и уведомления |
На пунктах меню показаны счётчики: ждущие версии у Очереди, опубликованные сеты, требующие внимания, у Сетов, ждущие зеркала у Зеркал и открытые жалобы у Отзывов. Заголовок вкладки браузера начинается с числа ждущих версий, а цветная точка у Обзора показывает самую серьёзную из открытых проблем.
Сет или ключ, названный в любом месте консоли, - это ссылка. Она открывает боковую панель со своим адресом, /admin/sets/<id>, /admin/sets/<id>/v/<версия> или /admin/keys/<hmac>, поверх страницы, с которой её открыли; кнопка «назад» в браузере её закрывает, а адрес можно передать или сохранить в закладках. Поиск, фильтры, сортировка и страница списков тоже хранятся в адресе.
Каждое действие сообщает, что сделало, уведомлением с формулировкой самого хаба, например approved 01J9.../2.
Публикация
Решение меняет базу сразу. Каталог, который скачивают роутеры, пересобирается в фоне: сборка начинается через 1,5 секунды после последнего изменения и не позже чем через 10 секунд после первого, так что серия решений заканчивается одной сборкой. Ничто не ждёт сборку, а неудачная сборка не отменяет решение.
Состояние публикации видно на двух страницах:
| Где | Что показывает |
|---|---|
| Обзор, карточка Каталог | Каталог совпадает с базой или Есть изменения для следующей сборки, пока в базе есть изменения, которые ещё не опубликованы |
| Обзор, Состояние | Последняя сборка не удалась, с текстом ошибки |
| Каталог, Опубликованный каталог | То же, что на карточке Каталог, а также время и текст ошибки неудачной сборки |
| Каталог, История сборок | Каждая сборка, почему она запускалась, её результат и что она изменила |
Неудачная сборка остаётся на обеих страницах, пока какая-нибудь сборка не пройдёт успешно, а у роутеров тем временем остаётся предыдущий каталог. Собрать сейчас на странице «Каталог» ставит в очередь новую сборку. Консоль опрашивает состояние сборки и, когда сборка завершается, заново загружает каталог, раздел «Состояние», историю сборок, зеркала, сеты и счётчики в меню.
Обзор
Первым идёт Состояние - список того, что требует внимания, у каждого пункта ссылка на страницу, где это решается:
| Проблема | Уровень |
|---|---|
| Каталог не опубликован | ошибка |
| Последняя сборка не удалась, с текстом ошибки | ошибка |
| Манифест истекает в течение 2 дней | ошибка; в течение 7 дней - предупреждение |
| Успешной сборки не было дольше суток и двух интервалов проверки | предупреждение |
| Версия ждёт решения больше 72 часов | предупреждение |
| Одобренные зеркала не проходят проверку или отдают старый каталог | предупреждение |
| Зеркала ждут одобрения | заметка |
| Есть открытые жалобы | заметка |
| На хабе работает сборка для разработки или сборка из дерева исходников с незакоммиченными изменениями | заметка |
Под списком - факты, на которых он основан: когда истекает манифест, последняя успешная сборка, последняя ошибка сборки, версия, которая ждёт дольше всех, и сколько одобренных зеркал в манифесте, с ошибками или отстаёт.
Дальше четыре счётчика, каждый открывает свою страницу: ждущие версии, сеты в каталоге, ключи с числом заблокированных и зеркала с числом объявленных и ждущих. Каталог - то, что роутеры скачивают прямо сейчас: файл, эпоха и порядковый номер, когда он собран и когда истекает, сколько в нём сетов и файлов payload, сколько зеркал в нём указано и ждёт ли что-то следующей сборки. Этот хаб показывает версию, дерево исходников b4, из которого он собран, id ключа, публичный URL и число отозванных ключей. Модерация считает принятые решения.
Очередь
По карточке на каждую ждущую версию, старые первыми; карточка устроена как карточка сета на странице Сеты роутера.
Полоса по верхнему краю разбита на сегменты по частям сета: Цели, Разделение, Фейки, Маршрут и DNS, а у блокирующего сета вместо сегмента Маршрут стоит Блок. Эскалация не передаётся в общем сете, поэтому сегмента для неё в полосе нет. Сегмент подсвечен, если сет настраивает эту часть, а щелчок по нему открывает её настройки под карточкой. Если карточек больше одной, Сравнить по сетам над ними открывает одну и ту же часть на всех карточках, а Свернуть всё и Развернуть всё закрывают и снова открывают то, что открыто.
Версия стоит в правом верхнем углу, v1 - первая версия нового сета. Её подсказка показывает id сета и версию и объясняет, что будет означать одобрение:
| Подсказка | Что означает |
|---|---|
| Первая версия нового сета | Ничего из этого сета не опубликовано |
| Новая версия сета, опубликованного как vN | Одобрение заменит опубликованную |
| Новая версия сета, у которого сейчас ничего не опубликовано | Одобрение вернёт сет в каталог |
| Старше опубликованной vN | Одобрение ничего не изменит в каталоге: опубликованной остаётся самая новая активная версия. Версия обведена оранжевым |
В строке под названием - автор, семейство техник, версия b4, которая нужна сету, и время получения версии. Её подсказка добавляет точное время, сеть, из которой хаб увидел загрузку, сеть, которую заявил отправитель, и версию b4 с движком захвата, из которых сет был отправлен. Дальше идут сводка целей и маршрут: маршрут по умолчанию, маршрут по умолчанию с DNS-пинами или блокировка с её действием. У сета, который не разбирается версией b4 этого хаба, полосы нет, а вместо маршрута стоит пояснение.
Хаб никогда не хранит ключ участника. Он хранит, а консоль показывает как автора, HMAC этого ключа под собственным секретом хаба: 16 символов везде, где назван автор, полное значение - в панели ключа. Два сета одного участника несут одну и ту же метку; сам ключ из неё не восстановить.
Ниже идёт ряд отметок:
| Отметка | Что означает |
|---|---|
| нужен payload, блокирует трафик, закрепляет адреса, только категории, шаблон | Флаги, каждый объяснён в подсказке. блокирует трафик красный, только категории и шаблон оранжевые |
| автор заблокирован | Пока блокировка не снята, из сета ничего не публикуется |
| сет снят с каталога | Модератор снял весь сет с каталога |
| изменён | Версию изменил модератор. Подсказка показывает время и заметку, а щелчок сравнивает версию с полученным сетом |
| похожие сеты: N или похожие сеты не проверены | У хаба уже есть сеты, похожие на эту версию, или проверить это не удалось; щелчок открывает список или ошибку |
| открытые жалобы: N | На версию есть открытые жалобы; подсказка их считает, а щелчок открывает панель сета |
В списке - сеты, которые уже есть у хаба, с теми же целями, той же стратегией, общими или перекрывающимися доменами, тем же или похожим названием или тем же автором, каждый со статусом, голосами и принятым решением. Те же цели или то же название, что у другого сета, означают вероятный дубликат, и отметка похожие сеты: N становится оранжевой. Отклонить как дубликат заполняет причину отклонения ссылкой на сет, который дублируется.
Щелчок по карточке или Открыть подробности в меню в её углу открывает панель сета на этой версии со всем, что содержит версия: сводка целей, стратегия, записанная предложениями, флаги, имена серверов в фейковых пакетах, пины, хост DoH, файлы payload с размерами и ссылками на скачивание, Голоса и Жалобы на неё, отпечаток и версия b4, которая нужна сету. Проекция раскрывает сет в виде JSON. Если опубликованная версия есть, Сравнить с опубликованной vN в том же меню показывает под карточкой построчную разницу между ней и ждущей. В меню также есть Заблокировать автора; Одобрить, Изменить, Отклонить и Скрыть - кнопки внизу карточки.
Решения
| Действие | Причина | Результат |
|---|---|---|
| Одобрить | не нужна | Версия становится активной и попадает в каталог при следующей сборке |
| Отклонить | обязательна | Версия отклоняется, причина записывается |
| Скрыть | по желанию | Версия уходит из каталога при следующей сборке |
| Изменить | не нужна | Открывает редактор в диалоге |
| Заблокировать автора | по желанию | См. Блокировка ключа |
Каждый диалог до подтверждения показывает, что будет с каталогом: какая версия в него попадёт, какую заменит, уйдёт ли сет из каталога или ничего не изменится. Если скрыть опубликованную версию, вместо неё публикуется самая новая из более старых активных версий; Также снять весь сет с каталога этого не допускает. Если на версию есть открытые жалобы, диалог говорит, сколько из них будет отклонено или отмечено обработанными, а Оставить открытые жалобы открытыми оставляет их как есть.
Одобрение версии сета, снятого с каталога, или версии заблокированного автора требует второго подтверждения: версия становится активной, но остаётся вне каталога, пока сет не вернут или блокировку не снимут.
Причина отклонения записывается на хабе и читается в этой консоли. Каталог несёт только одобренные версии, поэтому до автора причина не доходит: его роутер лишь сообщает, что сета нет в каталоге.
Отклонение и скрытие говорят о разном. Отклонение - вердикт по присланному. Скрытие выводит из оборота, не требуя новой версии, и скрытая версия продолжает считаться дубликатом для последующих отправок с той же стратегией.
Несколько сразу
Флажок на каждой карточке или Выбрать все собирают версии для одного решения. Диалог пакетного действия показывает, что будет с каталогом для каждой выбранной версии, и называет те, к которым действие неприменимо, например версию, которая уже не ждёт решения; они пропускаются, а остальные меняются вместе, в одной транзакции, за которой следует одна сборка. Пакетное действие принимает не больше 200 версий.
Сохранённые причины
Каждый диалог, где спрашивается причина, предлагает сохранённые для этого действия причины в виде чипов, самые используемые первыми. Введённую причину можно сохранить кнопкой Сохранить как шаблон. Список правится в Настройках, отдельно для каждого действия: отклонения и скрытия версии, снятия сета, блокировки ключа, отклонения зеркала и отклонения жалобы.
Правка ждущей версии
Присланное с хорошей стратегией и неудачными целями можно исправить, а не отклонять. Редактор открывается только на ждущей версии: как только версия попала в каталог, отклонена или скрыта, у неё можно изменить лишь название и описание, как описано ниже.
В диалоге есть Название, Описание, Цели и Заметка модератора. У каждого вида целей своё поле:
| Поле | Что принимает |
|---|---|
| Домены | По одной записи в строке |
| Адреса | IP-адреса и диапазоны CIDR, по одной записи в строке или через запятые и пробелы |
| ASN | По одной записи в строке, в виде AS13335 или 13335; правильная запись сохраняется как число |
| Категории geosite, Категории GeoIP | Имена из файлов geosite и GeoIP самого хаба или введённые вручную; каждый роутер ищет их в своём файле |
| Версия TLS | Любая, TLS 1.2 или TLS 1.3 |
| Версия IP | Любая, IPv4 или IPv6 |
| Только по домену | Домены сопоставляются только по имени из хендшейка и никогда по их IP-адресу |
Показать полный JSON сета открывает всё, что несёт сет, одним JSON-документом; там меняются настройки вне этих полей. Поля и JSON держатся в согласии: правка поля переписывает в JSON только его ключ, а правка JSON заново заполняет поля. Пока JSON некорректен, поля целей заблокированы.
Описание - единственное поле, которое кнопка публикации на роутере оставляет пустым. Обычно сет приходит с именем в качестве названия и без описания, хотя точка входа /api/hub/share на роутере описание принимает, а хаб его сохраняет; поэтому описание на карточке либо пришло с публикацией, либо написано здесь.
Проверить прогоняет присланное через те же проверки, что и свежую публикацию, и отвечает одним из трёх вердиктов:
| Вердикт | Что означает |
|---|---|
| Ничего не отличается от текущей версии | Правка пустая, сохранение отклоняется |
| Отличаются только цели, название или описание | Отпечаток не меняется, поэтому уже записанные голоса продолжают считаться |
| Стратегия отличается от присланной автором | Отпечаток меняется, голоса этой версии удаляются, и опубликованный сет перестаёт совпадать с копией автора |
Результат, дублирующий сет, который у хаба уже есть, отклоняется сразу, с указанием этого сета. Проверка сообщает и о смене версии b4, которая нужна сету, и о каждом флаге, который правка добавляет или снимает; новый флаг блокирует трафик, шаблон или только категории превращает это сообщение в предупреждение.
Проверка также сообщает, что сделала очистка. Предупреждение, которое касается одного поля, стоит под этим полем:
| Поле | Предупреждения |
|---|---|
| Домены | Записи, кроме шаблонов regexp:, в которых есть пробел, запятая или точка с запятой и которые поэтому ни с чем не совпадают, домены, похожие на внутренние, слишком много доменов, блокирующий сет с сопоставлением по шаблону, пин, отброшенный потому, что его домена нет в целях или он указывает на внутренний адрес |
| Адреса | Адреса, похожие на внутренние, записи, которые не являются ни IP-адресом, ни диапазоном CIDR и которые роутеры пропускают, диапазон /0, покрывающий все адреса, слишком много адресов |
| ASN | Слишком много ASN, значения, которых b4 не принимает |
| Категории geosite, Категории GeoIP | Имена, которых нет в файле самого хаба; у автора может быть другой источник |
Предупреждения проверки перечисляют остальное: поля, которых b4 не знает, другие значения, которых он не принимает, хост DoH вне публичного списка, пины, отсутствующий payload. Отброшенные поля перечисляют то, что вообще не переносится общим сетом, с причиной. Адреса, категории и ASN, а также пробелы, запятые и точки с запятой в записях доменов проверяются по мере ввода; после проверки вердикт хаба заменяет эти пометки у каждого поля, которое с тех пор не менялось.
Если проверка отклоняет сет, Проверка отклонила сет: перечисляет каждую причину с её полем, а под полем цели та же причина видна красным, например ASN, который не является публичным номером AS.
Проверки списка доменов
Синтаксиса со звёздочкой в b4 нет, а обычная запись и так покрывает все поддомены. Под полем Домены редактор отмечает четыре способа ошибиться в списке, а Применить предложения переписывает его одним действием.
| Проверка | Пример | Что предлагается |
|---|---|---|
| Запись, которая никогда не совпадёт | *.example.com | Заменить на example.com или убрать, если он уже в списке |
Запись www. без домена | один www.example.com | Заменить на example.com, который покрывает оба. Другие поддомены не отмечаются |
| Повтор | Example.com. после example.com | Убрать |
| Запись, уже покрытая другой | cdn.example.com рядом с example.com | Убрать |
Запись regexp: никогда не считается покрывающей что-либо и никогда не отмечается как покрытая; единственная проверка, которая её касается, - проверка на повтор, убирающая один и тот же шаблон, указанный дважды.
Что изменит сохранение, последняя часть результата проверки, сравнивает изменённый сет с версией в её нынешнем виде, поле за полем, со строкой на каждую добавленную или убранную запись списка.
Сохранить оставляет версию ждущей. Сохранить и одобрить одобряет её в той же транзакции. Обе кнопки недоступны, пока проверка текущего содержимого не покажет изменение и отсутствие дубликата, и ни одна не примет сет, у которого нет ни домена, ни адреса, ни ASN, ни категории или есть версия TLS или IP, которой b4 не знает. Обе записывают заметку модератора, видимую только в консоли, и сохраняют присланное, чтобы карточка в очереди и панель сета могли показать, что было изменено; запись в журнале также перечисляет добавленные и убранные цели и версию b4, которая нужна сету, если она сменилась. Версия, которую кто-то изменил после открытия диалога, не перезаписывается, а отклоняется.
Правка текста опубликованной версии
Изменить название на любой версии вне очереди меняет её название и описание и больше ничего. Стратегия, цели, отпечаток и номер версии остаются прежними, поэтому роутеры не видят новой версии, а голоса продолжают считаться. Каталог несёт новый текст со следующей сборки: роутеры, которые уже применили сет, сохраняют своё имя, а новые получают новое название. Название обязательно и ограничено 120 символами, описание - 2000.
Сеты
Пять вкладок:
| Вкладка | Что на ней |
|---|---|
| В каталоге | Версия каждого сета, которая сейчас в каталоге |
| Устаревшие | Более старые одобренные версии, которые ещё хранятся, с версией, которая их заменила |
| Не публикуются | Сеты, целиком убранные из каталога, потому что их сняли или их автор заблокирован, с причиной |
| Скрытые | Скрытые версии с причиной; скрытые по жалобам и ещё не разобранные помечены |
| Отклонённые | Отклонённые версии с причиной |
Каждая вкладка показывает сеты карточками, как в очереди, и постранично загружается с хаба, по 25, 50, 100 или 200 сетов на странице. Сортировка упорядочивает их по пунктам Последнее обновление, Дата получения, Название, Автор, Оценка, Вес голосов, Устройства или Жалобы, а стрелка рядом меняет направление; на вкладках Скрытые и Отклонённые оценки нет, поэтому пунктов Оценка, Вес голосов и Устройства там нет. Поиск находит название, описание, id сета, метку и HMAC автора, семейство и коды техник, причину решения, каждый целевой домен, каждую категорию geosite и каждый ASN в виде AS15169.
У карточки, как и в очереди, есть полоса частей сета, версия, название, цели и маршрут, а кроме того:
| Часть | Что показывает |
|---|---|
| Версия | id сета и версия в подсказке, а на вкладке В каталоге ещё и все активные версии, если их больше одной |
| Строка под названием | Автор, семейство техник и время последнего изменения версии. Подсказка добавляет имя и метку автора, метку, которую видят роутеры, доверен ли ключ или заблокирован, сеть, из которой пришла загрузка, и время получения и обновления версии |
| Строка под маршрутом | Заменён версией vN со временем или причина, по которой версия скрыта, отклонена или не публикуется |
| Отметки | Флаги, автор заблокирован, сет снят с каталога, скрыта до одобрения, изменён, отметки внимания и жалобы |
| Оценка | Оценка, которую роутеры получили в последней сборке, а у версии, которую эта сборка не публиковала, например на вкладках Устаревшие и Не публикуются, - оценка на текущий момент: зелёная от 70%, оранжевая от 40% и красная ниже, или без оценки. Если следующая сборка изменит опубликованную оценку, за ней идёт далее: с текущим значением. Дальше независимые голоса «работает» и «не работает». В подсказках взвешенные голоса и устройства за каждой цифрой, голоса самого автора и сколько других сетов делят голоса этой стратегии. На вкладках Скрытые и Отклонённые не показывается |
Три переключателя сужают список: С открытыми жалобами, Изменённые и, на вкладке В каталоге, Требуют внимания. Отметки внимания на опубликованном сете - сигнал только для консоли, роутеры по-прежнему видят сет:
| Отметка | Когда |
|---|---|
| низкая оценка | Не меньше 3 взвешенных голосов и оценка ниже 30% |
| устарел | 60 дней без голосов, и вес почти не остался |
| ниже 50% | Независимых голосов достаточно для оценки, и она ниже 50% |
| открытые жалобы | На опубликованную версию есть открытые жалобы |
На карточке они сводятся в одну отметку, которая называет самую серьёзную и добавляет +N за остальные; подсказка перечисляет все. Открытые жалобы показывает отдельная отметка жалоб: открытые жалобы: N, ждёт проверки у версии, скрытой по жалобам, на которую ещё есть открытые, или жалобы: N, когда все жалобы разобраны. Щелчок по ней открывает панель сета.
На вкладках, где это применимо, карточки можно выбрать для пакетного действия, по одной или все на странице кнопкой Выбрать все: скрыть опубликованные и устаревшие версии, вернуть скрытые и одобрить отклонённые.
Карточка открывает панель сета на своей версии. В панели все версии сета, у каждой статус, факты и действия, которые допускает её статус. Скрытую версию можно вернуть, а отклонённую - всё-таки одобрить. В панели также все голоса за сет и его История: каждое действие над сетом, кто его выполнил и с какой причиной. В меню в углу карточки есть Открыть подробности, которое открывает ту же панель, и Открыть ключ автора.
Снятие сета с каталога
Снять сет в панели убирает весь сет из каталога при следующей сборке, каким бы ни был статус его версий. Версии сохраняют свои статусы, поэтому Вернуть в каталог возвращает ровно то, что было опубликовано. Снятие отмечает открытые жалобы на сет обработанными. Новая версия снятого сета по-прежнему принимается и ждёт в очереди, как любая другая.
Удалить навсегда внизу панели удаляет сет со всеми версиями, голосами, жалобами и файлами payload, которые не использует другой сет. Для подтверждения нужно ввести id сета. Убрать сет из каталога можно снятием; удаление - для записи, которой не должно было быть. Роутеры, применившие сет, сохраняют свою копию и теряют связь с хабом.
Ключи
По строке на каждого участника, которого видел хаб, по HMAC, с временем первого и последнего появления, числом подписанных им сетов, голосов и жалоб и сетью последней записи. Поиск принимает начало HMAC, имя, заметку или собственный id ключа роутера, который хаб переводит в HMAC. Фильтры сужают список по статусу (заблокирован, доверенный, ни то ни другое), по метке и по сетам (любые, в каталоге, ждущие, нет).
Строка открывает панель ключа:
| Раздел | Что в нём |
|---|---|
| Активность | Отправки, голоса, жалобы и объявления зеркал по дням за последние 90 дней |
| Сеты | Каждый отправленный ключом сет, с его статусом и жалобами на него |
| Голоса | Голоса ключа с весом каждого |
| Отправленные жалобы | Жалобы, которые подал ключ, и их состояние |
| Сети | Сети, из которых приходили его записи |
| Версии b4 | Версии b4 и движки захвата, о которых он сообщал |
| Объявленные им зеркала | Зеркала, которые он объявил |
| История | Каждое действие над ключом |
Заметки оператора добавляют имя, которое везде в консоли показывается вместо начала HMAC, свободную заметку и метку:
| Метка | Действие |
|---|---|
| свой | Только метка; голоса ключа учитываются как обычно |
| тест | Голоса ключа перестают учитываться в опубликованных оценках со следующей сборки, его жалобы - в автоматическом скрытии, а его активность не попадает в статистику |
| Действие | Результат |
|---|---|
| Заблокировать | См. ниже |
| Разблокировать | Ключ снова принимается; его сеты возвращаются при следующей сборке, голоса и жалобы снова учитываются |
| Доверять | Ключ перестаёт учитываться в суточных лимитах на ключ |
| Снять доверие | Снова учитывается |
Доверие снимает лимиты и ничего больше. Сеты доверенного участника ждут модератора, как и все остальные, а лимиты на сеть продолжают действовать.
Блокировка ключа
Блокировка - обратимый карантин. С момента блокировки:
- каждая новая запись, подписанная ключом, отклоняется;
- при следующей сборке его сеты уходят из каталога на вкладку Не публикуются;
- его голоса перестают учитываться в опубликованных оценках, а жалобы - в автоматическом скрытии;
- его ждущие версии можно одобрить только со вторым подтверждением, и пока блокировка действует, они остаются вне каталога.
Ничего не удаляется, и разблокировка возвращает всё. До подтверждения диалог блокировки считает, что затронет блокировка: сеты в каталоге, ждущие версии, голоса и стратегии, в которые они идут, и открытые жалобы. Он также называет зеркала, объявленные ключом; блокировка оставляет их в манифесте, а убирает их отклонение на странице «Зеркала».
Зеркала
Все хабы, объявившие себя зеркалами этого, ждущие первыми, в столбцах Зеркало, Статус, Проверка, Отдаёт и, на широком экране, Последнее объявление. Зеркало - это URL, который открывает зеркало в новой вкладке, а под ним версия b4hub из последнего объявления зеркала и ключ, которым оно объявлено. Подробности каждого столбца - в его подсказках. Статус объединяет решение с тем, что делает с зеркалом манифест:
| Статус | Что означает |
|---|---|
| ожидает | Ждёт решения |
| отклонено | Никогда не объявляется; причина в подсказке |
| в манифесте | Одобрено и есть в манифесте |
| добавляется | Одобрено и попадёт в манифест при следующей сборке |
| уходит | Уйдёт из манифеста при следующей сборке |
| остаётся | Не проходит проверку, но остаётся в манифесте, пока ни одно зеркало не проходит проверку |
| нет в манифесте | Одобрено и попадёт в манифест после следующей успешной проверки |
Проверка - результат последней проверки состояния: ок или сбой с тем, как давно она была, или ещё не проверялось.
| Действие | Результат |
|---|---|
| Одобрить | Сразу запускается проверка, и зеркало попадает в манифест, как только проверка пройдена |
| Отклонить | Остаётся в списке с причиной и никогда не объявляется. Причина обязательна |
| Удалить | Забывается и может объявить себя снова |
| Проверить сейчас | Проверяет одно зеркало; Проверить все - все одобренные |
Хаб проверяет каждое одобренное зеркало раз в 10 минут и ещё раз перед первой сборкой после запуска. Проверка запрашивает у зеркала адрес состояния и манифест и убеждается, что манифест подписан этим хабом; подсказка неудачной проверки называет шаг, на котором произошёл сбой. Одобренное зеркало остаётся в манифесте 24 часа после последней успешной проверки, и подсказка его статуса показывает, когда оно выпадет без новой. Если сбой у всех одобренных зеркал сразу, зеркала из предыдущего манифеста остаются в нём, пока одно из них снова не пройдёт проверку или модератор их не отклонит или не удалит; их статус - остаётся, а времени выпадения нет. Если после очередного круга проверок меняется набор зеркал, которые следует объявлять, запрашивается сборка.
Столбец Отдаёт сравнивает каталог, который был у зеркала при последней проверке, с каталогом этого хаба: актуально, отстаёт на сколько-то номеров, устарело, если отставание держится 15 минут после публикации нового каталога или у зеркала старая эпоха, или новее этого хаба. Подсказка называет манифест, который отдавало зеркало.
Отзывы
Две вкладки.
Голоса - все голоса, новые первыми, более старые подгружаются по запросу. В строке: когда пришёл голос, сет и версия, вид, сеть, которую увидел хаб, и сеть, которую заявил роутер, участник, домен, по которому был отфильтрован список, версия b4 и движок, и вес голоса. Фильтры сужают список по «работает» или «не работает», по тому, голосует ли автор сета, по известной или неизвестной сети, а также полями ASN и Страна, значения которых выбираются из сетей и стран, откуда приходили голоса, с общим числом голосов у каждого; выбранная страна оставляет в списке ASN только сети, у которых есть голоса из неё, и сбрасывает выбранный ASN, у которого таких голосов нет. Ссылка на сет или ключ добавляет фильтр по нему.
Столбец веса показывает, что голос вносит в опубликованную оценку: базовый вес, множители за сеть, молодой ключ и давность и итог на момент последней сборки. Если голос не учитывается, указано почему: ни один опубликованный сет не использует его стратегию, голос пришёл после последней сборки, ключ заблокирован или помечен как тестовый, или автоматические голоса перевесили бы ручные.
Виды голосов - «работает» и «не работает», поданные вручную, загрузка, которая засчитывается автору как «работает», и те, которые роутер мог бы отправлять сам из детектора DPI, watchdog доменов и Дискавери. Эти автоматические виды хаб определяет и взвешивает, но b4 их пока не отправляет.
Жалобы - входящие с тремя состояниями:
| Состояние | Что означает |
|---|---|
| открыта | Ждёт модератора; учитывается в автоматическом скрытии |
| отклонена | Признана необоснованной |
| обработана | По ней приняты меры |
У каждой жалобы время, сет и версия, сеть, участник, введённая причина и учитывается ли она. Отклонить и Обработана принимают необязательную заметку и применяются к одной жалобе или к выбранным; Открыть снова возвращает жалобу во входящие. Скрытие, отклонение, возврат и снятие сета закрывают открытые жалобы на то, что они затрагивают, и записывают причину.
Опубликованная версия скрывается автоматически, когда на неё набирается три открытые жалобы от независимых ключей и сетей. Жалоба учитывается, только пока она открыта, если её сеть известна, а её ключ не заблокирован и не помечен как тест. У жалобы, которую одобренное зеркало передало с верной подписью пересылки, сеть неизвестна, поэтому она не учитывается никогда. Возврат версии отклоняет её открытые жалобы, поэтому счёт начинается с нуля.
Каталог
Опубликованные файлы, зеркала в манифесте, ключ, которым подписывает этот хаб, и ключи, которые манифест отзывает.
История сборок записывает каждую сборку: когда и почему она запускалась, удалась ли, порядковый номер, число сетов, сколько она длилась и что изменилось в каталоге: сеты добавлены, убраны, получили новую версию, новый текст или новую оценку, изменился список зеркал или отозванных ключей. Сборка, изменившая только оценки, так и отмечается. Список можно сузить до изменений и сбоев или только до сбоев.
Три операции, каждая публикует заново:
| Операция | Что делает |
|---|---|
| Собрать сейчас | Ставит в очередь сборку, которая публикует из базы, даже если ничего не менялось |
| Начать новую эпоху | Сбрасывает порядковый номер. Каждый роутер считает новую эпоху главной и скачивает каталог заново |
| Отозвать ключ подписи хаба | Добавляет id ключа в список, который несёт каждый манифест. Роутеры перестают доверять всему, что им подписано |
Сборка отклоняется, а причина видна в истории сборок, в двух случаях: когда её эпоха и порядковый номер не окажутся больше уже опубликованного каталога или каталога, который отдаёт одобренное зеркало, - так выглядит база, восстановленная из старой резервной копии, - и когда база, ещё ни разу не публиковавшая каталог, заменила бы опубликованный каталог или подписала бы пустой ключом, встроенным в b4. Второй случай подтверждает флаг --new-database у serve или build.
Новая эпоха нужна, чтобы опубликовать каталог после восстановления базы из старой резервной копии: всё, что старше уже имеющегося у них, роутеры отклоняют, а хаб отказывается такое собирать, пока эпоха не сменится. В остальных случаях она лишь заставляет каждый роутер заново скачать каталог.
Роутеры хранят каждый отзыв навсегда; если позже убрать ключ из списка хаба, отзыв не отменится. Хаб отказывается отзывать ключ, которым сам подписывает, а для отзыва ключа, встроенного в b4, нужно отдельное подтверждение, потому что это отрезает все роутеры, доверяющие этому ключу.
Отзыв и блокировка - разные инструменты. Отзыв называет ключ подписи хаба или зеркала и через манифест доходит до каждого роутера. Блокировка называет участника и влияет только на то, что этот хаб принимает и учитывает.
Статистика
Счётчики за последние 7, 30, 90 или 365 дней, по дням UTC. Ключи с меткой тест не учитываются нигде на этой странице.
| Раздел | Что показывает |
|---|---|
| Итоги | Отправки с числом дубликатов, голоса «работает» и «не работает», новые ключи, жалобы и скрытые по ним сеты |
| Активность | Отправки, дубликаты и новые ключи по дням; голоса «работает», «не работает» и жалобы по дням |
| Модерация и публикация | Одобрения, отклонения, скрытия, автоматические скрытия и снятия по дням; сборки, неудачные сборки и объявления зеркал по дням |
| Опубликованные оценки | Глобальная оценка каждого сета текущего каталога в десяти интервалах, отдельно сеты с голосами хотя бы с двух устройств и остальные; медиана и сколько сетов с отметкой низкой оценки или устаревания |
| Сеты с наибольшим числом голосов | Сеты, за которые проголосовало больше всего ключей за период |
| Откуда приходят голоса | Голоса и ключи по странам и по сетям, по адресу, с которого пришёл голос, кроме голосов, переданных одобренным зеркалом с верной подписью пересылки, у которых сети нет; и ключи по версии b4 и движку их последней записи |
Журнал
Каждое действие на хабе записывается со временем, исполнителем, объектом, причиной и изменёнными полями. Исполнитель - консоль, вход по паролю (basic-аутентификация вместо сессии), командная строка или автоматически, например автоматическое скрытие; у записей консоли и входа по паролю есть ещё адрес, с которого пришёл запрос.
Журнал фильтруется по виду объекта, по исполнителю и по точному id объекта, более старые записи подгружаются по запросу. Действия, выполненные вместе в пакетном диалоге, помечены пакет, и по этой отметке показывается весь пакет. Та же история есть в панели каждого сета и каждого ключа.
Настройки
Шесть лимитов, каждый - целое число от 1 до 1000000, применяются со следующего запроса; то, что ключ уже израсходовал сегодня, сохраняется.
| Лимит | Период | По умолчанию |
|---|---|---|
| Сетов на ключ | сутки | 5 |
| Голосов на ключ | сутки | 20 |
| Жалоб на ключ | сутки | 20 |
| Объявлений зеркал на ключ | сутки | 48 |
| Новых ключей на сеть | сутки | 5 |
| Запросов на сеть | час | 2000 |
Сутки - календарный день UTC, час - часовой интервал, поэтому лимит, исчерпанный в 22:00 UTC, сбрасывается в полночь. Счётчики хранятся в памяти и обнуляются при перезапуске сервиса. Сеть здесь - /24 отправителя, для IPv6 - /48.
Запись, которую хаб отклонил, и отправленный сет, оказавшийся дубликатом уже имеющегося, не расходуют квоту участника. Ключ, отмеченный как доверенный, не учитывается в лимитах на ключ, но учитывается в лимитах на сеть.
Что видит роутер, упёршись в один из лимитов, описано в разделе Отчёты и жалобы.
Сохранённые причины хранят готовые причины, которые предлагаются в диалогах решений, отдельный список на каждый вид действия, у каждой короткая метка, текст и число использований.
Уведомления
Хаб может отправлять сводку о поступившем в чат Telegram, на webhook или туда и туда.
| Канал | Настройки |
|---|---|
| Telegram | Токен бота и id чата: число или @имя публичного канала. Бот должен состоять в чате |
| Webhook | URL, https:// или обычный http:// к loopback или частному адресу, и необязательный секрет для подписи |
Каждую настройку можно задать и в окружении сервиса, B4HUB_TELEGRAM_TOKEN, B4HUB_TELEGRAM_CHAT, B4HUB_WEBHOOK_URL и B4HUB_WEBHOOK_SECRET; значение оттуда важнее консоли, и она показывает такое поле только для чтения. Значения, введённые в консоли, хранятся зашифрованными ключом, выведенным из файла secret хаба, и никогда не отправляются обратно в браузер: страница показывает лишь, что значение сохранено, с id бота или схемой и хостом URL.
| Событие | Когда отправляется |
|---|---|
| Новые сеты в очереди | Отправка принята и ждёт решения |
| Жалобы | Жалоба принята |
| Скрыто по жалобам | Опубликованная версия скрыта автоматически |
| Неудачные сборки | Сборка каталога завершилась ошибкой, с текстом ошибки |
| Новые зеркала | Зеркало объявило о себе и ждёт одобрения |
До первого сохранения настроек выбраны новые сеты и жалобы. Отправки и жалобы от ключей с меткой тест не пересылаются.
Первое событие после затишья уходит сразу, следующие собираются не чаще одного сообщения за интервал сводки: по умолчанию 60 секунд, допустимо от 30 до 3600. Сообщение считает события каждого вида, перечисляет до десяти событий каждого, заканчивается ссылкой на страницу консоли, где они разбираются, и пишется на английском или русском. Включение канала или события не пересылает то, что пришло раньше.
Неудачная доставка повторяется с растущей задержкой, от 30 секунд до 30 минут, с учётом Retry-After; пока доставка не удаётся, ничего не теряется, потому что каждый канал хранит свою позицию в потоке событий. Для каждого канала видно, когда он последний раз доставил сообщение, сколько отправил и последнюю ошибку, пока сбои продолжаются. Отправить тест доставляет тестовое сообщение через сохранённый канал, включён он или нет.
Webhook получает POST с телом в JSON:
{
"hub": "https://hub.example",
"sent_at": "2026-09-27T12:41:15Z",
"counts": { "share": 2, "report": 1 },
"events": [
{ "kind": "share", "at": "2026-09-27T12:40:58Z", "set_id": "01J9...", "version": 1, "title": "Example", "author": "70837b639d58b777", "asn": "12389", "country": "RU", "url": "https://hub.example/admin/sets/01J9.../v/1" }
],
"more": 0,
"console": "https://hub.example/admin/queue"
}
Каждый запрос несёт X-B4hub-Timestamp - Unix-время отправки. Если задан секрет, есть и X-B4hub-Signature: sha256=<hex> - HMAC-SHA256 под секретом от времени, точки и тела запроса как есть. Перенаправления не выполняются, а любой статус вне 2xx считается сбоем.
Без консоли
b4hub moderate делает из командной строки то же, что и консоль, через те же проверки и с теми же записями в журнале. Команда открывает ту же базу напрямую, в режиме WAL с таймаутом ожидания, поэтому сервис может продолжать работать. Сама она ничего не публикует: каждое изменение оставляет запрос на сборку, который запущенный b4hub serve подхватывает примерно за десять секунд.
| Команды | Что делают |
|---|---|
list, approve, reject, hide, restore | Очередь и решения по версиям. Сет указывается как <id> или <id>/<версия>; можно указать несколько сразу, и approve применяется ко всем или ни к одному |
withdraw, reinstate, delete | Сеты целиком. delete требует --confirm <id> |
ban, unban, trust, untrust | Ключи, по HMAC |
reports, dismiss-report, resolve-report, reopen-report | Входящие жалобы |
mirrors, approve-mirror, reject-mirror, remove-mirror, check-mirror | Зеркала |
status, builds, epoch, revoke | Публикация, история сборок, новая эпоха и отзыв ключа подписи хаба с --confirm <key_id> |
audit | Журнал |
Правка версии, имени, заметки и метки ключа, сохранённые причины, уведомления и лимиты доступны только в консоли.