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

204 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Эксплуатация 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-команды:
```sh
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`](../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-оверлея** — во время
незавершённого полного отката это может быть единственная копия:
```sh
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-менеджер): скрипт намеренно оставляет метку сериализации, а снимает её
только полное удаление модуля менеджером. Если модуль остался установленным и
вы хотите им пользоваться, метку нужно убрать вручную:
```sh
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 +
новый модуль» достижима.