docs(security): периметр 80/443→HAProxy, 25→KSMG; UFW на .117

Переписаны docs/security под текущий этап: SSH/stats из SSH_ALLOWED,
80/443 для всех. Скрипт UFW дополнен правилом 8404.
This commit is contained in:
Andrey Lutsenko
2026-06-13 22:34:57 +10:00
parent e3201ae41b
commit 8e2a4ac1b9
9 changed files with 259 additions and 406 deletions
+42 -45
View File
@@ -1,67 +1,64 @@
# Архитектура защиты
## Поток трафика
## Периметр (MikroTik)
| С интернета | DNAT на | Порт |
|-------------|---------|------|
| HTTP/HTTPS | **HAProxy** `192.168.160.117` | **80**, **443** |
| SMTP | **KSMG** `192.168.160.57` | **25** |
На HAProxy с интернета **только 80 и 443**. Порт **25** на HAProxy **не проброшен**.
## Потоки
![Поток трафика](architecture-flow.svg)
Схема в SVG — без Mermaid, чтобы Gitea/Firefox не ломали рендер из‑за `<br>` в XML.
Та же схема текстом:
```text
Интернет → MikroTik (DNAT 80/443) → HAProxy .117 ACL (SNI/Host) бэкенды .160.0/24
Интернет ──80/443──► MikroTik ──► HAProxy .117 ── ACL (SNI/Host) ──► бэкенды .160.0/24
Интернет ──25──────► MikroTik ──► KSMG .57
```
**Периметр MikroTik:** с интернета на HAProxy проброшены только **80** и **443**. Порт **25** (и прочие) на HAProxy снаружи **недоступны** — DNAT не настроен.
### Через HAProxy (80/443)
## Два контура
- **443**: reject неизвестного SNI; allowlist — git, sac-web, rds, erp, syno; без allowlist — Exchange, sac-api.
- **80**: только `Host: zabbix.kalinamall.ru` + `zabbix-allowed`.
### 1. Публичный вход (через HAProxy)
Прокси и health-check идут **с IP `.117`**. Бэкенды должны разрешать этот источник (UFW на бэкендах — **позже**, см. [backend-hosts.md](backend-hosts.md)).
Клиент → публичный IP → **MikroTik (DNAT 80/443)****HAProxy** → (проверки) → один бэкенд.
### Мимо HAProxy
На HAProxy с интернета доступны только:
- **Почта**: inbound SMTP → **напрямую KSMG** (не через `fe_smtp` на `.117`).
- **LAN/VPN**: прямой доступ к бэкендам, RDP, SSH — если нет host firewall.
- **443/TCP**: отклонение неизвестного SNI; allowlist для git, sac-web, rds, erp, syno.
- **80/HTTP**: только `Host: zabbix.kalinamall.ru` + `zabbix-allowed`.
## Текущий этап: UFW на HAProxy
**25/SMTP** в `haproxy.cfg` слушает на хосте, но **с интернета не проброшен** (MikroTik DNAT только 80/443). Inbound-почта на KSMG идёт **не через** HAProxy:25 с периметра.
Сейчас внедряем только [haproxy-host.md](haproxy-host.md) — UFW на `.117`:
### 2. Внутренняя сеть (LAN / VPN)
| Порт | Кому |
|------|------|
| **22** | `SSH_ALLOWED`: `5.100.81.121`, `192.168.128.0/17` |
| **8404** (stats) | тот же список (если frontend включён) |
| **80**, **443** | все |
| остальное | deny (в т.ч. **25** на HAProxy) |
Трафик **мимо HAProxy** возможен, если:
## Матрица фильтрации
- есть VPN в `192.168.160.0/24`;
- бэкенд слушает на LAN без host firewall;
- RDP/RDP Gateway по внутренним адресам.
Защита: **UFW на бэкендах** + политика «сервисный порт только с `.117`», админ-доступ — отдельные правила.
## IP HAProxy (источник для бэкендов)
| Имя | IP |
|-----|-----|
| haproxy.kalinamall.ru | **192.168.160.117** |
Health-check HAProxy и прокси идут **с этого IP**. Правила на бэкендах должны разрешать его явно.
## Матрица: кто фильтрует что
| Угроза | MikroTik | UFW HAProxy | HAProxy cfg | UFW бэкенд | Приложение |
|--------|----------|-------------|-------------|------------|------------|
| Сканирование портов | ✓ | ✓ | — | ✓ | — |
| Угроза | MikroTik | UFW HAProxy | HAProxy cfg | UFW бэкенд* | Приложение |
|--------|----------|-------------|-------------|-------------|------------|
| Лишние порты с интернета | ✓ | ✓ | — | — | — |
| Неверный SNI / Host | — | — | ✓ | — | — |
| Доступ не из allowlist | — | — | ✓ | — | ✓ |
| Прямой удар в бэкенд | | — | — | ✓ | — |
| Brute SSH на HAProxy | | ✓ | — | — | fail2ban |
| DDoS L4 | | частично | conn limits* | | |
| Не из allowlist | — | — | ✓ | — | ✓ |
| Прямой удар в бэкенд | частично | — | — | ✓ | — |
| Brute SSH | | ✓ | — | — | fail2ban |
| SMTP-спам на KSMG | | — | — | ✓‡ | KSMG |
\* Опционально: `maxconn`, rate-limit на frontend (Enterprise / custom); на 2.8 — sysctl, MikroTik, внешний scrubbing.
\* Бэкенды — следующий этап.
† Рекомендуется, не в scope текущего UFW.
‡ KSMG — периметровый хост для **25**, отдельный план.
## Принципы
1. **Default deny** на вход (UFW `incoming deny`, бэкенды — только HAProxy + admin).
2. **Минимум открытых портов** с интернета на HAProxy: **80** и **443** (DNAT на MikroTik).
3. **Не дублировать** смысл правил без нужды: allowlist в HAProxy для HTTP/SNI; UFW — транспорт и админ.
4. **Сначала dry-run**, потом `--apply`; для SSH — **console/IPMI** или сессия, которую UFW не оборвёт.
5. **Логи**: HAProxy + UFW + fail2ban; алерты на аномалии (Zabbix уже в инфраструктуре).
1. **Default deny** на вход (UFW `incoming deny`).
2. Периметр на MikroTik — источник истины для DNAT; UFW на HAProxy — defense in depth + SSH.
3. Allowlist в `haproxy.cfg` для 443/80; UFW не дублирует SNI/Host.
4. UFW: сначала dry-run, потом `--apply`; держать вторую SSH-сессию.