mirror of
https://gitverse.ru/kpa39l/md2vk.git
synced 2026-09-29 09:55:04 +00:00
69 lines
4.7 KiB
Markdown
69 lines
4.7 KiB
Markdown
# md2vk — Безопасность
|
||
|
||
## Два уровня доступа
|
||
|
||
### 1. Внешний — Caddy basic_auth (на vps02)
|
||
|
||
- Весь https://md2vk.nixg.ru закрыт HTTP Basic Auth.
|
||
- Пользователь: **estorozhenko**; пароль — у пользователя, в конфиге только bcrypt-хэш.
|
||
- Хэш в Caddyfile: `estorozhenko $2a$14$uzlQxJdcRZJ5gDpGG5B26OXnudIme1IYe7xh0WtDwFtbB6XiiDYTS`
|
||
(сгенерирован 2026-09-18 `docker exec caddy caddy hash-password --plaintext '<пароль>'`).
|
||
- Без basic auth сервис наружу не отдаётся.
|
||
|
||
### 2. Внутренний — API-ключ (FastAPI)
|
||
|
||
- Все эндпоинты `/api/v1/*` (кроме `/health`) требуют API-ключ `md2vk_...`:
|
||
- в заголовке `Authorization: Bearer <api_key>` (GET) или в теле `{"api_key": ...}` (POST);
|
||
- API-ключ даёт право публиковать, но **не позволяет прочитать VK-токен** (raw токен не возвращается ни одним эндпоинтом).
|
||
- Хранится только SHA-256 хэш (`api_key_hash`), сравнение constant-time (`hmac.compare_digest`).
|
||
- Пользователь estorozhenko + API-ключ: создаётся скриптом, ключ кладётся в `secrets/estorozhenko_api_key.txt` (не в git).
|
||
|
||
## Блокировка после 5 неудачных попыток (fail2ban на vps02)
|
||
|
||
- На vps02 установлен fail2ban (v1.0.2), jail `md2vk`:
|
||
- следит за site-логом Caddy: `/opt/caddy/caddy_data/logs/md2vk.access.log` (JSON, все запросы включая 401),
|
||
- фильтр `filter.d/caddy-md2vk.conf`: `^.*"request":\{"remote_ip":"<HOST>"[^}]*"host":"md2vk\.nixg\.ru"[^}]*\}.*"status":401`,
|
||
- правило: ban IP после **5 неудачных попыток** (`maxretry=5`, `findtime=600`; на 6-й срабатывает),
|
||
- наказание: **ban до ручного снятия** (`bantime = -1`),
|
||
- действие: `iptables-allports` (цепочка `f2b-md2vk`, REJECT; на Debian 12 транслируется в nftables),
|
||
- ignoreip: `127.0.0.1/8 ::1 10.8.0.0/24` (не баним bigbox/vps02).
|
||
- **Ручная разблокировка** (на vps02, sudo):
|
||
```bash
|
||
fail2ban-client -c /etc/fail2ban unban <ip>
|
||
fail2ban-client -c /etc/fail2ban status md2vk # проверить
|
||
```
|
||
- Логи fail2ban: `journalctl -u fail2ban -e` или `/var/log/fail2ban.log`.
|
||
|
||
## Шифрование VK-токенов
|
||
|
||
- VK OAuth-токены в БД только в шифрованном виде: **Fernet (AES-128-CBC + HMAC-SHA256)**.
|
||
- Ключ — Docker secret `/run/secrets/token_encryption_key` (файл на bigbox: `secrets/token_encryption_key`, не в git).
|
||
- Расшифровка только в памяти при публикации.
|
||
|
||
## Rate limiting
|
||
|
||
- В конфиге `RATE_LIMIT_PER_MINUTE=10` (запросов/мин на VK-аккаунт).
|
||
- In-memory bucket — НЕ реализован (открытая задача).
|
||
|
||
## Аудит-лог
|
||
|
||
- Пишется JSONL в `/opt/md2vk/logs/access.{YYYY-MM-DD}.log` (вне контейнера — `logs/` на bigbox).
|
||
- Событие на каждый запрос `/api/v1/*`: `ts, ip, method, path, api_key_prefix, user_id, status, success, latency_ms, error`.
|
||
- Используется для мониторинга (доступность, успешность, активная сессия) и расследований.
|
||
- Caddy на vps02 пишет свой access-лог (используется fail2ban).
|
||
|
||
## Матрица рисков
|
||
|
||
| Сценарий | Последствия | Защита |
|
||
|---|---|---|
|
||
| Утечка .db | Токены зашифрованы | Fernet + Docker secret |
|
||
| Утечка API-ключа | Можно постить, но не украсть токен | API-ключ ≠ VK-токен |
|
||
| Брутфорс basic auth | Полный доступ к веб-интерфейсу API | fail2ban ban после 5 попыток, ручной unban |
|
||
| Перехват HTTP | — | HTTPS (Caddy/Let's Encrypt) |
|
||
| Компрометация контейнера | Полный доступ к токенам | read-only rootfs, audit log |
|
||
| Отзыв токена VK | Пост не выйдет | VK вернёт ошибку → error_message |
|
||
|
||
## Правило пользователя
|
||
|
||
> Никогда не удалять файлы пользователя без явного подтверждения. Пароли и токены не сохранять в коде —
|
||
> только через переменные окружения, Docker secrets или файлы, исключённые из git (.gitignore). |