Docs/docs/10-security.md
2026-04-01 15:30:40 +05:00

344 lines
16 KiB
Markdown
Raw Permalink 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.

# 10. Безопасность
## Обзор
В этом разделе собраны текущие проблемы безопасности инфраструктуры и план их устранения. Документ основан на результатах аудита, проведённого в марте 2026 года.
> **Последнее обновление**: 1 апреля 2026
> **Применено на хостах**: `torrent` (192.168.1.211), `Olimp` (Proxmox VE)
> **В процессе**: применение на остальных хостах
---
## Текущее состояние
| Область | Статус | Комментарий |
|---------|--------|-------------|
| SSH (парольная аутентификация) | ✅ | Отключена на всех хостах |
| SSH (вход root) | ✅ | Запрещён (`PermitRootLogin no`) на `torrent`, применяется на остальных |
| Пользователь `zailon` | ✅ | Создан с правами `sudo`, SSH-ключи настроены |
| SSH-ключи | ✅ | Управляются централизованно через Ansible |
| Samba (протокол) | ✅ | Обновлён до `SMB2` на `media` |
| Samba (шифрование) | 🟡 | `smb encrypt = desired` (пока не `required` из-за совместимости) |
| UFW / фаервол | 🔴 | Отключён на всех LXC и ВМ |
| Хранение паролей в Ansible | ✅ | Все секреты перенесены в `vault.yml` и зашифрованы |
| Заголовки безопасности в NPM | 🔴 | Отсутствуют для большинства прокси |
| Docker-образы | 🟡 | Используется тег `latest` на части сервисов |
| Обновления систем | 🟡 | Требуют периодического применения |
| Мониторинг | ✅ | Node Exporter, Promtail, VictoriaMetrics настроены |
| Резервное копирование | ✅ | **Proxmox Backup Server настроен и протестирован** |
---
## ✅ Решённые проблемы
### 1. Вход root по SSH — ИСПРАВЛЕНО
- **Описание**: На всех хостах разрешён вход под пользователем `root` через SSH. При компрометации ключа злоумышленник получает полный контроль над системой.
- **Что сделано**:
- Создан пользователь `zailon` с правами `sudo`
- Настроены SSH-ключи из `ssh_public_keys`
- В `/etc/ssh/sshd_config` установлено `PermitRootLogin no`
- Применено через Ansible на хосте `torrent`
- **Проверка**:
```bash
ssh zailon@192.168.1.211
ssh root@192.168.1.211
grep PermitRootLogin /etc/ssh/sshd_config
```
- **Статус**: ✅ Применено на всех хостах
### 2. Пароли в открытом виде в Ansible — ИСПРАВЛЕНО
- **Описание**: В файле `group_vars/all.yml` присутствовали пароли в открытом виде.
- **Что сделано**:
- Все секреты перенесены в `group_vars/vault.yml`
- Файл зашифрован через `ansible-vault encrypt vault.yml`
- В `all.yml` остались только публичные переменные
- **Список зашифрованных переменных**:
```yaml
vault_zailon_password: "..."
vault_grafana_admin_password: "..."
vault_gitlab_root_password: "..."
vault_bitwarden_admin_token: "..."
vault_bitwarden_smtp_password: "..."
vault_mealie_db_password: "..."
vault_flibusta_db_password: "..."
vault_immich_db_password: "..."
vault_mumble_server_password: "..."
vault_mumble_superuser_password: "..."
vault_matrix_postgres_password: "..."
vault_matrix_synapse_secret: "..."
vault_matrix_macaroon_secret: "..."
vault_matrix_form_secret: "..."
vault_matrix_admin_password: "..."
vault_snikket_admin_password: "..."
vault_snikket_invite_token: "..."
vault_smb_olimp_password: "..."
vault_samba_password_qb: "..."
vault_pve_exporter_token: "..."
```
- **Запуск playbook с vault**:
```bash
ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass
echo "your_vault_password" > ~/.vault_pass
chmod 600 ~/.vault_pass
ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.vault_pass
```
- **Статус**: ✅ Завершено
### 3. Samba использует SMB1 — ИСПРАВЛЕНО
- **Описание**: На хосте `media` в конфигурации Samba был установлен `server min protocol = NT1` (SMB1), что уязвимо к атакам типа EternalBlue.
- **Что сделано**:
- В `/etc/samba/smb.conf` на хосте `media` изменено:
```ini
[global]
server min protocol = smb2
smb encrypt = desired
```
- Проверена работа клиентов (Windows, Android, Docker)
- **Статус**: ✅ Завершено на `media` `games`
### 4. Резервное копирование не было настроено — ИСПРАВЛЕНО
- **Описание**: Отсутствовала автоматическая система резервного копирования конфигураций, баз данных и пользовательских данных.
- **Что сделано** (апрель 2026):
- **Установлен Proxmox Backup Server** (PBS) в LXC контейнере (CT 220)
- **Создано хранилище** на ZFS dataset `rpool/pbs-backups` (187 GB, SSD mirror)
- **Настроено хранилище** `ssd-backups` с дедупликацией и компрессией ZSTD
- **PBS подключён** к Proxmox VE как `pbs-ssd`
- **Настроены бэкапы** для критичных систем:
- LXC контейнеры: 201-211 (gateway, data, media, photo, talk, games, manage, git, ansible, torrent)
- VM: 205 (Nextcloud), 213 (VPN)
- **Расписание**: ежедневно в 02:30 и 22:30
- **Retention политика**: Keep Last 7, Keep Daily 7, Keep Weekly 2
- **Режим**: Snapshot (без остановки сервисов)
- **Исключены** большие диски (16TB RAID6 массив)
- **Восстановление протестировано**: CT 201 → CT 216 (успешно)
- **Архитектура**:
```
Proxmox VE Host (Olimp)
├─ ZFS Pool: rpool (2x240GB SSD mirror)
│ └─ Dataset: rpool/pbs-backups (187 GB)
│ └─ Mounted to: /rpool/pbs-backups
└─ LXC Container (CT 220) - Proxmox Backup Server
└─ Mount: /mnt/backups → /rpool/pbs-backups
└─ Datastore: ssd-backups
```
- **Команды управления**:
```bash
zfs list rpool/pbs-backups
zpool list rpool
pct exec 220 -- proxmox-backup-client datastore stats ssd-backups
```
- **Восстановление**:
```bash
pct restore <new-vmid> pbs-ssd:backup/ct/<ctid>/<backup-time>
qm restore <new-vmid> pbs-ssd:backup/vm/<vmid>/<backup-time>
```
- **Статус**: ✅ Работает, требует мониторинга места
- **Примечание**: PBS развёрнут на том же хосте что и Proxmox VE (временное решение до появления отдельного сервера). Рекомендуется настроить репликацию на внешний носитель или облако.
---
## 🔴 Критические проблемы (требуют внимания)
### 1. Отсутствие фаервола на всех LXC
- **Описание**: UFW отключён на всех LXC-контейнерах. Сервисы доступны из всей локальной сети без ограничений.
- **Решение**: Включить UFW на каждом хосте с минимально необходимыми правилами:
```yaml
- name: Enable UFW with default deny
ufw:
state: enabled
policy: deny
direction: incoming
become: yes
- name: Allow SSH from trusted subnets
ufw:
rule: allow
port: 22
proto: tcp
from: "{{ item }}"
loop:
- "192.168.1.0/24"
- "192.168.45.0/24"
become: yes
- name: Allow Samba from trusted subnets
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
from: "192.168.1.0/24"
loop:
- 139
- 445
become: yes
- name: Allow HTTP/HTTPS for NPM
ufw:
rule: allow
port: "{{ item }}"
proto: tcp
loop:
- 80
- 443
become: yes
```
- **План**: Создать роль `ufw_setup` и применить ко всем хостам
- **Срок**: В течение недели
### 2. Отсутствие заголовков безопасности в NPM
- **Описание**: Для публичных прокси не настроены заголовки безопасности: HSTS, X-Content-Type-Options, X-Frame-Options.
- **Решение**: Через веб-интерфейс NPM → Proxy Hosts → Edit → Advanced → Custom locations добавить:
```nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;
```
- **Применить ко всем публичным доменам**: `*.zailon.ru`
- **Срок**: В течение недели
---
## 🟠 Проблемы высокого приоритета
### 1. Использование Docker-образов с тегом `latest`
- **Описание**: Образы обновляются неконтролируемо, что может привести к несовместимости.
- **Решение**: Зафиксировать версии в `docker-compose.yml`:
```yaml
services:
npm:
image: jc21/nginx-proxy-manager:2.12.3
```
- **План**: Пройтись по всем `docker-compose.yml` и зафиксировать версии
- **Срок**: В течение месяца
### 2. Необновлённые системы
- **Описание**: На хостах накапливаются обновления пакетов.
- **Решение**:
- Регулярно запускать `apt update && apt upgrade` через Ansible
- Настроить `unattended-upgrades` для автоматических обновлений безопасности
```yaml
- name: Install unattended-upgrades
apt:
name: unattended-upgrades
state: present
become: yes
- name: Configure unattended-upgrades
copy:
content: |
Unattended-Upgrade::Allowed-Origins {
"${distro_id}:${distro_codename}";
"${distro_id}:${distro_codename}-security";
};
Unattended-Upgrade::Automatic-Reboot "false";
dest: /etc/apt/apt.conf.d/50unattended-upgrades
become: yes
```
- **Статус**: 🟡 В процессе
---
## 🟡 Проблемы среднего приоритета
### 1. Шифрование Samba: `desired` вместо `required`
- **Описание**: `smb encrypt = desired` допускает незашифрованные соединения.
- **Решение**: После тестирования всех клиентов в VPN изменить на `required`:
```ini
[global]
smb encrypt = required
```
- **Статус**: 🟡 Отложено до полной проверки совместимости
### 2. Отсутствие алертов на логи в Grafana
- **Описание**: Нет правил для оповещения при ошибках в логах.
- **Решение**: Настроить правила в Grafana → Alerting на основе Loki:
```logql
{job="promtail", filename="/var/log/auth.log"} |= "Failed password" | rate() > 5
{job="promtail", container="nginx-proxy-manager"} |= "error"
```
- **Статус**: 🟡 В планах
### 3. cAdvisor не включён на всех хостах
- **Описание**: Метрики Docker-контейнеров собираются не везде.
- **Решение**: Раскомментировать роль `cadvisor` в `olimp-deploy.yml` при необходимости.
- **Статус**: 🟡 По мере необходимости
---
## 🟢 Рекомендации по улучшению
| Задача | Описание | Приоритет |
|--------|----------|-----------|
| Автоматические обновления | Настроить `unattended-upgrades` на всех хостах | 🟢 |
| Сегментация сети | Выделить VLAN для IoT и гостевой сети | 🟢 |
| Мониторинг роутера | Сбор SNMP-метрик с TP-Link | 🟢 |
| Двухфакторная аутентификация | Включить 2FA в Grafana, GitLab, Bitwarden | 🟢 |
| Регулярный аудит | Запускать Lynis/OpenVAS раз в 3 месяца | 🟢 |
| Оффсайт-бэкапы | Настроить репликацию PBS в облако (Backblaze B2/Wasabi) | 🟢 |
---
## 📋 План действий
| Задача | Приоритет | Срок | Статус |
|--------|-----------|------|--------|
| Применить настройку SSH (root+zailon) на всех хостах | 🔴 | 1 день | 🔄 В процессе |
| Включить UFW на всех хостах | 🔴 | 1 неделя | ⏳ Ожидает |
| Добавить заголовки безопасности в NPM | 🔴 | 1 неделя | ⏳ Ожидает |
| Зафиксировать версии Docker-образов | 🟠 | 1 месяц | ⏳ Ожидает |
| Настроить unattended-upgrades | 🟢 | 1 месяц | ⏳ Ожидает |
| Настроить алерты на логи | 🟡 | По необходимости | ⏳ Ожидает |
| Настроить репликацию PBS (оффсайт) | 🟢 | 2 месяца | ⏳ Ожидает |
---
## 🔐 Чек-лист применения изменений
Перед запуском playbook на всех хостах:
```bash
chmod 600 /root/.ssh/id_rsa
ansible-vault view vault.yml --ask-vault-pass | grep zailon
ansible-playbook -i inventories/hosts olimp-deploy.yml -l torrent --check --diff --ask-vault-pass
ansible-playbook -i inventories/hosts olimp-deploy.yml -l torrent --ask-vault-pass
ssh zailon@192.168.1.211
ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass
```
> ⚠️ **Важно**: Не закрывайте текущую SSH-сессию `root`, пока не проверите вход под `zailon` в отдельном окне!
---
## 📊 Мониторинг безопасности
```bash
zfs list rpool/pbs-backups
zpool list rpool
pct exec 220 -- proxmox-backup-client datastore stats ssd-backups
pct exec 220 -- df -h /mnt/backups
```
---
**Связанные разделы**:
- [05. Samba файловые шары](05-samba.md)
- [07. Проксирование и SSL (NPM)](07-proxy-ssl.md)
- [08. Мониторинг и логирование](08-monitoring.md)
- [09. Управление конфигурацией (Ansible)](09-ansible.md)
- [11. Резервное копирование](11-backup.md)