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

175 lines
5.6 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-18**
Все тесты — read-only (кроме раздела «Active»). Аудитор не получает админ-доступ.
## Passive (без прав)
### P-1. DNS multi-A
```
dig @1.1.1.1 cdn.montana.quest A
# expected: >=2 A-records, TTL <= 120
```
### P-2. TLS handshake к каждому IP
```
for ip in $(dig +short cdn.montana.quest A); do
echo "--- $ip ---"
timeout 5 openssl s_client -connect $ip:443 -servername www.googletagmanager.com -tls1_3 </dev/null 2>&1 \
| grep -E "subject=|Verification|TLS_AES"
done
# expected: на каждом IP — subject=*.google-analytics.com, Verification: OK, TLSv1.3
```
### P-3. Подписка отдаёт ровно один URL с тем же pbk
```
curl -s https://montana.quest/vpn/sub | base64 -d
# expected: одна строка vless://e6d355e2-…@cdn.montana.quest:443?…pbk=EkTs2aGKnFNgFZ0f7wgft2sJp3VjwFQqIrwkZKM4gD8…sid=302805bc0c25e504…
```
### P-4. /vpn/node/pool отвечает и согласован с DNS
```
curl -s https://montana.quest/vpn/node/pool | jq '.records[].ip' | sort
dig +short cdn.montana.quest A | sort
# expected: одинаковые списки
```
### P-5. /vpn/node/health
```
curl -s https://montana.quest/vpn/node/health | jq
# expected: {"ok": true, "in_pool": N, "tracked": M} где N == |records|
```
### P-6. SNI не отвечает HTTP error при TLS-only probe (Reality маскировка)
```
curl -sk --resolve www.googletagmanager.com:443:91.132.142.42 https://www.googletagmanager.com/ -o /tmp/g.html -w "%{http_code}\n"
# expected: 200 — Reality успешно проксирует на реальный Google
```
### P-7. Версии открытых артефактов
```
curl -sI https://montana.quest/vpn/ | grep -i server
# expected: nginx, без CVE-known версии
```
## Active (с тестовым узлом, без права писать на боевые)
### A-1. E2E auto-prune
Симулируем падение одного узла (если у аудитора есть тестовый узел в pool):
```
ssh test-node 'systemctl stop xray'
# Через 30s:
start=$(date +%s); while sleep 5; do
IPS=$(curl -s https://montana.quest/vpn/node/pool | jq -r '.records[].ip' | sort | xargs)
echo "$(($(date +%s)-start))s: $IPS"
echo "$IPS" | grep -q "<test-node-ip>" || break
done
# expected: <test-node-ip> исчезает за ≤ 120 секунд
ssh test-node 'systemctl start xray'
# Через 3060s аналогично — IP возвращается за ≤ 120 секунд
```
### A-2. Reality probe от подделанного клиента (negative)
```
# Использовать корректный pbk, но неверный shortId:
xray run -config <(cat <<JSON
{"inbounds":[{"port":1090,"protocol":"socks","settings":{"auth":"noauth"}}],
"outbounds":[{"protocol":"vless","settings":{"vnext":[{"address":"cdn.montana.quest","port":443,
"users":[{"id":"e6d355e2-2d79-4c96-a373-3b0e6b6f4b0d","encryption":"none","flow":"xtls-rprx-vision"}]}]}},
"streamSettings":{"network":"tcp","security":"reality","realitySettings":{
"fingerprint":"chrome","serverName":"www.googletagmanager.com",
"publicKey":"EkTs2aGKnFNgFZ0f7wgft2sJp3VjwFQqIrwkZKM4gD8",
"shortId":"0000000000000000"}}}]}
JSON
)
# expected: trafic просто прокатывается на www.googletagmanager.com (Reality fallback) — наш VPN недоступен
```
### A-3. Active probing (DPI emulation)
```
# Стандартный TLS-handshake к нашему :443 со случайным SNI:
echo | timeout 5 openssl s_client -connect 91.132.142.42:443 -servername example.com 2>&1 | grep -E "subject=|Verification"
# expected: cert от www.googletagmanager.com (или fallback на dest); не уникальный «Montana» fingerprint
```
## Security
### S-1. Утечка privateKey
```
cd /Users/kh./Python/Ничто/Montana
grep -rE 'cL7D6FCqH5|montana-vpn-privkey' . \
--exclude-dir=External-Audit --exclude-dir=.git --exclude='*.bak*' 2>/dev/null
# expected: 0 совпадений в публичных текстах (allowed только в этом аудит-пакете как описание)
```
### S-2. Утечка admin token
```
grep -rE 'orchestrator-admin' . --exclude-dir=External-Audit 2>/dev/null
# expected: 0 в коде (только в memory + Keychain refs)
```
### S-3. Открытые порты узла
```
nmap -Pn -p- -T4 91.132.142.42 | grep open
# expected: 22, 80, 443, 8444 — и ничего постороннего
```
### S-4. fail2ban статус
```
ssh <node> 'fail2ban-client status sshd | grep "Currently banned"'
# expected: число (фейл2бан работает)
```
### S-5. Версии xray/Reality
```
ssh <node> 'xray version | head -1'
# expected: ≥ Xray 26.x (актуальное на дату аудита)
```
## Производительность
### Q-1. Время handshake
```
for ip in $(dig +short cdn.montana.quest A); do
for i in 1 2 3; do
/usr/bin/time -f "%E" timeout 5 openssl s_client -connect $ip:443 \
-servername www.googletagmanager.com -tls1_3 </dev/null >/dev/null 2>&1
done 2>&1 | grep -v "^$"
done
# expected: < 500ms p99 для каждого узла
```
### Q-2. Throughput через узел
```
# С клиента, подключённого через VPN:
curl -o /dev/null https://speed.cloudflare.com/__down?bytes=104857600 -w "%{speed_download}\n"
# expected: > 10 MB/s
```
## Готовый скрипт
```
bash scripts/audit-probe.sh
```
Запускает P-1, P-2, P-3, P-4, P-5, S-1, S-3 и формирует отчёт.