magisk-zapret2/docs/USER_OPERATIONS_RU.md
loop-uh e39251266d Record the pairing the contract marker cannot gate
Raising the marker makes the older app refuse a 2.2.0 package through
its own update path, but a root-manager flash never consults it. That
leaves one reachable combination in which a completed stop is displayed
as a failure, so the operations guide names it and the remedy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-25 12:20:12 +03:00

16 KiB
Raw Permalink Blame History

Эксплуатация Zapret2: поддержка, разрешения и восстановление

Этот документ дополняет основной README точными эксплуатационными границами APK и root-модуля. Он описывает контракт исходников. Подписанный релиз и конкретное устройство считаются проверенными только после прохождения release/device-матрицы.

Поддерживаемая конфигурация

Компонент Контракт
Android API 24 (Android 7.0) или новее
Архитектура ARM64 или ARM; x86/x86_64 не поставляются
Root-менеджер Magisk 20.4+, KernelSU или APatch
Установка ZIP Только boot mode: интерфейс менеджера либо magisk --install-module, ksud module install или apd module install из Zapret2 Control
Firewall IPv4 iptables с NFQUEUE, --queue-bypass, multiport и mark; connbytes необязателен и при отсутствии включает исходящий KEEPALIVE-режим оригинального zapret2
IPv6 Требует того же набора в ip6tables; при его отсутствии IPv6 явно не перехватывается
Интерфейс Jetpack Compose, Material 3 Expressive, светлая/тёмная тема и dynamic color на Android 12+

KernelSU 3.x требует metamodule только для содержимого system/: CLI-wrapperов и hosts-оверлея. Основной сервис запускается модульным service.sh и не требует монтирования /system. Другие root-менеджеры не входят в подтверждённую матрицу: приложение не угадывает неизвестный installer backend.

Прошивка ZIP через TWRP/custom recovery не поддерживается. Installer получает корректные MODPATH, архитектуру и manager environment только в boot mode. Поддерживаемый root-менеджер сначала распаковывает кандидата в /data/adb/modules_update/zapret2, а активный модуль остаётся неизменным до перезагрузки.

Зачем APK нужны разрешения

  • INTERNET — только для запроса метаданных релиза и скачивания выбранных APK/ZIP.
  • ACCESS_NETWORK_STATE — для отображения типа текущего подключения.
  • REQUEST_INSTALL_PACKAGES — для передачи уже проверенного APK системному установщику. Приложение не может незаметно завершить установку за пользователя.
  • Root выдаётся отдельно через активный менеджер/libsu. Он нужен для чтения защищённого состояния, изменения конфигурации, запуска/остановки сервиса и staging обновления через manager backend.

Приватный FileProvider не экспортируется и выдаёт временный read-доступ только к проверенному APK внутри cache/updates/. Доступ ко всему cache или внешнему хранилищу не предоставляется.

Что происходит при обновлении

Каждое обновление создаёт новую чистую генерацию из release ZIP в /data/adb/modules_update/zapret2. Старое дерево не копируется и не объединяется с новым: runtime-настройки, пользовательские пресеты, hostlist-файлы и Lua-изменения начинаются с содержимого релиза. Активный модуль и запущенная служба не меняются до перезагрузки. Downgrade через APK не поддерживается.

Нормальное восстановление

У пакетного обновления нет собственного lock/transaction/backup/recovery слоя. Незавершённый staging можно повторить через root-менеджер; активная генерация остаётся неизменной до перезагрузки. Runtime lifecycle и Full rollback имеют отдельные контракты и не участвуют в установке новой версии.

Безопасный порядок действий:

  1. Откройте Control и дождитесь завершения автоматической проверки состояния.
  2. Если доступно, повторите операцию или выполните обычную остановку/перезапуск.
  3. Для подтверждённо повреждённой установки используйте Full rollback в Control.
  4. Сохраните вывод Logs/Diagnostics; экспорт ограничен последними 64 КиБ и проходит редактирование приватных идентификаторов.
  5. Если приложение не может доказать безопасное состояние, перезагрузитесь и повторите проверку до любых ручных удалений.

Fail-closed сообщение не означает, что нужно стирать state-файлы. Оно означает, что автоматическая операция отказалась продолжать без достаточного доказательства.

Удаление и чистая переустановка

Для обычного удаления используйте интерфейс своего root-менеджера и затем перезагрузите устройство. Обычный uninstall удаляет runtime-состояние, но сохраняет защищённый tombstone как доказательство завершённого удаления.

Для полностью чистой переустановки есть отдельная необратимая операция:

  1. В APK откройте Control → «Восстановление» → «Удалить данные модуля полностью» и подтвердите удаление. APK останется установленным, а его внутреннее состояние будет сброшено вместе с модулем.
  2. Если интерфейс APK недоступен, нажмите Action у модуля в root-менеджере два раза в течение 120 секунд. Первое нажатие создаёт одноразовое подтверждение, второе выполняет удаление.
  3. Перезагрузите устройство до повторной установки модуля.

