# Phala и Intel TDX: аттестация сборщика Telegram

Canonical page: https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/

Защищённый сервер, работающий круглосуточно на Hetzner или Phala Cloud, шлюзовой DNS и проверки, которые может повторить любая третья сторона.

[Project context and measured scale](https://phishdestroy.github.io/TgWitness/ru/docs/reference/overview/)

[Documentation index](https://phishdestroy.github.io/TgWitness/ru/llms.txt)

Translation coverage: this edition includes material from the English original.

Защищённый сервер, работающий круглосуточно на Hetzner или Phala Cloud, шлюзовой DNS и проверки, которые может повторить любая третья сторона.

[TgWitness](https://github.com/phishdestroy/TgWitness/blob/main/README.md) / [Документация](https://github.com/phishdestroy/TgWitness/blob/main/docs/README.md) · [Развертывание и восстановление](https://phishdestroy.github.io/TgWitness/ru/docs/reference/deployment/)

![Развертывание и восстановление](https://phishdestroy.github.io/TgWitness/assets/chapter-operate.svg)

Развертывание с высоким уровнем надежности добавляет независимые проверки среды сбора данных к проверке архива. Рецензент запрашивает записи о развертывании и доступе, хранящиеся у поставщика облачных услуг и Cloudflare, а развертывание с использованием Intel TDX добавляет аппаратную аттестацию среды сборщика данных.

Обычное использование локальной среды и Docker остаётся без изменений. Ничто здесь не запускается, пока вы не выполните развёртывание с помощью `python -m tgwitness.cloud`, а сборщик считывает данные с хоста только тогда, когда развертывание устанавливает `TGWITNESS_ASSURANCE`.

Блок-схема · Оператор → Сервер, брандмауэр без правил входящего трафика (API провайдера); Оператор → Туннель и DNS (API Cloudflare); Сервер, брандмауэр без правил входящего трафика → Туннель и DNS (только исходящие сообщения); Сервер, брандмауэр без правил входящего трафика → Ключ подписи, созданный на сервере; Verifier, токены только для чтения → Журнал провайдера и брандмауэр; Verifier, токены только для чтения → Адрес туннельного коннектора и входной трафик; Verifier, токены только для чтения → Подписанное заявление /api/assurance; Verifier, токены только для чтения → Архив доказательств в формате ZIP · Оператор · Verifier, токены толькодля чтения · Сервер, брандмауэр безправил входящего трафика · Журнал провайдера ибрандмауэр · Адрес туннельногоконнектора и входнойтрафик · Подписанное заявление/api/assurance · Архив доказательств вформате ZIP · Туннель и DNS · Ключ подписи, созданный насервере · API провайдера · API Cloudflare · только исходящие сообщения

**Схема в текстовом формате**

1. Оператор → Сервер, брандмауэр без правил входящего трафика (API провайдера)
2. Оператор → Туннель и DNS (API Cloudflare)
3. Сервер, брандмауэр без правил входящего трафика → Туннель и DNS (только исходящие сообщения)
4. Сервер, брандмауэр без правил входящего трафика → Ключ подписи, созданный на сервере
5. Verifier, токены только для чтения → Журнал провайдера и брандмауэр
6. Verifier, токены только для чтения → Адрес туннельного коннектора и входной трафик
7. Verifier, токены только для чтения → Подписанное заявление /api/assurance
8. Verifier, токены только для чтения → Архив доказательств в формате ZIP

**На этой странице**

- [Что может проверить верификатор](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#what-a-verifier-can-check)
- [Провайдеры](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#providers)
- [Конфиденциальная виртуальная машина на Phala Cloud (Intel TDX)](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#confidential-vm-on-phala-cloud-intel-tdx)
- [Перед началом работы](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#before-you-start)
- [Из панели](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#from-the-panel)
- [Быстрый туннель без домена](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#quick-tunnel-without-a-domain)
- [Развертывание](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#deploy)
- [Отладка развертывания и блокировка](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#debug-deployment-and-lock)
- [Удалить развертывание](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#remove-a-deployment)
- [Любой сервер (самосертифицированный)](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#any-server-self-attested)
- [Проверить](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#verify)
- [Отчет о передаче доказательств](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#report-for-evidence-handover)
- [Cloudflare в качестве внешнего свидетеля](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#cloudflare-as-an-outside-witness)
- [Чтение результатов развертывания](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#reading-the-deployment-result)

## Что может проверить верификатор

| Заявление | Как это проверяется | Ведёт |
| --- | --- | --- |
| Сервер был создан с помощью API провайдера в известный момент времени | Объект «Сервер» и его создание в собственном журнале провайдера | Провайдер |
| Никто не использовал пути доступа провайдера | Журнал консольных запросов, восстановление, сброс пароля, перекомпиляция, ISO, образы, резервные копии | Провайдер |
| Ничто не смогло подключиться к нему | В брандмауэре провайдера отсутствуют правила входящего трафика; SSH скрывается с момента первой загрузки | Провайдер (брандмауэр), хост (SSH) |
| Доступ к панели осуществляется только через туннель | Входящий трафик через туннель перенаправляется исключительно на панель; коннектор запускается с адреса сервера | Cloudflare |
| Именно это программное обеспечение работает | Подписанный хеш дерева исходного кода коллектора совпадает с хэшем коммита, развернутого в производственной среде. | Collector, сверка с Git |
| Ключ подписи был создан на этом сервере | Ключ подписывает заявление, в котором указываются идентификатор сервера провайдера и хеш полученного им файла cloud-init. | Collector, проверенный провайдером |
| Журнал принадлежит этому ключу и серверу | Каждый запуск процесса в доказательстве ZIP содержит показатели хоста для данного сервера | Доказательства ZIP |

Коллектор записывает состояние SSH, сеансы, историю входа в систему и информацию о загрузке в подписанные записи process-start и `host.state`. На обычной виртуальной машине это локальные инвентарные записи, которые эксперт сравнивает с независимыми записями провайдера. Приведенное ниже развертывание Intel TDX дополнительно проверяет измерения, основанные на аппаратных средствах.

## Провайдеры

| `--provider` | Учетные данные | Доступ Verifier только для чтения | Журнал провайдера для верификатора | Хранится для |
| --- | --- | --- | --- | --- |
| `hetzner` | `HCLOUD_TOKEN` | Прочитать токен того же проекта | Действия сервера и брандмауэра | Пока эти ресурсы существуют |
| `digitalocean` | `DIGITALOCEAN_TOKEN` | Личный токен доступа только для чтения | Действия Droplet | Пока Droplet существует |
| `linode` | `LINODE_TOKEN` | `linodes`, `firewall`, `events` области, доступные только для чтения | События учетной записи, версии правил брандмауэра | 90 дней |
| `vultr` | `VULTR_API_KEY` | Пользователь с доступом на чтение и `activity_logs` разрешением | Журнал активности аккаунта (метод, путь, участник) | 30 дней, а с подпиской на журнал аудита — дольше |
| `aws` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` | `ec2:DescribeInstances`, `ec2:DescribeSecurityGroups`, `cloudtrail:LookupEvents` | История событий CloudTrail | 90 дней |
| `phala` | `PHALA_CLOUD_API_KEY` | API-ключ того же рабочего пространства | Версии приложений и операции с CVM: изменения конфигурации и среды Docker Compose, перезапуски, обновления ОС | Пока приложение существует |
| `generic` | нет | нет | нет: **самоподтверждённый** | – |

Используйте отдельный проект, команду, аккаунт или субаккаунт для каждого дела: тогда у верификатора будет доступ только для чтения, и он увидит только эту развертку. Учетные данные считываются из `--provider-token-file` или из указанной выше переменной, но ни в коем случае не из командной строки. Для AWS в файле указывается `ACCESS_KEY_ID SECRET_ACCESS_KEY [SESSION_TOKEN]`; регион — `--location`.

В каждом отчёте указывается, какую информацию не могут отобразить записи каждого провайдера. Короче говоря: Hetzner регистрирует запросы консоли; консоль восстановления DigitalOcean, Lish/Glish от Linode и веб- консоль Vultr не регистрируются как таковые, поэтому доступ root блокируется при первой загрузке, и для входа в консоль требуется сброс пароля или изменение параметров загрузки, которые регистрируются. Vultr возвращает адрес консоли при нажатии любой клавиши, позволяющей прочитать данные инстанса; ни в записи, ни в отчёте он не сохраняется.

## Конфиденциальная виртуальная машина на Phala Cloud (Intel TDX)

При этом `--provider phala` коллектор работает в конфиденциальной виртуальной машине Intel TDX на [Phala Cloud](https://phala.com/), управляемой dstack. Хост и сотрудники Phala не могут читать её память, а процессор подписывает подтверждение того, что именно загрузила машина. Верификатор не доверяет Phala на слово: `tgwitness.tdx` самостоятельно проверяет каждое подтверждение, вплоть до закрепленного корневого центра сертификации Intel SGX, по спискам отзывов Intel и подписанным Intel данным о платформе, и отклоняет машины, которые могут быть отлажены или перенесены.

| Запись отчёта | Что здесь показано |
| --- | --- |
| `tdx_binding` | Аттестация охватывает подписанное заявление сборщика и случайное значение данного запроса. |
| `tdx_quote` | Intel подтверждает достоверность аттестации; она считается пройденной только в том случае, если Intel оценивает платформу как актуальную. |
| `tdx_compose_hash` | RTMR3, воспроизводимый из журнала событий dstack, измеряет количество сообщений, составленных в приложении, о которых сообщает сборщик данных. |
| `tdx_compose` | Этот код байт за байтом соответствует коду, скомпилированному из развернутого коммита: исходные файлы закреплены по хешу, оба изображения — по дайджесту, другого кода нет |
| `tdx_identity` | Аттестация поступает от развернутого приложения и экземпляра с использованием ключей из KMS Phala и зашифрованного диска. |
| `tdx_os` | Значения MRTD и RTMR0-2 соответствуют значениям, рассчитанным верификатором на основе образа ОС dstack, публикуемого Dstack-TEE, определённого по хешу образа ОС, сообщаемому CVM, а также на основе таблиц ACPI, формируемых QEMU для конфигурации виртуальной машины: прошивка, ядро, initrd, командная строка с хешем корневой файловой системы, память, виртуальные процессоры и устройства. Образ для разработки не проходит проверку |

The OS image (about 180 MB, of which 21 MB are kept) is downloaded once from [Dstack-TEE/meta-dstack](https://github.com/Dstack-TEE/meta-dstack/releases) into `dstack-images` beside the record; `--tdx-image FOLDER` uses another folder or an unpacked image, `--tdx-image none` skips the comparison. The measurement follows `dstack-mr` and the `qemu-acpi` crate of Dstack-TEE/dstack. Private measurement regressions compare QEMU's own ACPI output and a retained Phala Cloud quote; live qualification also needs the published image. `--tdx-measurements` still compares MRTD and RTMR0-2 given as JSON instead.

Каждый запуск коллектора, зафиксированный в журнале, сопровождается таким подтверждением, поэтому `verify --evidence` проверяет каждый запуск и образ ОС, с которого он был загружен. Ревизии приложений Phala и операции CVM служат в качестве журнала поставщика: изменение конфигурации Docker Compose после развертывания приводит к отклонению отчета, а перезапуски фиксируются для последующего анализа.

В панели выберите **«Конфиденциальная виртуальная машина · Phala Cloud»** в разделе **«Дополнительно»** → **«Сервер 24/7»** и вставьте ключ API Phala Cloud; быстрый туннель работает так же, как на Hetzner. Из командной строки:

```
python -m tgwitness.cloud deploy --provider phala --name case-1 --server-type tdx.small \
    --ref v0.8.0 --repository https://github.com/phishdestroy/TgWitness --quick-tunnel \
    --provider-token-file phala-key.txt
python -m tgwitness.cloud verify --record deployments/case-1/deployment.json \
    --provider-token-file phala-key.txt --cloud-init deployments/case-1/docker-compose.yaml \
    --source CHECKOUT_OF_COMMIT --fingerprint COLLECTOR_FINGERPRINT --report certificate.md
python -m tgwitness.cloud check-report --report certificate.pdf --verifier-fingerprint VERIFIER_KEY
```

`--tdx-collateral` считывает сертификаты и списки отзывов Intel из файла, а не загружает их с сайта Intel. Шлюз DNS здесь недоступен: у Phala нет провайдерского брандмауэра для исходящего трафика.

### Сертификат аттестации

При развёртывании Phala `verify --report certificate.md` также записывает сертификат: автономный файл `certificate.html` и файл формата A4 `certificate.pdf`, содержащий заключение, цепочку доверия от корневого сертификата Intel до ключа сборщика, сравнение с обычными серверами и серверами повышенной надёжности, результаты измерений рядом со значениями, рассчитанными на основе опубликованного образа, информацию о том, кто ручается за каждую часть, цепочку сертификатов Intel, все проверки, журнал поставщика, а также инструкции по повторению проверки. Отчёт в формате JSON остаётся авторитетным документом; страницы отображают его содержимое.

Отчёт заверяется цифровой печатью; данные заверения находятся в `certificate.seal.json` и соседних файлах `.tsq`/`.tsr`:

| Печать | Что это добавляет |
| --- | --- |
| Квалифицированная электронная временная метка, `http://tsa.belgium.be/connect` | Метка времени RFC 3161 для точной последовательности байтов `certificate.json`, выданная квалифицированным поставщиком доверенных услуг федерального правительства Бельгии (FPS Policy and Support, BOSA). Его подразделение включено в бельгийский доверенный список ЕС как квалифицированная служба меток времени со статусом granted; корневой сертификат (Belgium Root CA6) и записи списка по состоянию на выпуск от 20 октября 2026 года закреплены в `tgwitness/tsa_roots.py`. Согласно статье 41 Регламента (ЕС) № 910/2014 такая метка времени пользуется презумпцией точности даты и времени и целостности связанных данных во всех государствах — членах ЕС |
| Метка времени по RFC 3161, FreeTSA | Вторая, независимая отметка времени |
| Подпись верификатора | Ed25519 над текстом, содержащим SHA-256 отчёта и каждую метку времени, с использованием собственного ключа верификатора (`--sign-with FOLDER`, по умолчанию `~/.tgwitness/verifier`); PDF-файл содержит подпись, сгенерированную тем же ключом |

`--timestamp URL` (повторяемый) выбирает другие центры сертификации, `--timestamp none` — ни один, `--sign-with
none` оставляет печать неподписанной. `check-report` проверяет хеш отчёта, подпись верификатора, каждую временную метку относительно доверенного корня и её квалифицированный статус, а также подпись PDF-файла. Юридическая сила квалифицированной временной метки за пределами ЕС, а также отчёта в целом, определяется судом или органом власти, получающим данный документ; печать подтверждает момент создания отчёта и отсутствие в нём изменений.

Аттестация не может исключить наличие уязвимости в модуле TDX или микрокоде Intel, а также физический доступ к шине памяти. Тот, кто контролирует приложение в аккаунте Phala, может развернуть другой компоуз; он отображается как новая ревизия с новым хешем компоуза. Хост контролирует источник времени машины и сеть.

Развёртывание, проверка с `--evidence`, перезапуски, сравнение образа ОС, заверение сертификата и удаление проверены непосредственно на Phala Cloud; см. [прогон от 4 ноября 2026 года](https://phishdestroy.github.io/TgWitness/ru/docs/reference/verification/#live-phala-cloud-deployment--4-november-2026).

## Прежде чем начать

1. Зона Cloudflare, её ID учётной записи и токен API с правами **Cloudflare Tunnel Edit**, **Zone Read** и **DNS Edit**, указанные с помощью `--cloudflare-token-file` или `CLOUDFLARE_API_TOKEN`. Для верификатора: **права Cloudflare Tunnel Read**, **DNS Read** и, для журнала аудита, **Account Settings Read**. Без домена для [быстрого туннеля](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#quick-tunnel-without-a-domain) ничего из этого не требуется.
2. Учетные данные провайдера с правом записи в выделенный проект; `lock` использует то же самое:

   - Hetzner: токен API с правами на чтение и запись;
   - DigitalOcean: личный токен доступа с правом записи;
   - Linode: личный токен доступа с `linodes`, `firewall` и `events` областями доступа «чтение/запись»;
   - Vultr: ключ API выделенного аккаунта или суб-аккаунта;
   - AWS: разрешены учетные данные IAM `ec2:DescribeVpcs`, `ec2:DescribeImages`, `ec2:CreateSecurityGroup`, `ec2:AuthorizeSecurityGroupIngress`, `ec2:RunInstances`, `ec2:CreateTags`, `ec2:DescribeInstances`, `ec2:DescribeSecurityGroupRules` и `ec2:RevokeSecurityGroupIngress`.
3. Кит, который нужно запустить. Тег релиза однократно сопоставляется с соответствующим китом с помощью `git ls-remote`; сервер всегда получает только 40-символьный коммит.

## Из панели

На вашем компьютере в меню **«Дополнительно» → «Сервер 24/7»** запускается то же самое `deploy` для Hetzner в три шага: выберите Европу или США, вставьте токен Hetzner (чтение и запись), затем проверьте тип сервера, месячную стоимость, адрес и версию, которые панель нашла по этому токену. Ничего не создается до вашего подтверждения. Панель отображает каждый шаг в виде `deploy` по мере их появления, а затем — адрес, токен панели и отпечаток ключа подписи. Без домена сервер получает [быстрый туннель](https://phishdestroy.github.io/TgWitness/ru/docs/reference/high-assurance/#quick-tunnel-without-a-domain) ; **в разделе «Ваши серверы» → «Найти текущий адрес»** он запрашивается заново после перезапуска. Для фиксированного адреса под вашим собственным доменом откройте **«Дополнительно» · «Ваш собственный домен** » и добавьте токен Cloudflare (подготовленная ссылка выбирает «Зона чтения», «Редактирование DNS» и «Редактирование туннеля Cloudflare»).

Токены передаются с каждым запросом из вкладки браузера на TgWitness на том же компьютере и никуда не записываются; запись развертывания, отредактированный файл cloud-init, токен панели и, для быстрого туннеля, ключ адреса хранятся в `deployments/NAME` внутри каталога данных. Панель предоставляет доступ к этому только главному администратору по прямому loopback-соединению (`127.0.0.1`без прокси или заголовков туннеля); панель, доступ к которой осуществляется через сеть, вместо этого отображает команды . По умолчанию версия соответствует тегу релиза запущенной панели, определяемому через API GitHub. Местоположение, тип сервера и цена получаются из API Hetzner: `cpx22` если он предлагается, в противном случае — самый дешёвый тип x86 с объёмом памяти не менее 2 ГБ.

## Быстрый туннель без домена

`--quick-tunnel` заменяет `--zone`, `--cloudflare-account` и `--panel-host`; при этом не используется ни учётная запись Cloudflare, ни токен:

```
python -m tgwitness.cloud deploy --provider hetzner --name case-2026-11 --server-type cpx22 \
    --ref 0123456789abcdef0123456789abcdef01234567 --quick-tunnel --provider-token-file hetzner.token
```

На сервере cloudflared открывает [быстрый туннель](https://developers.cloudflare.com/tunnel/get-started/quick-tunnels/) к панели: случайный `https://….trycloudflare.com` адрес, который меняется при каждой перезапуске cloudflared или сервера. Небольшой сервис на сервере публикует каждый адрес в случайной теме ntfy.sh , подписав его (HMAC-SHA256) ключом, хранящимся только в каталоге развёртки (`address-key.txt`), и повторяет это каждые три часа, поскольку ntfy.sh хранит сообщения в течение 12. `deploy` и **Find текущий адрес** принимают только подписанные сообщения, поэтому поддельное сообщение не сможет направить вас и ваш токен панели на чужой адрес. Тема находится в записи и в опубликованном cloud-init: любой, у кого они есть, может прочитать текущий адрес, который по-прежнему запрашивает токен панели. Сервер не открывает входящий порт ни в том, ни в другом случае.

Верификатор не имеет ключа адреса, и любой, кто читает тему, может публиковать в ней сообщения. Поэтому коллектор также публикует сам адрес, подписанный собственным ключом Ed25519, а `verify` берет самое новое сообщение, подписанное ключом коллектора в записи развертывания; сообщения упорядочиваются по времени их получения ntfy.sh, а не по времени, указанному в них. Коллектор, созданный до введения данного изменения, ничего не подписывает, и `verify` затем берет самое новое сообщение и указывает это в проверке `statement`; поддельное сообщение может только привести к сбою этой проверки, поскольку адрес по-прежнему должен отвечать ключом коллектора.

Ограничения: быстрый туннель не привязан к учётной записи Cloudflare, поэтому `verify` отмечает проверки туннеля, коннектора и DNS как недоступные; лучший возможный результат — `incomplete`. На Phala Cloud проверка проходит: коннектор работает внутри конфигурации Docker Compose, включённой в измерения. Записи провайдера, брандмауэр, подписанное заявление, измерения хоста и сравнение установщиков проверяются как обычно. Для побайтового сравнения с эталонным установщиком нужен развёрнутый коммит с поддержкой `--quick-tunnel`; при проверке версии 0.7.0 собирается установщик для домена и обнаруживаются различия. Cloudflare не гарантирует доступность быстрых туннелей, ограничивает очередь 200 запросами и не передаёт Server-Sent Events. Поэтому обновления панели в реальном времени (после 0.7.0) могут не проходить через такой туннель, и страницу придётся перезагружать; эта часть ещё не проверялась. Для постоянной работы используйте собственный домен.

## Развертывание

Сначала просмотрите всё, что будет отправлено. `plan` не отправляет запросов ни провайдеру, ни Cloudflare:

```
python -m tgwitness.cloud plan --provider hetzner --name case-2026-11 --server-type cpx22 \
    --ref 0123456789abcdef0123456789abcdef01234567 --zone example.org \
    --cloudflare-account CLOUDFLARE_ACCOUNT_ID --panel-host case.example.org
```

Затем выполните развертывание с теми же параметрами и учетными данными:

```
python -m tgwitness.cloud deploy --provider hetzner --name case-2026-11 --server-type cpx22 \
    --ref 0123456789abcdef0123456789abcdef01234567 --zone example.org \
    --cloudflare-account CLOUDFLARE_ACCOUNT_ID --panel-host case.example.org \
    --witness-host case-witness.example.org \
    --provider-token-file hetzner.token --cloudflare-token-file cloudflare.token
```

Типы серверов для начала: `cpx22` (Hetzner), `s-1vcpu-2gb` (DigitalOcean), `g6-standard-1` (Linode), `vc2-1c-2gb` (Vultr), `t3.small` (AWS). `--location` и `--image` по умолчанию для каждого провайдера — Ubuntu 24.04 в европейском регионе.

`--repository` принимает коммит из другого репозитория Git по протоколу https без указания учетных данных в URL (по умолчанию `https://github.com/phishdestroy/TgWitness.git`). `deploy` также принимает `--out` для другого каталога развертывания (по умолчанию `deployments/NAME`; каталог, в котором уже находится развертывание, отклоняется) и `--wait`, количество минут ожидания подписанного отчета сборщика: от 1 до 240, по умолчанию 20 или 60 для `generic`.

Команда:

1. создаёт туннель Cloudflare, входящий трафик которого перенаправляет имя хоста панели на саму панель и, если указано, имя хоста свидетеля на `/api/witness/head` и `/api/assurance` только;
2. создаёт проксированные записи CNAME для этих имён хостов, отклоняя имена, которые уже существуют;
3. создаёт брандмауэр провайдера без правил входящего трафика и сервер за ним без SSH-ключа, без резервных копий, без консольного агента и с cloud-init, который маскирует SSH, блокирует root, устанавливает `cloudflared`, загружает именно этот коммит, проверяет его и запускает TgWitness в качестве защищённого сервиса systemd;
4. ожидает подписанного заявления сборщика и проверяет, указаны ли в нём этот сервер и хэш данного файла cloud-init.

`deployments/case-2026-11/` затем содержит:

| Файл | Содержание | Поделиться? |
| --- | --- | --- |
| `deployment.json` | Идентификаторы, хеши, выполненные вызовы API (метод, путь, статус) и первое подписанное утверждение | Да, с помощью верификатора |
| `cloud-init.redacted.yaml` | Точный файл cloud-init, в котором два секрета заменены на `REDACTED` | Да |
| `panel-token.txt` | Токен панели | Нет |

Корневой пароль провайдера, токен туннеля и токен панели никогда не записываются `deployment.json`. Опубликуйте отпечаток коллектора, указанный в конце, через канал, которым вы не управляете в одиночку, например, через канал свидетеля или в сообщении получателю.

Войдите в Telegram по адресу `https://case.example.org` с помощью токена панели, как описано в [руководстве по работе с аккаунтами](https://phishdestroy.github.io/TgWitness/ru/docs/reference/accounts/). Действия панели записываются в подписанный журнал; они не являются SSH-сессиями. [Свидетель](https://phishdestroy.github.io/TgWitness/ru/docs/reference/witness/) может опрашивать `https://case-witness.example.org`.

SSH отсутствует: если начальная инициализация завершится сбоем, коллектор никогда не ответит. Удалите сервер и разверните его заново или воспользуйтесь отладочным развертыванием, чтобы найти причину.

### Секреты в пользовательских данных

Cloud-init хранит два секрета: токен панели и токен туннеля Cloudflare. Ключ подписи среди них нет; он создаётся на сервере. Hetzner, DigitalOcean и Linode не возвращают пользовательские данные через свои API. Vultr возвращает их любому ключу, который может читать инстанс, а EC2 — через `DescribeInstanceAttribute`. Для AWS предоставляйте верификатору только три действия из таблицы, ни в коем случае `ec2:Describe*`. Для Vultr следует предположить, что ключ верификатора может читать оба токена. Токен туннеля позволяет кому-либо запустить второй коннектор: `verify` сообщает о любом коннекторе, не находящемся на сервере, и заявления коллектора нельзя подделать таким образом, поскольку каждый из них подписывает новый челлендж. При использовании `--quick-tunnel` вторым секретом является ключ адреса: кто бы ни прочитал его, может опубликовать ложный адрес, который панель примет.

В публичном заявлении сборщика не указываются адрес сервера и источники логинов; оба эти элемента остаются в подписанном журнале.

## Отладка развертывания и блокировка

`--debug-ssh-key KEY --debug-ssh-from 198.51.100.4` поддерживает SSH для одного ключа с одного адреса или небольшой сети, максимум /24 для IPv4 или /48 для IPv6. `KEY` уже зарегистрирован у провайдера: имя или ID SSH-ключа в проекте Hetzner, ID или отпечаток SSH-ключа в команде DigitalOcean, имя пользователя Linode, SSH-ключи которого добавлены в профиль root, ID SSH-ключа в учётной записи Vultr или имя пары ключей EC2 в регионе. Эти параметры не применяются к `generic`. Такое развертывание регистрируется как `debug` и **никогда не** отмечается как «высокого уровня безопасности». По завершении выполните `sudo tgwitness-lock` в качестве последней команды последнего сеанса SSH, а затем:

```
python -m tgwitness.cloud lock --record deployments/case-2026-11/deployment.json --provider-token-file hetzner.token
```

Брандмауэр теряет все правила входящего трафика. Затем в отчётах отображается, когда SSH был разрешён, а когда был закрыт; это окно остаётся видимым.

## Удалить развёртку

`destroy` Удаляет сервер и его брандмауэр, найденные по метке развертывания, так что развертывание, завершившееся сбоем на полпути, также удаляется, а затем — записи DNS, указывающие на его туннель, и сам туннель. Журнал сервера и ключ подписи удаляются вместе с ним: сначала экспортируйте доказательства. Запись сохраняется, помеченная `removed`, с указанием вызовов API, связанных с удалением.

```
python -m tgwitness.cloud destroy --record deployments/case-2026-11/deployment.json --confirm case-2026-11 \
    --provider-token-file hetzner.token --cloudflare-token-file cloudflare.token
```

Удаление через API реализовано для Hetzner. Для других провайдеров `destroy` процесс останавливается перед удалением и указывает метку для удаления в консоли провайдера. Ручно установленный сервер (`generic`) теряет только свои записи туннеля и DNS. Для быстрого развертывания туннеля не требуется токен Cloudflare: его туннель заканчивается на сервере, а его сообщения удаляются из ntfy.sh в течение 12 часов.

## Любой сервер (с самоподписью)

`--provider generic` предназначено для сервера, приобретённого или установленного вручную. `deploy` создаёт туннель и DNS, записывает `install.sh` (частный) и `install.redacted.sh` (для публикации), а затем ожидает. Скопируйте `install.sh` на свежеустановленный сервер Ubuntu 24.04 и запустите его там:

```
sudo bash install.sh
```

Он фиксирует состояние хоста в том виде, в каком он был (логины, аккаунты, `authorized_keys`, сокеты прослушивания, сервисы, запланированные задания, пакеты), устанавливает коммит, включает брандмауэр хоста, удаляет себя, маскирует SSH и завершает сессию. Отчёт по такому серверу в лучшем случае является **САМОУДОСТОВЕРЕННЫМ**: тот, кто запустил установщик, имел права root до этого, и у проверяющего нет доступа к записям провайдера. Это всё же лучше, чем необъяснимый сервер: инвентарь, хэш установщика и каждый последующий вход в систему подписаны.

## Проверить

Верификатору потребуются `deployment.json`опубликованный установщик, учетные данные только для чтения и, в идеале, выгрузку коммита и доказательство ZIP:

```
git clone -c core.autocrlf=false https://github.com/phishdestroy/TgWitness.git checkout
git -C checkout checkout 0123456789abcdef0123456789abcdef01234567
python -m tgwitness.cloud verify --record deployment.json \
    --provider-token-file read-only.token --cloudflare-token-file cloudflare-read.token \
    --fingerprint COLLECTOR_FINGERPRINT --cloud-init cloud-init.redacted.yaml \
    --source checkout --evidence tgwitness-evidence.zip --report report.md
```

В момент проверки верификатор запрашивает все данные у провайдера и Cloudflare; запись предоставляет только идентификаторы, по которым необходимо запросить информацию. Код завершения равен 0 для **PASS**, 1 для **FAIL** и 2 для **REVIEW**, **INCOMPLETE** или **SELF-ATTESTED**. `--fingerprint` должно поступать из независимого канала; без него ключ сравнивается только с записью оператора. `python verify.py` по-прежнему проверяет само доказательство ZIP, как описано в разделе [«Доказательства](https://phishdestroy.github.io/TgWitness/ru/docs/reference/evidence/)».

Действия провайдера классифицируются: создание и запуск в течение 30 минут после создания проходят успешно; консоль, восстановление, сброс пароля, пересборка, ISO, образы, снимки, резервные копии, Systems Manager, подключение к экземпляру EC2 и открытие портов брандмауэра завершаются сбоем; действия, связанные с питанием, и всё неожиданное помечаются для проверки. Неизвестное действие никогда не проходит незаметно.

## Отчёт о передаче доказательств

`--report report.md` создаёт отчёт в формате Markdown и `report.json` рядом с ним:

1. результат, отпечаток ключа коллектора, развёртывание, провайдер, фиксация, сервер, брандмауэр, туннель;
2. каждая проверка с указанием её статуса и источника (API провайдера, API Cloudflare, отчёт сборщика, журнал доказательств);
3. журнал провайдера с оценкой каждого действия и, если провайдер это фиксирует, с указанием исполнителя;
4. конечные точки Cloudflare, хранящие соединения туннеля, конфигурацию и журнал аудита;
5. подписанное заявление сборщика;
6. что подтверждает отчёт, а что нет;
7. команды для воспроизведения результата, а также SHA-256 каждого предоставленного файла.

Передайте отчет, `report.json`, `deployment.json`, опубликованный установщик и доказательства ZIP. Подготовьте отчет заранее: журналы провайдеров хранятся в течение ограниченного времени.

## Cloudflare в качестве внешнего свидетеля

Здесь всё необязательно. Без учётной записи Cloudflare сервер всё равно работает, и два из них работают уже сегодня:

| Что | Что здесь показано | В TgWitness |
| --- | --- | --- |
| Быстрый туннель или туннель вашего домена | Доступ к панели осуществляется только через туннель | Мастер настройки сервера, см. выше |
| ретранслятор drand `drand.cloudflare.com` | записи, сделанные после раунда drand, более поздние, чем эта: дневник велся по ходу событий | режим «доказательства», **«Дополнительные свидетели»**, «без аккаунта» ([формат](https://phishdestroy.github.io/TgWitness/ru/docs/reference/evidence/#optional-records-in-evidence-mode-drand-and-telegram-devices)) |
| Уведомления о состоянии туннеля | когда туннель не работал, по электронной почте или через веб-хук от Cloudflare | Настройте их в панели управления Cloudflare |
| DNS-шлюз (`--gateway-dns`или **Cloudflare Gateway DNS** в мастере) | каждое имя, запрос на которое обращался сервер, на который Cloudflare отвечал по протоколу TLS; брандмауэр Hetzner не пропускает DNS-запросы никуда больше; может ли политика шлюза переписать ответы | Hetzner, бесплатный тарифный план Zero Trust, без домена; `verify` проверяет брандмауэр, местоположение, ведение журналов, политики, запросы сервера и журнал аудита; режим «evidence» копирует журнал в дневник |
| Шлюз с Cloudflare: один клиент на сервере, брандмауэр исходящего трафика, пропускающий только Cloudflare | каждое соединение, установленное сервером, а не только DNS | ещё не реализовано |
| Доступ перед панелью | кто и когда вошёл в панель | не реализовано: требуется собственный домен |
| Регистрация SSH-команд | каждая команда в сеансе отладки | ещё не реализовано |

Logpush, который позволяет хранить собственную копию Cloudflare в R2, является функцией Enterprise: на бесплатном тарифном плане Cloudflare отвечает `logpush is not enabled for this account`. Журнал шлюза хранится там 24 часа, поэтому в режиме «доказательства» он копируется в подписанный журнал (**журнал Cloudflare Gateway, содержащий DNS-запросы данного сервера**, — токен только для чтения с правом «Account Analytics Read»).

Без плана «Zero Trust» у аккаунта есть одно DNS-местоположение. Когда Cloudflare отклоняет другое, сервер использует существующее, и его запросы различаются по адресу; для этого фильтра также требуется «Zero Trust PII Read», и `destroy` оставляет общее местоположение. Один запрос журнала охватывает не более трёх часов, поэтому копия и `verify` чтение данных за день в трехчасовых интервалах.

Gateway DNS отвечает за системный резолвер. Запросы DNS через HTTPS по порту 443 к другому резолверу, а также соединения с адресами, по которым поиск не проводится (например, с дата-центрами Telegram), не фиксируются в его журнале.

Cloudflare не имеет доступа к шифрованным данным Telegram, другим устройствам, привязанным к аккаунту Telegram (список устройств в режиме «evidence mode» фиксирует их со стороны Telegram) или гипервизору провайдера.

## Как читать результат проверки среды

В случае обычной виртуальной машины провайдер контролирует инфраструктуру хоста, а локальные ресурсы проверяются наряду с записями провайдера. В случае Intel TDX верификатор дополнительно проверяет характеристики оборудования, привязку коллектора, компоновку и показатели ОС. Ознакомьтесь с отдельными результатами, чтобы увидеть, какие проверки прошли успешно, а какие были недоступны.

Исторические данные о брандмауэре зависят от провайдера; Linode сохраняет версии правил. Запись [валидация](https://phishdestroy.github.io/TgWitness/ru/docs/reference/verification/) содержит список протестированных развертываний и оставшихся активных проверок, а [область верификации](https://phishdestroy.github.io/TgWitness/ru/docs/reference/evidence/#verification-scope) связывает эти проверки среды с получением архива и проверкой его целостности.
