From b32cc0116031e2745699fe235c26a57f805625e4 Mon Sep 17 00:00:00 2001 From: Administrator Date: Tue, 24 Mar 2026 11:33:34 +0500 Subject: [PATCH] Update file 10-security.md --- docs/10-security.md | 428 +++++++++++++++++++++++++++++++++----------- 1 file changed, 320 insertions(+), 108 deletions(-) diff --git a/docs/10-security.md b/docs/10-security.md index 544d220..31c307c 100644 --- a/docs/10-security.md +++ b/docs/10-security.md @@ -4,121 +4,333 @@ В этом разделе собраны текущие проблемы безопасности инфраструктуры и план их устранения. Документ основан на результатах аудита, проведённого в марте 2026 года. +> **Последнее обновление**: 24 марта 2026 +> **Применено на хостах**: `torrent` (192.168.1.211) +> **В процессе**: применение на остальных хостах + +--- + ## Текущее состояние | Область | Статус | Комментарий | |---------|--------|-------------| | SSH (парольная аутентификация) | ✅ | Отключена на всех хостах | -| SSH (вход root) | 🔴 | Разрешён на всех хостах | -| SSH-ключи | 🟡 | Управляются через Ansible, но требуется проверка на наличие лишних ключей | -| Samba (шифрование) | 🟡 | На `media` – `desired`, на `games` – `required` | -| Samba (протокол) | 🔴 | На `media` используется `NT1` (SMB1), что небезопасно | +| SSH (вход root) | ✅ | Запрещён (`PermitRootLogin no`) на `torrent`, применяется на остальных | +| Пользователь `zailon` | ✅ | Создан с правами `sudo`, SSH-ключи настроены | +| SSH-ключи | ✅ | Управляются централизованно через Ansible | +| Samba (протокол) | ✅ | Обновлён до `SMB2` на `media` | +| Samba (шифрование) | 🟡 | `smb encrypt = desired` (пока не `required` из-за совместимости) | | UFW / фаервол | 🔴 | Отключён на всех LXC и ВМ | -| Хранение паролей в Ansible | 🔴 | Часть паролей в открытом виде в `all.yml` | +| Хранение паролей в Ansible | ✅ | Все секреты перенесены в `vault.yml` и зашифрованы | | Заголовки безопасности в NPM | 🔴 | Отсутствуют для большинства прокси | -| Docker-образы | 🟡 | Используется тег `latest`, неконтролируемые обновления | -| Обновления систем | 🟡 | Много пакетов требуют обновления (49 на `media`, аналогично на других) | -| Мониторинг | 🟢 | Настроен, но нет алертов на логи и некоторые метрики | -| Резервное копирование | 🔴 | Не настроено (будет описано в отдельном разделе) | - -## Критические проблемы (🔴) - -### 1. Вход root по SSH -- **Описание**: На всех хостах разрешён вход под пользователем `root` через SSH. При компрометации ключа злоумышленник получает полный контроль над системой. -- **Решение**: Создать обычного пользователя (например, `ansible`), добавить его в группу `sudo`, настроить ключи и запретить вход root в `/etc/ssh/sshd_config` (`PermitRootLogin no`). Перезапустить SSH. - -### 2. Samba на media использует SMB1 -- **Описание**: В конфигурации Samba на хосте `media` установлен `server min protocol = NT1`, что соответствует SMB1. Этот протокол уязвим (EternalBlue и другие атаки). -- **Решение**: Изменить на `server min protocol = SMB2` (или `SMB3`). После изменения проверить работу клиентов (Windows, Android, Docker). Если Android не поддерживает SMB2/3, использовать VPN для доступа к шарам. - -### 3. Отсутствие фаервола на всех LXC -- **Описание**: UFW отключён на всех LXC-контейнерах. Сервисы доступны из всей локальной сети без ограничений. -- **Решение**: Включить UFW на каждом хосте, разрешив только необходимые порты: - - SSH (только из подсетей 192.168.1.0/24 и 192.168.45.0/24) - - Samba (139, 445) – только из локальной и VPN-подсетей - - Порты Docker-сервисов (например, 45131, 45132 и т.д.) – если они должны быть доступны только через NPM, то разрешить только для `gateway` или для всей локальной сети - - HTTP/HTTPS (80, 443) – если сервис слушает напрямую, а не через NPM - -### 4. Пароли в открытом виде в Ansible -- **Описание**: В файле `group_vars/all.yml` присутствуют пароли в открытом виде (например, `grafana_admin_password`, пароли Samba, PostgreSQL и др.). -- **Решение**: Немедленно перенести все секреты в `group_vars/vault.yml` и зашифровать с помощью Ansible Vault. Удалить открытые пароли из `all.yml`. - -### 5. Отсутствие заголовков безопасности в NPM -- **Описание**: Для большинства проксируемых доменов не настроены заголовки HSTS, X-Content-Type-Options, X-Frame-Options и другие. -- **Решение**: Через веб-интерфейс NPM для каждого публичного прокси добавить заголовки (см. раздел [Проксирование и SSL](07-proxy-ssl.md)). - -## Проблемы высокого приоритета (🟠) - -### 1. Использование Docker-образов с тегом `latest` -- **Описание**: Образы, такие как `jc21/nginx-proxy-manager:latest`, обновляются неконтролируемо, что может привести к несовместимости или неожиданным изменениям. -- **Решение**: Зафиксировать версии образов в `docker-compose.yml` (например, `jc21/nginx-proxy-manager:2.12.3`). - -### 2. Необновлённые системы -- **Описание**: На хосте `media` 49 пакетов требуют обновления, включая Docker и системные библиотеки. Аналогичная ситуация на других хостах. -- **Решение**: Выполнить `apt update && apt upgrade` на всех хостах. Настроить автоматические обновления безопасности (`unattended-upgrades`). - -### 3. Прокси с Offline статусом -- **Описание**: `qb.zailon.ru` недоступен. Возможно, qBittorrent не запущен или не слушает порт 8080. -- **Решение**: Проверить контейнер qBittorrent на `torrent`, убедиться, что порт 8080 открыт, и правило прокси в NPM корректно. - -## Проблемы среднего приоритета (🟡) - -### 1. Шифрование Samba на media -- **Описание**: Установлено `smb encrypt = desired` вместо `required`. Это снижает безопасность передачи данных. -- **Решение**: После включения VPN для доступа к шарам извне изменить на `required`. Если Android-клиенты не поддерживают шифрование, использовать VPN. - -### 2. Управление SSH-ключами -- **Описание**: В `all.yml` указаны три публичных ключа. Необходимо убедиться, что на всех хостах нет лишних ключей, а также что ключи актуальны. -- **Решение**: Проверить содержимое `~/.ssh/authorized_keys` на каждом хосте, удалить ненужные. Использовать Ansible для централизованного управления ключами. - -### 3. cAdvisor не включён на всех хостах -- **Описание**: В плейбуке роль `cadvisor` закомментирована, поэтому метрики Docker-контейнеров собираются не везде. -- **Решение**: Если нужен полный мониторинг, раскомментировать роль в `olimp-deploy.yml` и применить её для хостов с Docker. - -### 4. Отсутствие алертов на логи -- **Описание**: Настроены только алерты на метрики. Нет алертов на появление в логах ошибок, попыток взлома и т.п. -- **Решение**: Настроить правила алертов в Grafana на основе Loki (например, при появлении `error` в логах NPM или SSH). - -## Рекомендации по улучшению (🟢) - -### 1. Включить автоматические обновления безопасности -- На всех хостах установить `unattended-upgrades` и настроить его на автоматическую установку обновлений безопасности. - -### 2. Сегментация сети -- Выделить VLAN для умных устройств (IoT) и гостевой сети, чтобы ограничить распространение атаки. - -### 3. Мониторинг роутера -- Настроить сбор SNMP-метрик с роутера TP-Link (если поддерживается) для мониторинга нагрузки, ошибок и подозрительного трафика. - -### 4. Резервное копирование -- Организовать регулярное резервное копирование конфигураций, баз данных и пользовательских данных. Хранить копии в зашифрованном виде вне основной сети. - -### 5. Двухфакторная аутентификация -- Для критических сервисов (Grafana, GitLab, Bitwarden) включить 2FA, если это поддерживается. - -### 6. Регулярный аудит -- Проводить периодический аудит безопасности (например, раз в 3 месяца) с использованием специализированных инструментов (Lynis, OpenVAS). - -## План действий - -| Задача | Приоритет | Срок | -|--------|-----------|------| -| Перенести пароли в Ansible Vault | 🔴 | Немедленно | -| Запретить вход root по SSH | 🔴 | Немедленно | -| Включить UFW на всех хостах | 🔴 | В течение недели | -| Обновить Samba (протокол и шифрование) | 🔴 | В течение недели | -| Добавить заголовки безопасности в NPM | 🔴 | В течение недели | -| Зафиксировать версии Docker-образов | 🟠 | В течение месяца | -| Обновить все системы | 🟠 | В течение месяца | -| Настроить автоматические обновления | 🟢 | В течение месяца | -| Включить cAdvisor | 🟡 | По мере необходимости | -| Настроить алерты на логи | 🟡 | По мере необходимости | +| Docker-образы | 🟡 | Используется тег `latest` на части сервисов | +| Обновления систем | 🟡 | Требуют периодического применения | +| Мониторинг | ✅ | Node Exporter, Promtail, VictoriaMetrics настроены | +| Резервное копирование | 🔴 | Не настроено (будет описано в разделе 11) | --- -**Связанные разделы:** -- [Samba – файловые шары](05-samba.md) -- [Проксирование и SSL (NPM)](07-proxy-ssl.md) -- [Мониторинг и логирование](08-monitoring.md) -- [Управление конфигурацией (Ansible)](09-ansible.md) -- [Резервное копирование](11-backup.md) \ No newline at end of file +## ✅ Решённые проблемы + +### 1. Вход root по SSH — ИСПРАВЛЕНО + +- **Описание**: На всех хостах разрешён вход под пользователем `root` через SSH. При компрометации ключа злоумышленник получает полный контроль над системой. +- **Что сделано**: + - Создан пользователь `zailon` с правами `sudo` + - Настроены SSH-ключи из `ssh_public_keys` + - В `/etc/ssh/sshd_config` установлено `PermitRootLogin no` + - Применено через Ansible на хосте `torrent` +- **Проверка**: +```bash +# Проверка подключения под zailon +ssh zailon@192.168.1.211 # ✅ Работает + +# Проверка запрета root +ssh root@192.168.1.211 # ❌ Permission denied (publickey) + +# Проверка конфигурации SSH +grep PermitRootLogin /etc/ssh/sshd_config +# Ожидаемый вывод: PermitRootLogin no +``` +- **Статус**: ✅ Применено на `torrent`, готовится применение на остальных хостах + +### 2. Пароли в открытом виде в Ansible — ИСПРАВЛЕНО + +- **Описание**: В файле `group_vars/all.yml` присутствовали пароли в открытом виде. +- **Что сделано**: + - Все секреты перенесены в `group_vars/vault.yml` + - Файл зашифрован через `ansible-vault encrypt vault.yml` + - В `all.yml` остались только публичные переменные +- **Список зашифрованных переменных**: +```yaml +# vault.yml (зашифрован) +vault_zailon_password: "M!n0t@vr" # Пароль администратора +vault_grafana_admin_password: "..." # Grafana +vault_gitlab_root_password: "..." # GitLab +vault_bitwarden_admin_token: "..." # Bitwarden +vault_bitwarden_smtp_password: "..." # Bitwarden SMTP +vault_mealie_db_password: "..." # Mealie DB +vault_flibusta_db_password: "..." # Flibusta DB +vault_immich_db_password: "..." # Immich DB +vault_mumble_server_password: "..." # Mumble +vault_mumble_superuser_password: "..." # Mumble superuser +vault_matrix_postgres_password: "..." # Matrix/Synapse +vault_matrix_synapse_secret: "..." # Matrix secrets +vault_matrix_macaroon_secret: "..." +vault_matrix_form_secret: "..." +vault_matrix_admin_password: "..." +vault_snikket_admin_password: "..." # Snikket XMPP +vault_snikket_invite_token: "..." +vault_smb_olimp_password: "..." # SMB shares +vault_samba_password_qb: "..." +vault_pve_exporter_token: "..." # Proxmox exporter +``` +- **Запуск 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 # было: NT1 + smb encrypt = desired # оставлено для совместимости с клиентами +``` + - Проверена работа клиентов (Windows, Android, Docker) +- **Статус**: ✅ Завершено на `media` + +--- + +## 🔴 Критические проблемы (требуют внимания) + +### 1. Отсутствие фаервола на всех LXC + +- **Описание**: UFW отключён на всех LXC-контейнерах. Сервисы доступны из всей локальной сети без ограничений. +- **Решение**: Включить UFW на каждом хосте с минимально необходимыми правилами: +```yaml +# Пример роли ufw_setup/tasks/main.yml +- 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" # LAN + - "192.168.45.0/24" # OpenVPN + become: yes + +- name: Allow Samba from trusted subnets + ufw: + rule: allow + port: "{{ item }}" + proto: tcp + from: "{{ from_item }}" + loop: + - 139 + - 445 + loop_control: + loop_var: port + vars: + from_item: "192.168.1.0/24" + 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 +# Security headers +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` +- **Срок**: В течение недели + +### 3. Резервное копирование не настроено + +- **Описание**: Нет автоматического бэкапа конфигураций, баз данных и пользовательских данных. +- **Решение**: Описано в разделе [11. Резервное копирование](11-backup.md) +- **Срок**: В течение 2 недель + +--- + +## 🟠 Проблемы высокого приоритета + +### 1. Использование Docker-образов с тегом `latest` + +- **Описание**: Образы обновляются неконтролируемо, что может привести к несовместимости. +- **Решение**: Зафиксировать версии в `docker-compose.yml`: +```yaml +# Было: +services: + npm: + image: jc21/nginx-proxy-manager:latest + +# Стало: +services: + npm: + image: jc21/nginx-proxy-manager:2.12.3 # Зафиксированная версия +``` +- **План**: Пройтись по всем `docker-compose.yml` и зафиксировать версии +- **Срок**: В течение месяца + +### 2. Необновлённые системы + +- **Описание**: На хостах накапливаются обновления пакетов. +- **Решение**: + - Регулярно запускать `apt update && apt upgrade` через Ansible (уже реализовано в роли `base_setup`) + - Настроить `unattended-upgrades` для автоматических обновлений безопасности +```yaml +# Пример задачи для unattended-upgrades +- 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 + owner: root + mode: '0644' + become: yes +``` +- **Статус**: 🟡 В процессе + +--- + +## 🟡 Проблемы среднего приоритета + +### 1. Шифрование Samba: `desired` вместо `required` + +- **Описание**: `smb encrypt = desired` допускает незашифрованные соединения. +- **Решение**: После тестирования всех клиентов в VPN изменить на `required`: +```ini +[global] + smb encrypt = required +``` +- **Статус**: 🟡 Отложено до полной проверки совместимости + +### 2. Отсутствие алертов на логи в Grafana + +- **Описание**: Нет правил для оповещения при ошибках в логах. +- **Решение**: Настроить правила в Grafana → Alerting на основе Loki: +```logql +# Пример: алерт на ошибки в логах SSH +{job="promtail", filename="/var/log/auth.log"} |= "Failed password" | rate() > 5 + +# Пример: алерт на ошибки в логах NPM +{job="promtail", container="nginx-proxy-manager"} |= "error" | level="error" +``` +- **Статус**: 🟡 В планах + +### 3. cAdvisor не включён на всех хостах + +- **Описание**: Метрики Docker-контейнеров собираются не везде. +- **Решение**: Раскомментировать роль `cadvisor` в `olimp-deploy.yml` при необходимости. +- **Статус**: 🟡 По мере необходимости + +--- + +## 🟢 Рекомендации по улучшению + +| Задача | Описание | Приоритет | +|--------|----------|-----------| +| Автоматические обновления | Настроить `unattended-upgrades` на всех хостах | 🟢 | +| Сегментация сети | Выделить VLAN для IoT и гостевой сети | 🟢 | +| Мониторинг роутера | Сбор SNMP-метрик с TP-Link | 🟢 | +| Двухфакторная аутентификация | Включить 2FA в Grafana, GitLab, Bitwarden | 🟢 | +| Регулярный аудит | Запускать Lynis/OpenVAS раз в 3 месяца | 🟢 | + +--- + +## 📋 План действий + +| Задача | Приоритет | Срок | Статус | +|--------|-----------|------|--------| +| Применить настройку SSH (root+zailon) на всех хостах | 🔴 | 1 день | 🔄 В процессе | +| Включить UFW на всех хостах | 🔴 | 1 неделя | ⏳ Ожидает | +| Добавить заголовки безопасности в NPM | 🔴 | 1 неделя | ⏳ Ожидает | +| Настроить резервное копирование | 🔴 | 2 недели | ⏳ Ожидает | +| Зафиксировать версии Docker-образов | 🟠 | 1 месяц | ⏳ Ожидает | +| Настроить unattended-upgrades | 🟢 | 1 месяц | ⏳ Ожидает | +| Настроить алерты на логи | 🟡 | По необходимости | ⏳ Ожидает | + +--- + +## 🔐 Чек-лист применения изменений + +Перед запуском playbook на всех хостах: + +```bash +# 1. Проверка прав на SSH-ключ Ansible +chmod 600 /root/.ssh/id_rsa + +# 2. Проверка vault +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 + +# 4. Применение на одном хосте +ansible-playbook -i inventories/hosts olimp-deploy.yml -l torrent --ask-vault-pass + +# 5. Тест подключения под zailon (в НОВОМ окне!) +ssh zailon@192.168.1.211 + +# 6. Если всё ок — применяем на всех +ansible-playbook -i inventories/hosts olimp-deploy.yml --ask-vault-pass +``` + +> ⚠️ **Важно**: Не закрывайте текущую SSH-сессию `root`, пока не проверите вход под `zailon` в отдельном окне! + +--- + +**Связанные разделы**: +- [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) \ No newline at end of file