Обе кнопки вызывают один канонический lifecycle-сценарий. Он останавливает сервис, проверяет отсутствие принадлежащих Zapret2 процессов и firewall-правил, затем удаляет активный/ожидающий модуль, настройки, списки, журналы, state, install/update/recovery каталоги и устаревшие файлы. Сам установленный APK не удаляется. Операция отказывается продолжать при активной или неоднозначной транзакции и не обходит recovery-доказательства.

Uninstall сначала публикует защищённый tombstone, затем выполняет bounded stop и проверяет отсутствие принадлежащих Zapret2 процессов/firewall-правил. Неавторизованные или неоднозначные файлы намеренно сохраняются для диагностики вместо слепого удаления.

Диагностика

Базовые root-команды:

su -c zapret2-status
su -c zapret2-stop
su -c zapret2-start
su -c zapret2-restart

Проверьте в таком порядке:

  1. Root-менеджер действительно выдал APK root и модуль не отключён/не ожидает удаления.
  2. Control не показывает active update/recovery или partial package state.
  3. В статусе доказаны текущий owner, PID/starttime, generation и ruleset.
  4. Ядро поддерживает обязательные NFQUEUE/firewall-возможности.
  5. AdGuard, NetGuard, AFWall+ и другие владельцы firewall временно отключены для изолированной проверки.
  6. Для стратегии выбран совместимый preset/category и существующие hostlist-файлы.

Read-only device preflight и формат сохраняемых доказательств описаны в tests/device/README.md. Изменяющие стадии допускаются только на одноразовом устройстве с явными подтверждениями, указанными в harness.

Модуль не запускается и не останавливается

Если и zapret2-start, и zapret2-stop отвечают RECOVERY_BLOCKED (в приложении — ошибка с доменом LIFECYCLE и стадией START_RECOVERY или STOP_RECOVERY), значит в /data/adb/zapret2-state осталось состояние прерванной операции. Снять его вправе только загрузочный проход восстановления — перезагрузите устройство, после чего автостарт отработает штатно. Это же указано в тексте самой ошибки.

Текст ошибки называет и само лекарство: перезагрузка помогает, когда состояние классифицировано как unsafe. Если речь о незавершённом полном откате (rollback-partial), сначала доведите откат до конца — перезагрузка сама по себе такие улики не снимает, они durable по замыслу.

Если и это не помогло, каталог состояния можно удалить целиком. Сначала проверьте, нет ли в нём резервной копии вашего hosts-оверлея — во время незавершённого полного отката это может быть единственная копия:

su -c 'ls -l /data/adb/zapret2-state/hosts.rollback.backup'
# если файл есть — сохраните его, например:
su -c 'cp /data/adb/zapret2-state/hosts.rollback.backup /sdcard/zapret2-hosts.backup'
su -c 'rm -rf /data/adb/zapret2-state'

Пресеты, hostlist-файлы и runtime.ini лежат в каталоге модуля и при этом не страдают.

Отказ STATE_UNAVAILABLE («insecure or unavailable zapret2 state directory») лечится тем же способом: каталог должен принадлежать root и иметь режим 0700.

Старт отказывает с «uninstall tombstone blocks start/restart»

Так бывает после ручного запуска uninstall.sh (без удаления модуля через root-менеджер): скрипт намеренно оставляет метку сериализации, а снимает её только полное удаление модуля менеджером. Если модуль остался установленным и вы хотите им пользоваться, метку нужно убрать вручную:

su -c 'rm -f /data/adb/zapret2-state/uninstall.tombstone'

Штатное удаление через root-менеджер этой ситуации не создаёт: там удаляется весь приватный каталог целиком.

Сообщение «IPv6 не удалось перепроверить»

На части устройств ядро собрано без ip6table_mangle, поэтому ip6tables установлен, но на запросы не отвечает. Модуль отличает такую ситуацию от занятой блокировки xtables: он повторяет опрос несколько раз и только после этого считает семейство недоступным на этом устройстве.

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

  • остановка и удаление завершаются успешно, но не заявляют «проверено чисто»;
  • полный откат сообщает Z2_RB_STATUS=partial при Z2_RB_FIREWALL_CLEAN=0;
  • полное удаление отдаёт квитанцию partial с той же оговоркой;
  • приложение показывает оговорку рядом с результатом, а не как ошибку.

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

Известные границы текущего дерева

  • Material 3 Expressive закреплён на экспериментальном API; это не stable Material 3.
  • Source-аудит не заменяет compile/lint/test, screenshot/TalkBack и rooted-device gates.
  • x86/x86_64, неизвестные installer backendы и устройства без обязательного NFQUEUE-контракта не заявлены как поддержанные.
  • До публикации следует сверить SHA-256 и подпись именно финальных APK/ZIP, а не только имена файлов или страницу релиза.
  • Обновляйте APK и модуль вместе. В 2.2.0 остановка вправе не подтверждать набор правил, когда одно семейство прочитать не удалось; приложение 2.1.x такую форму выразить не умеет и покажет успешную остановку как отказ. Маркер контракта поднят до 8, поэтому обновление модуля из приложения старая версия отклонит сама, — но прошивка ZIP через рут-менеджер эту проверку обходит, и там пара «старый APK + новый модуль» достижима.