montana/Node/External-Audit/TRANSPARENCY.md
2026-05-21 03:44:38 +03:00

75 lines
5.4 KiB
Markdown
Raw 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.

# Прозрачность счётчика пользователей
Версия: **2026-05-19**
## Что мы доказываем
Число «Уникальных пользователей» на `montana.quest/vpn/`**не выдумано**.
## Что мы НЕ публикуем
IP-адреса пользователей. Это PII (персональные данные) — публиковать их незаконно (GDPR / 152-ФЗ) и аморально.
## Как доказательство работает
1. На узле Helsinki в `/var/lib/montana-vpn-stats/unique-ips.txt` накапливается список IP, когда-либо подключавшихся к VPN (из xray access.log). Файл root:root 600, не доступен публично.
2. Каждую минуту скрипт `/opt/montana-vpn-stats/transparency-sign.py`:
- читает список IP
- сортирует
- вычисляет `sha256(joined-with-LF)`**merkle_root**
- подписывает snapshot `{ts_utc, unique_users, merkle_root, algorithm}` ключом ed25519
- публикует:
- `https://montana.quest/vpn/transparency.json` — последний snapshot
- `https://montana.quest/vpn/transparency-log.txt` — append-only лог всех snapshot'ов
3. Публичный ключ подписи: `d9a8bf07871d35c8e85f7de4a9b62896c330ba0987732468515c7bda8bb4adde` (ed25519). Лежит здесь и в репозитории. Приватный ключ — только на узле, 600 root.
## Что может проверить аудитор без доступа к серверу
| Свойство | Как проверить |
|---|---|
| **Подпись валидна** | `verify-transparency.sh` проверяет ed25519 над snapshot |
| **Публичный ключ не сменили** | сравнить с публикуемым в этом репозитории |
| **Число не подкручивается вниз** | `transparency-log.txt` — append-only, аудитор скачивает последние N снимков, проверяет монотонность |
| **Snapshot timestamp реальный** | сравнить `ts_utc` с моментом скачивания (расхождение ≤ 60s) |
| **Один и тот же merkle root = одни и те же IPы** | повторный merkle root между snapshots = новых IP нет |
## Что аудитор НЕ может узнать
- Конкретные IP пользователей (они зашифрованы в merkle root).
- Страну/время подключения отдельного пользователя.
Чтобы доказать что конкретный IP в множестве — нужен сам IP (известен только владельцу) + полный список (raw `unique-ips.txt` доступен только под NDA на аудит, не публично).
## Запуск проверки
```bash
bash scripts/verify-transparency.sh
```
Скрипт:
1. Скачивает `https://montana.quest/vpn/transparency.json`.
2. Проверяет ed25519-подпись с известного `EXPECTED_PUBKEY`.
3. Скачивает `https://montana.quest/vpn/transparency-log.txt`.
4. Проверяет монотонность роста за последние 50 снимков.
5. Выводит зелёные галки и текущее число.
## Ограничения текущей реализации
1. **Anti-tamper только в пределах подписи.** Атакующий с доступом к privateKey может выдавать любое число. Защита: ключ 600 root + сервер изолирован.
2. **Нет on-chain anchor.** При желании можно anchored daily snapshot в Bitcoin через OpenTimestamps — это даст proof что snapshot существовал не позднее timestamp'а в чейне. Roadmap.
3. **IP = пользователь — приближение.** Один человек с двух IP считается как 2; несколько человек за одним NAT-IP считаются как 1. Это **верхняя оценка уникальных** для NAT и **нижняя** для multi-device. Точнее без trackable user-ID (что = приватность ↓).
4. **Уязвимость к ротации файла.** Если `unique-ips.txt` корраптится — счётчик откатывается. Защита: append-only лог сохраняет историю.
## Полный список секретов
- `/etc/montana/transparency-privkey` (Moscow, 600 root) — ed25519 приватный ключ подписи.
- Только этот хост может подписывать. При компрометации — генерация нового keypair, обновление публичного ключа в репо + публикация incident notice.
## Roadmap
- **P1:** Bitcoin OpenTimestamps anchoring каждый день в 00:00 UTC.
- **P2:** Migration на cryptographic accumulator (RSA / Merkle tree) для proof-of-membership без раскрытия списка.
- **P3:** Multi-party signing (2 of 3 узлов подписывают) — устраняет single point of trust на Moscow privateKey.