Update file 10-security.md

This commit is contained in:
Administrator 2026-04-01 15:16:42 +05:00
parent da99d31b2f
commit 3e42a507cf

View File

@ -4,8 +4,8 @@
В этом разделе собраны текущие проблемы безопасности инфраструктуры и план их устранения. Документ основан на результатах аудита, проведённого в марте 2026 года. В этом разделе собраны текущие проблемы безопасности инфраструктуры и план их устранения. Документ основан на результатах аудита, проведённого в марте 2026 года.
> **Последнее обновление**: 24 марта 2026 > **Последнее обновление**: 1 апреля 2026
> **Применено на хостах**: `torrent` (192.168.1.211) > **Применено на хостах**: `torrent` (192.168.1.211), `Olimp` (Proxmox VE)
> **В процессе**: применение на остальных хостах > **В процессе**: применение на остальных хостах
--- ---
@ -26,7 +26,7 @@
| Docker-образы | 🟡 | Используется тег `latest` на части сервисов | | Docker-образы | 🟡 | Используется тег `latest` на части сервисов |
| Обновления систем | 🟡 | Требуют периодического применения | | Обновления систем | 🟡 | Требуют периодического применения |
| Мониторинг | ✅ | Node Exporter, Promtail, VictoriaMetrics настроены | | Мониторинг | ✅ | Node Exporter, Promtail, VictoriaMetrics настроены |
| Резервное копирование | 🔴 | Не настроено (будет описано в разделе 11) | | Резервное копирование | ✅ | **Proxmox Backup Server настроен и протестирован** |
--- ---
@ -42,15 +42,9 @@
- Применено через Ansible на хосте `torrent` - Применено через Ansible на хосте `torrent`
- **Проверка**: - **Проверка**:
```bash ```bash
# Проверка подключения под zailon ssh zailon@192.168.1.211
ssh zailon@192.168.1.211 # ✅ Работает ssh root@192.168.1.211
# Проверка запрета root
ssh root@192.168.1.211 # ❌ Permission denied (publickey)
# Проверка конфигурации SSH
grep PermitRootLogin /etc/ssh/sshd_config grep PermitRootLogin /etc/ssh/sshd_config
# Ожидаемый вывод: PermitRootLogin no
``` ```
- **Статус**: ✅ Применено на `torrent`, готовится применение на остальных хостах - **Статус**: ✅ Применено на `torrent`, готовится применение на остальных хостах
@ -63,34 +57,30 @@ grep PermitRootLogin /etc/ssh/sshd_config
- В `all.yml` остались только публичные переменные - В `all.yml` остались только публичные переменные
- **Список зашифрованных переменных**: - **Список зашифрованных переменных**:
```yaml ```yaml
# vault.yml (зашифрован) vault_zailon_password: "..."
vault_zailon_password: "..." # Пароль администратора vault_grafana_admin_password: "..."
vault_grafana_admin_password: "..." # Grafana vault_gitlab_root_password: "..."
vault_gitlab_root_password: "..." # GitLab vault_bitwarden_admin_token: "..."
vault_bitwarden_admin_token: "..." # Bitwarden vault_bitwarden_smtp_password: "..."
vault_bitwarden_smtp_password: "..." # Bitwarden SMTP vault_mealie_db_password: "..."
vault_mealie_db_password: "..." # Mealie DB vault_flibusta_db_password: "..."
vault_flibusta_db_password: "..." # Flibusta DB vault_immich_db_password: "..."
vault_immich_db_password: "..." # Immich DB vault_mumble_server_password: "..."
vault_mumble_server_password: "..." # Mumble vault_mumble_superuser_password: "..."
vault_mumble_superuser_password: "..." # Mumble superuser vault_matrix_postgres_password: "..."
vault_matrix_postgres_password: "..." # Matrix/Synapse vault_matrix_synapse_secret: "..."
vault_matrix_synapse_secret: "..." # Matrix secrets
vault_matrix_macaroon_secret: "..." vault_matrix_macaroon_secret: "..."
vault_matrix_form_secret: "..." vault_matrix_form_secret: "..."
vault_matrix_admin_password: "..." vault_matrix_admin_password: "..."
vault_snikket_admin_password: "..." # Snikket XMPP vault_snikket_admin_password: "..."
vault_snikket_invite_token: "..." vault_snikket_invite_token: "..."
vault_smb_olimp_password: "..." # SMB shares vault_smb_olimp_password: "..."
vault_samba_password_qb: "..." vault_samba_password_qb: "..."
vault_pve_exporter_token: "..." # Proxmox exporter vault_pve_exporter_token: "..."
``` ```
- **Запуск playbook с vault**: - **Запуск playbook с vault**:
```bash ```bash
# Интерактивный ввод пароля
ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass
# Или через файл с паролем
echo "your_vault_password" > ~/.vault_pass echo "your_vault_password" > ~/.vault_pass
chmod 600 ~/.vault_pass chmod 600 ~/.vault_pass
ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.vault_pass ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.vault_pass
@ -104,12 +94,53 @@ ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.
- В `/etc/samba/smb.conf` на хосте `media` изменено: - В `/etc/samba/smb.conf` на хосте `media` изменено:
```ini ```ini
[global] [global]
server min protocol = smb2 # было: NT1 server min protocol = smb2
smb encrypt = desired # оставлено для совместимости с клиентами smb encrypt = desired
``` ```
- Проверена работа клиентов (Windows, Android, Docker) - Проверена работа клиентов (Windows, Android, Docker)
- **Статус**: ✅ Завершено на `media` - **Статус**: ✅ Завершено на `media`
### 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 (временное решение до появления отдельного сервера). Рекомендуется настроить репликацию на внешний носитель или облако.
--- ---
## 🔴 Критические проблемы (требуют внимания) ## 🔴 Критические проблемы (требуют внимания)
@ -119,7 +150,6 @@ ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.
- **Описание**: UFW отключён на всех LXC-контейнерах. Сервисы доступны из всей локальной сети без ограничений. - **Описание**: UFW отключён на всех LXC-контейнерах. Сервисы доступны из всей локальной сети без ограничений.
- **Решение**: Включить UFW на каждом хосте с минимально необходимыми правилами: - **Решение**: Включить UFW на каждом хосте с минимально необходимыми правилами:
```yaml ```yaml
# Пример роли ufw_setup/tasks/main.yml
- name: Enable UFW with default deny - name: Enable UFW with default deny
ufw: ufw:
state: enabled state: enabled
@ -134,8 +164,8 @@ ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.
proto: tcp proto: tcp
from: "{{ item }}" from: "{{ item }}"
loop: loop:
- "192.168.1.0/24" # LAN - "192.168.1.0/24"
- "192.168.45.0/24" # OpenVPN - "192.168.45.0/24"
become: yes become: yes
- name: Allow Samba from trusted subnets - name: Allow Samba from trusted subnets
@ -143,14 +173,10 @@ ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.
rule: allow rule: allow
port: "{{ item }}" port: "{{ item }}"
proto: tcp proto: tcp
from: "{{ from_item }}" from: "192.168.1.0/24"
loop: loop:
- 139 - 139
- 445 - 445
loop_control:
loop_var: port
vars:
from_item: "192.168.1.0/24"
become: yes become: yes
- name: Allow HTTP/HTTPS for NPM - name: Allow HTTP/HTTPS for NPM
@ -171,7 +197,6 @@ ansible-playbook -i inventories/hosts olimp-deploy.yml --vault-password-file ~/.
- **Описание**: Для публичных прокси не настроены заголовки безопасности: HSTS, X-Content-Type-Options, X-Frame-Options. - **Описание**: Для публичных прокси не настроены заголовки безопасности: HSTS, X-Content-Type-Options, X-Frame-Options.
- **Решение**: Через веб-интерфейс NPM → Proxy Hosts → Edit → Advanced → Custom locations добавить: - **Решение**: Через веб-интерфейс NPM → Proxy Hosts → Edit → Advanced → Custom locations добавить:
```nginx ```nginx
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always; add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Frame-Options "SAMEORIGIN" always;
@ -182,12 +207,6 @@ add_header Content-Security-Policy "default-src 'self'" always;
- **Применить ко всем публичным доменам**: `*.zailon.ru` - **Применить ко всем публичным доменам**: `*.zailon.ru`
- **Срок**: В течение недели - **Срок**: В течение недели
### 3. Резервное копирование не настроено
- **Описание**: Нет автоматического бэкапа конфигураций, баз данных и пользовательских данных.
- **Решение**: Описано в разделе [11. Резервное копирование](11-backup.md)
- **Срок**: В течение 2 недель
--- ---
## 🟠 Проблемы высокого приоритета ## 🟠 Проблемы высокого приоритета
@ -197,15 +216,9 @@ add_header Content-Security-Policy "default-src 'self'" always;
- **Описание**: Образы обновляются неконтролируемо, что может привести к несовместимости. - **Описание**: Образы обновляются неконтролируемо, что может привести к несовместимости.
- **Решение**: Зафиксировать версии в `docker-compose.yml`: - **Решение**: Зафиксировать версии в `docker-compose.yml`:
```yaml ```yaml
# Было:
services: services:
npm: npm:
image: jc21/nginx-proxy-manager:latest image: jc21/nginx-proxy-manager:2.12.3
# Стало:
services:
npm:
image: jc21/nginx-proxy-manager:2.12.3 # Зафиксированная версия
``` ```
- **План**: Пройтись по всем `docker-compose.yml` и зафиксировать версии - **План**: Пройтись по всем `docker-compose.yml` и зафиксировать версии
- **Срок**: В течение месяца - **Срок**: В течение месяца
@ -214,10 +227,9 @@ services:
- **Описание**: На хостах накапливаются обновления пакетов. - **Описание**: На хостах накапливаются обновления пакетов.
- **Решение**: - **Решение**:
- Регулярно запускать `apt update && apt upgrade` через Ansible (уже реализовано в роли `base_setup`) - Регулярно запускать `apt update && apt upgrade` через Ansible
- Настроить `unattended-upgrades` для автоматических обновлений безопасности - Настроить `unattended-upgrades` для автоматических обновлений безопасности
```yaml ```yaml
# Пример задачи для unattended-upgrades
- name: Install unattended-upgrades - name: Install unattended-upgrades
apt: apt:
name: unattended-upgrades name: unattended-upgrades
@ -233,8 +245,6 @@ services:
}; };
Unattended-Upgrade::Automatic-Reboot "false"; Unattended-Upgrade::Automatic-Reboot "false";
dest: /etc/apt/apt.conf.d/50unattended-upgrades dest: /etc/apt/apt.conf.d/50unattended-upgrades
owner: root
mode: '0644'
become: yes become: yes
``` ```
- **Статус**: 🟡 В процессе - **Статус**: 🟡 В процессе
@ -258,11 +268,8 @@ services:
- **Описание**: Нет правил для оповещения при ошибках в логах. - **Описание**: Нет правил для оповещения при ошибках в логах.
- **Решение**: Настроить правила в Grafana → Alerting на основе Loki: - **Решение**: Настроить правила в Grafana → Alerting на основе Loki:
```logql ```logql
# Пример: алерт на ошибки в логах SSH
{job="promtail", filename="/var/log/auth.log"} |= "Failed password" | rate() > 5 {job="promtail", filename="/var/log/auth.log"} |= "Failed password" | rate() > 5
{job="promtail", container="nginx-proxy-manager"} |= "error"
# Пример: алерт на ошибки в логах NPM
{job="promtail", container="nginx-proxy-manager"} |= "error" | level="error"
``` ```
- **Статус**: 🟡 В планах - **Статус**: 🟡 В планах
@ -283,6 +290,7 @@ services:
| Мониторинг роутера | Сбор SNMP-метрик с TP-Link | 🟢 | | Мониторинг роутера | Сбор SNMP-метрик с TP-Link | 🟢 |
| Двухфакторная аутентификация | Включить 2FA в Grafana, GitLab, Bitwarden | 🟢 | | Двухфакторная аутентификация | Включить 2FA в Grafana, GitLab, Bitwarden | 🟢 |
| Регулярный аудит | Запускать Lynis/OpenVAS раз в 3 месяца | 🟢 | | Регулярный аудит | Запускать Lynis/OpenVAS раз в 3 месяца | 🟢 |
| Оффсайт-бэкапы | Настроить репликацию PBS в облако (Backblaze B2/Wasabi) | 🟢 |
--- ---
@ -293,10 +301,10 @@ services:
| Применить настройку SSH (root+zailon) на всех хостах | 🔴 | 1 день | 🔄 В процессе | | Применить настройку SSH (root+zailon) на всех хостах | 🔴 | 1 день | 🔄 В процессе |
| Включить UFW на всех хостах | 🔴 | 1 неделя | ⏳ Ожидает | | Включить UFW на всех хостах | 🔴 | 1 неделя | ⏳ Ожидает |
| Добавить заголовки безопасности в NPM | 🔴 | 1 неделя | ⏳ Ожидает | | Добавить заголовки безопасности в NPM | 🔴 | 1 неделя | ⏳ Ожидает |
| Настроить резервное копирование | 🔴 | 2 недели | ⏳ Ожидает |
| Зафиксировать версии Docker-образов | 🟠 | 1 месяц | ⏳ Ожидает | | Зафиксировать версии Docker-образов | 🟠 | 1 месяц | ⏳ Ожидает |
| Настроить unattended-upgrades | 🟢 | 1 месяц | ⏳ Ожидает | | Настроить unattended-upgrades | 🟢 | 1 месяц | ⏳ Ожидает |
| Настроить алерты на логи | 🟡 | По необходимости | ⏳ Ожидает | | Настроить алерты на логи | 🟡 | По необходимости | ⏳ Ожидает |
| Настроить репликацию PBS (оффсайт) | 🟢 | 2 месяца | ⏳ Ожидает |
--- ---
@ -305,22 +313,11 @@ services:
Перед запуском playbook на всех хостах: Перед запуском playbook на всех хостах:
```bash ```bash
# 1. Проверка прав на SSH-ключ Ansible
chmod 600 /root/.ssh/id_rsa chmod 600 /root/.ssh/id_rsa
# 2. Проверка vault
ansible-vault view vault.yml --ask-vault-pass | grep zailon ansible-vault view vault.yml --ask-vault-pass | grep zailon
# 3. Dry-run на одном хосте
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 --check --diff --ask-vault-pass
# 4. Применение на одном хосте
ansible-playbook -i inventories/hosts olimp-deploy.yml -l torrent --ask-vault-pass ansible-playbook -i inventories/hosts olimp-deploy.yml -l torrent --ask-vault-pass
# 5. Тест подключения под zailon (в НОВОМ окне!)
ssh zailon@192.168.1.211 ssh zailon@192.168.1.211
# 6. Если всё ок — применяем на всех
ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass
``` ```
@ -328,6 +325,17 @@ ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass
--- ---
## 📊 Мониторинг безопасности
```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) - [05. Samba файловые шары](05-samba.md)
- [07. Проксирование и SSL (NPM)](07-proxy-ssl.md) - [07. Проксирование и SSL (NPM)](07-proxy-ssl.md)