Проектирование программной платформы защищённого NAS


    Допустим, аппаратная часть NAS собрана и на неё установлена ОС, например, как показано здесь. И сейчас у вас есть работающий сервер с Debian, который загружается, подключен в сеть, и вы имеете к нему полный физический доступ.


    Теперь надо спроектировать среду, позволяющую легко и безопасно добавлять, удалять прикладные сервисы, а также управлять их работой.


    Вдохновившись статьёй от некоего Cloud Architect, я решил сделать систему, в которой большинство служб работают в контейнерах.


    Кроме того, сходные методы (например, разделение пространств ввода-вывода путём контейнерной виртуализации) используются в достаточно ответственных системах атомной индустрии.


    Это очень удобно и безопасно:


    • Нет конфликтов зависимостей. Возможно держать в системе несколько разных версий Glibc, php, nginx и всего, что угодно, кроме ядра.
    • Нет непонятно где разбросанных конфигураций.
    • Службы легко останавливать, запускать, обновлять и т.д..
    • В каждый контейнер легко добавить свои настройки и изменения, где бы они не находились, хоть в /usr. В "обычной ОС" пакетная система затрёт такие изменения и надо извращаться с хуками, чтобы они были постоянны.
    • Контейнеры предоставляют высокую степень изоляции: одна скомпрометированная служба ещё не означает полного доступа ко всем остальным и, тем более, к системе.

    Но в его варианте есть и то, что мне не понравилось:


    • Proxmox здесь лишний. Во-первых, ради поддержки ZFS устанавливать его нет смысла, т.к. ОС с полной его поддержкой, включая корневую ФС, я устанавливаю вручную. Во-вторых, это NAS, а не сервер виртуальных машин, так что функциональность Proxmox избыточна. В-третьих, контейнерами и виртуальными машинами может управлять OpenMediaVault, а иметь две точки входа неудобно. Ну и, в-четвёртых ядро Proxmox поддерживается OMV, при подключении репозиториев OMV Extras, и заниматься пересборкой пакетов не нужно.
    • Конфликты зависимостей — это один из самых больших минусов, которые несёт с собой использование Proxmox совместно с OpenMediaVault. Из-за этого приходится пересобирать пакеты, и затрудняются обновления.
    • Устанавливать OMV 3-й версии, когда есть 4-я, в которой много переделано, сейчас уже не имеет смысла.
    • nginx-proxy-companion для lets-encrypt у меня не заработал, и пришлось решать проблему сертификата другим методом.

    В данной статье предложен вариант, который работает на моём NAS и пока меня вполне устраивает.


    С целью повышения удобочитаемости, тема разбита на две статьи: проектирование и реализация.


    Дисковая организация


    Здесь я немного повторюсь и для полноты кратко приведу дисковую организацию системы.

    Системные SSD


    Под систему отведено две SSD, причём вторая SSD является зеркалом первой.


    Структура данных на SSD:


    • part_boot — раздел с загрузчиком. Размер = 1GB.
    • part_system — раздел с системой. Размер = 32 GB (Рекомендованный размер: 16 GB * 2).
    • part_slog — раздел с SLOG. Размер = 5 GB.
      SLOG не может быть более размера RAM = 32 GB + 48 GB swap = 80 GB, 16 GB с учётом возможного расширения swap).
      96 GB — абсолютный лимит.
      Обычным правилом для установки размера SLOG является выделение объёма не более того, который система может пропустить за 5 с.
      В случае платы с 2-мя 1G интерфейсами, SLOGsz = 1000 / 8 2 5 = 1250 MB.
      Размер с запасом выбран 5 GB.

    part_system и part_slog зашифрованы в XTS режиме.


    В целом, их организация такова:


    SSD1: [part_boot] -> [zfs_mirror] <---> SSD2
    SSD1: [part_system] -> [crypto_xts] -> [zfs_mirror] <---> SSD2
    SSD1: [part_slog] -> [crypto_xts] -> [zfs_zil_mirror] <---> SSD2

    Дублирование разделов производится средствами ZFS.


    SSD с кэшем L2ARC


    Нижний слой зашифрован, используя XTS режим на случайном ключе.


    Содержит два раздела:


    • part_swap — раздел подкачки. Размер = 48 GB (max RAM * 1.5 = 32 GB * 1.5).
    • part_l2arc — L2ARC. Размер = 196 GB (ARC size * [3..10], ARC size = 0.6 * max RAM size, т.е. 58 — 196 GB, кроме того, с выключенной дедупликацией нужно ~1 GB L2ARC на 1 TB данных).

    swap и l2arc зашифрованы случайным ключом.


    Случайный ключ для раздела подкачки приемлем, т.к. система не будет использовать режим гибернации.


    Под L2ARC выделяется всё оставшееся место, его реальная нужность при размере памяти до 32 GB сомнительна.


    Размер L2ARC требуется точнее настроить в процессе работы системы по статистике кэш-попаданий.


    Организация:


    SSD3: | -> [part_swap] -> [crypto_xts] -> [system swap]
          | -> [part_l2arc] -> [crypto_xts] -> [l2arc]

    Дисковая корзина


    Т.к. на первом этапе планировалось использовать 4 диска из 8-ми возможных, все диски в корзине включены в 2 ZFS VDEV.


    Каждый диск первым имеет слой шифрования XTS. Поверх него организуется физическое устройство ZFS.


    4 физических устройства объединены в один RAIDZ1. Если не жалко дискового пространства, либо устройств больше (например, планируется сразу закупить все диски), рекомендуется сделать RAIDZ2 и один массив.


    Замеры производительности.
    • Прямое копирование на диск блоками по 4 MB: 185 MB/s (dsync: 136 MB/s)
    • LUKS раздел с поддержкой команд AES-NI: 184 MB/s (dsync: 135 MB/s)
    • ZFS volume = 170 MB/s (dsync: 50 MB/s).
    • LUKS on ZFS volume = 274 MB/s (dsync: 38 MB/s).
    • ZFS on LUKS = 187 MB/s (dsync: 50 MB/s)

    Отсюда вывод: всё-таки несмотря на "заверения экспертов" располагать ZFS pool лучше поверх LUKS, а не наоборот. LUKS почти не вносит оверхед (с AES-NI). А кэширование записи диска всегда возможно включить вручную (как и подобрать размер блока, который у ZFS, к тому же, переменный).


    Полная схема такова:


    HDD1: [crypto_xts] -> [zfs_phdev] |
    HDD2: [crypto_xts] -> [zfs_phdev] |
    HDD3: [crypto_xts] -> [zfs_phdev] | -> [RAIDZ1] -> [tank0]
    HDD4: [crypto_xts] -> [zfs_phdev] |
    
    HDD5: [crypto_xts] -> [zfs_phdev] |
    HDD6: [crypto_xts] -> [zfs_phdev] |
    HDD7: [crypto_xts] -> [zfs_phdev] | -> [RAIDZ1] -> [tank1]
    HDD8: [crypto_xts] -> [zfs_phdev] |

    Организация файловых систем


    Структура пула


    NAS будет содержать различные прикладные системы, описание которых приведено ниже.
    Каждая система добавляет свой каталог в фиксированные точки структуры каталогов пула, но имена каталогов для каждой системы будут описаны при её проектировании.


    Ниже приведена файловая структура пула, общая для всех систем:



    Код диаграммы
    @startsalt
    {
    {T
    +/
    ++ tank0
    +++ docker
    ++++ lib
    ++++ services
    +++ apps
    +++ repos
    +++ user_data
    ++++ music
    ++++ videos
    ++++ pictures
    ++++ Хранилища пользователей.
    ++ tank1
    +++ apps
    +++ user_data
    }
    }
    @endsalt

    На диаграмме:


    • tank0/docker — данные служб, запущенных в Docker.
      • lib — служебные файлы докера. Это отдельная ФС, и требуется для того, чтобы докер не засорял /var снэпшотами.
      • services — описание контейнеров (например, файлы dockercompose) и их служебные файлы.
    • tank0/apps — хранилище является корнем, в котором создаются хранилища для пользовательских приложений. Внутри подкаталога для приложения, приложение вольно располагать данные так, как считает нужным.
    • tank0/repos — репозитории. Здесь будут храниться пользовательские данные под версионным контролем. Поскольку я планирую использовать только Git, там будут содержатся непосредственно репозитории. Но вообще, в данном каталоге могут быть подкаталоги для разных систем контроля версий.
    • tank0/user_data — хранилище является корнем, в котором создаются хранилища для пользовательских данных:
      • books — здесь хранится пользовательская библиотека.
      • music — музыка пользователей.
      • videos — видео.
      • pictures — различные изображения и фотографии.
      • Хранилища пользователей (по их именам).
    • tank1/apps — хранилище является корнем, в котором создаются хранилища для пользовательских приложений. Повторяет структуру в tank0.
    • tank1/user_data — хранилище является корнем, в котором создаются хранилища для пользовательских данных. Повторяет структуру в tank0.

    Хранилище tank1 выделено на перспективу: оно будет реализовано в случае расширения дискового пространства.


    Состав системного ПО и взаимодействие компонентов


    Так выглядит NAS в контексте взаимодействующих с ним систем:



    Код диаграммы
    @startuml
    ' -----------------------------------------------------
    'left to right direction
    scale 0.72
    
    package Internet #efefff {
    cloud "Let's\nEncrypt" as le {
    }
    
    cloud "Cloud DNS" #ffffff {
      frame "A-записи" as af {
        artifact "system.NAS.cloudns.cc" as d1
        artifact "omv.NAS.cloudns.cc" as d2
        artifact "ldap.NAS.cloudns.cc" as d3
        artifact "ssp.NAS.cloudns.cc" as d4
        artifact "cloud.NAS.cloudns.cc" as d5
        artifact "git.NAS.cloudns.cc" as d6
        artifact "backup.NAS.cloudns.cc" as d7
      }
    
      frame "TXT-записи" as tf {
        artifact "Domain:_acme-challenge.*.NAS.cloudns.cc\nTxt value:9ihDbjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    }
    
    cloud "Почтовый сервер" as ms #ffffff
    }
    'Internet end
    
    package LAN #efffef {
    node Роутер as router #ffffff {
      component "DNS сервер" {
        artifact ".*\.nas" as ndns
      }
      component "NAT" {
         artifact "Порт 80" as rop80
         artifact "Порт 443" as rop443
         artifact "Порт 5022" as rop5022
      }
    
    }
    
    node NAS #ffefef {
      component "Порты" {
         artifact "Порт 22" as nasp22
         artifact "Порт 80" as nasp80
         artifact "Порт 443" as nasp443
      }
    
      package Docker {
        component "letsencrypt-dns" as led {
        }
    
        component "nginx-reverse-proxy" as nrp {
        }
    
        component "nginx-local" as ngl {
        }
    
        component "LDAP сервер и его WEB GUI" as ldaps {
        }
    
        component "LDAP SSP" as ssp {
        }
        collections "Прочие сервисы\n(Backup, Cloud, DLNA, etc.)" as services
      }
    
      artifact "Файлы сертификата" as cert_file
    
      component "WEB интерфейс OMV" as omvwg {
      }
    
      component "Демоны OMV" as omv {
      }
    
      component "SSH сервер" as sshd {
      }
    
      component "NUT" as nut {
      }
    
    }
    }
    'LAN end
    
    node ИБП as ups #ffefef
    
    actor Пользователь as user
    user <- af
    user <-> router
    user <- ms
    
    nut <-- ups : USB
    
    le <-- af
    le <-- tf
    led .-> tf : Через\nроутер
    led <-. le : Через\nроутер
    led .> cert_file
    nrp <. cert_file
    
    af -> router
    
    ndns -> NAS
    rop80 <--> nasp80
    rop443 <--> nasp443
    rop5022 <--> nasp22
    
    nasp22 <--> sshd
    nasp80 <--> nrp
    nasp443 <--> nrp
    
    nrp <--> ngl : Сеть\ndocker0
    nrp <--> ldaps : Сеть\ndocker0
    nrp <--> ssp : Сеть\ndocker0
    ldaps <--> ssp : Сеть\ndocker0
    
    nrp <--> services
    
    ngl <--> omvwg : Сеть хоста
    omv <--> omvwg : Сеть хоста
    omv .> ms : Через\nроутер
    omv ..> sshd : Управление\nиз WEB GUI
    omv ..> nut : Управление\nиз WEB GUI
    @enduml

    На этой загромождённой диаграмме отражён состав его служб и большинство взаимодействий.
    Далее компоненты, назначение служб и алгоритмы функционирования будут расписаны подробнее.


    Операционная система


    Система, как было показано выше, установлена на SSD, включённых в зеркало средствами ZFS. В качестве ОС выбран OpenMediaVault — система управления хранилищем и WEB GUI (далее — OMV).


    Его достаточно просто установить пакетом, а всё остальное будет подтянуто по зависимостям: ядро, дополнительные репозитории и т.п..


    Системное ПО


    Центральными компонентами являются:


    • Nginx proxy — диспетчер с автоматическим управлением сертификатами (посредством отдельного механизма).
    • Docker — система контейнеризации. Обеспечивает удобную работу с контейнерами: загрузку образов, сборку, конфигурирование и т.п… Для управления контейнерами используется плагин OMV.

    На физической машине работает только OMV, SSH и демоны, к которым не обращается пользователь. Все остальные системы работают внутри Docker-контейнеров.


    Управление пользователями


    Аутентификация пользователей производится посредством LDAP. Это сделано потому, чтобы управлять пользователями централизованно, и большинство сервисов поддерживает этот механизм, в отличие от, например RADIUS сервера и подобных пусть и более удобных, новых и легковесных решений.


    LDAP сервер работает в контейнере, но обращение к нему доступно также из сети хоста.
    Сервисы (gitlab, OMV, облако и т.д.) настраиваются на использование LDAP сервера.
    Менять пароли пользователи могут с использованием LDAP Self Service Password.


    Пользователя при добавлении в систему предварительно нужно зарегистрировать, используя консоль, либо WEB-интерфейс. Я использую PHP LDAP Admin.


    При желании дать пользователям права на действия с ОС, возможно использовать PAM LDAP.


    Сеть


    Физическая организация


    Как видно на диаграмме развёртывания, NAS находится за роутером в локальной сети. В идеале, с целью повышения безопасности сети, неплохо бы изолировать его в DMZ с использованием второго роутера, но это не обязательно.


    Пользователь может обращаться к NAS как из сети Интернет, так и из локальной сети. Любое обращение затрагивает роутер.


    Т.к. система имеет несколько интерфейсов, к роутеру подключено более одного одновременно (в моём случае два) и организован их бондинг.


    Во-первых, интерфейсы в таком случае не простаивают без дела.
    Во-вторых, это повышает надёжность, а в некоторых режимах и пропускную способность.


    Логическая организация


    Как возможно видеть из диаграммы, в работе системы принимает участие роутер.


    В случае доступа из внешней сети, роутер организует проброс портов. Порты 80 и 443 служат для организации доступа к сервисам по HTTP и HTTPS соответственно. Порт 5022 пробрасывается на порт 22 NAS для доступа по SSH. В идеале лучше иметь некую дисциплину назначения номеров портов: например, порты 10001-10999 назначаются для доступа к сервисам хоста в NAS, порты 110001-11999 назначаются для доступа ко второму домашнему серверу и т.п..


    При доступе из Интернета нужно иметь возможность привязать несколько доменных имён к своему IP. Это реализуется разными способами, но я использую вариант с облачным DNS, предоставляющим DNS зону. В качестве такового, был применён ClouDNS.


    В случае доступа из локальной сети, роутер предоставляет DNS сервер. Если перенести DNS сервер с роутера на NAS, система будет полностью автономной. Но это не имеет особого смысла, т.к. без функционирующего роутера, который служит для организации локальной сети (в том числе, и подключения NAS в сеть) и связи с внешними сетями, нормально пользоваться NAS всё-равно не получится.


    У его DNS сервера должна быть возможность возвращать определённый IP, если имя попадает под регулярное выражение.


    Для NAS там есть две записи: ".*\.nas" и ".*\.NAS\.cloudns\.cc", где NAS — зарегистрированная в ClouDNS зона.


    В результате, независимо от того, есть ли Интернет, роутер перенаправит все обращения из локальной сети к доменам в зоне NAS.cloudns.cc на NAS.


    HTTP запрос, попав на порт NAS 80 или 443, перенаправляется на порт контейнера с nginx-reverse-proxy.


    Он возвращает пользователю подписанный сертификат для безопасного доступа по HTTPS. Затем, в зависимости от доменного имени, переадресует запрос контейнеру с нужной службой. Например, запрос на cloud.NAS.cloudns.cc будет перенаправлен контейнеру, в котором работает персональное облако.


    Есть два типа служб:


    • Службы, работающие в контейнерах. Их форнтэнд разделяет ту же сеть, что и nginx-reverse-proxy. Здесь перенаправление организуется напрямую.
    • Службы, работающие на хосте. Например, WEB-интерфейс OMV работает прямо на хосте, не в контейнере и недоступен напрямую из внешней сети по порту 443 (просто потому, что данный порт слушает nginx-reverse-proxy).

    В случае служб второго типа, перенаправление организуется через контейнер nginx-local, содержащий шаблоны доменных имён "железного" хоста.


    Процесс прохождения запроса внутри NAS показан на диаграмме ниже. Процесс обновления сертификата, указанный на диаграмме, описан далее.



    Код диаграммы
    @startuml
    actor Пользователь as user
    
    participant "cloudns" as cld
    participant "letsencrypt-dns" as led
    participant "Let's Encrypt" as le
    participant "nginx-reverse-proxy" as nrp
    participant "Приложение" as app
    participant "nginx-local" as ngl
    
    user -> cld : Получение IP от Cloudns\n[nas.nas.cloudns.cc]
    user <- cld : Возврат IP\n[1.2.3.4]
    user -> cld : Получение сертификата
    user <- cld : Сертификат
    
    group Периодическая генерация сертификата
      led -> le : Запрос генерации\nсертификата
      led <- le : Контрольное значение
      led -> cld : DNS challenge,\nиспользуя API
      led <- cld : Сертификат\nзарегистрирован
      led -> le : Проверить домен\nи получить сертификат
      cld <- le : Проверка принадлежности домена
      cld -> le : Успешно
      led <- le : Подписанный\ncертификат
    end
    
    user -> nrp : Запрос по IP [1.2.3.4]\nна порты 80, 443,\nс именем хоста [nas.nas.cloudns.cc]\nидёт на прокси
    nrp -> app : Запрос к приложению\nна виртуальном хосте [nas.*]\nпо межконтейнерной\nсети docker0
    
    group Запрос к приложению не в Docker контейнере
      app --> ngl : Проброс в сеть localhost
      ngl -> "Приложение на хосте" : Запрос
      ngl <- "Приложение на хосте" : Результат
      app <-- ngl : Возврат результата
    end
    
    nrp <- app : Результат
    
    user <- nrp : Возврат пользователю результата приложения
    @enduml

    Сертификат

    Периодически контейнер с letsencrypt-dns получает сертификат для группы доменов. Получение сертификата реализуется с использованием certbot. Перед получением сертификата, сервис Let's Encrypt производит проверку того, принадлежит ли домен тому, кто запрашивает на него сертификат.


    С случае с ClouDNS, это делается с использованием так называемого DNS challenge:


    • Генерируется случайная последовательность.
    • Последовательность вставляется в TXT запись.
    • Let's Encrypt проверяет, что такая последовательность действительно присутствует.

    Вставка в TXT запись может производиться вручную, а может с использованием API. Для того, чтобы унифицировать доступ к разным DNS провайдерам, существует библиотека и инструмент Lexicon.


    К сожалению, у ClouDNS существует минус: его API платное. С учётом того, сертификат я приделал не сразу, и мне не хотелось всё переделывать, я просто купил доступ, который стоит $42 за 2 года (да и зажимать сорок баксов, при совокупной цене NAS более $3000 было бы странно).


    При желании возможно найти нормальные сервисы с бесплатным API.


    Сетевые сервисы


    Инфраструктурные сервисы, касающиеся сети, которые требуются для функционирования и обслуживания:


    • Nginx-reverse-proxy является диспетчером, передающим сервису данные по его URL.
    • Lets-encrypt для обновления сертификатов.
    • Nginx, проксирующий запросы в сеть хоста из сети контейнеров.
    • Управление по SSH организовано с использованием OpenSSH.
    • DNS сервер, как уже было сказано, не будет входить в состав NAS. Для того, чтобы сделать NAS полностью автономным, он конечно не помешает. Но с учётом того, что NAS не нужен без сети, его возможно реализовать на роутере.
    • POP3/SMTP сервер, указанный на диаграмме, является внешним и нужен для посылки оповещений от NAS.

    Возможно использовать nginx-proxy-companion для получения сертификатов, но он у меня не заработал.


    Взаимодействие с источником питания


    В качестве ядра системы управления питанием был выбран демон NUT, который поддерживается плагином OMV и которому нет серьёзных универсальных альтернатив.


    Соответственно, источник бесперебойного питания Eaton был изначально выбран так, чтобы проблем в связке Linux+NUT с ним не возникало.


    Eaton-ы, в данном случае вообще очень хорошо поддерживаются. Единственный серьёзный его недостаток — это шум. Но он легко исправляется заменой вентилятора, что было описано в "железной" статье.


    Для того, чтобы NAS правильно взаимодействовал и ИБП требуется настроить реакции на события, которые описаны ниже.


    При достижении батареей ИБП предела срока службы, выполняется:


    • Сигнализация в WEB-интерфейсе. За это отвечает плагин и требование не обязательное.
    • Отправка сообщения на e-mail каждые 24 часа. Также реализуется через OMV.

    При отключении питающей сети на время более 1 минуты, выполняется:


    • Сигнализация в WEB-интерфейсе.
    • Отправка сообщения по e-mail.

    При понижении заряда батареи ниже критического, выполняется:


    • Отправка сообщения на e-mail.
    • Завершение работы системы.

    Средства защиты от НСД


    Здесь приведены только общие меры безопасности, касающиеся именно NAS:


    • Все пользователи авторизуются: анонимного доступа нет. В дальнейшем от такой схемы возможно несколько отступить. Ссылки на файлы в облаке могут быть предоставлены сторонними пользователями.
    • Реализовано полнодисковое шифрование. В том числе, шифруется корневая файловая система.
    • Установлена парольная защита на системные установки посредством EFI.
    • Система доверенной загрузки. Является дополнительным средством контроля аутентичности загрузчика.
    • Возможна двуфакторная аутентификация в виде токена, но это пока не реализуется.
    • Используется файрволл.
    • В качестве дополнительной меры защиты от брутфорса возможно использовать fail2ban.
    • Внедрение системы мандатного контроля доступа также повысит сложность удалённого взлома и может частично нивелировать его последствия.

    Средства повышения надёжности


    Для того, чтобы понизить вероятность отказа системы, используются:


    • Оповещения по e-mail (как удалённые, так и локальные) обо всём: выключение питания, вскрытие, проблемы SMART.
    • Мониторинг SMART.
    • Изоляция приложений.
    • Средства дополнительного резервирования. Например, репликация данных в облачное хранилище.

    В случае достижения параметров SMART какого-либо диска критических значений, выполняется:


    • Сигнализация в WEB интерфейсе.
    • Отправка сообщения на e-mail.
    • При возможности, вывод диска из пула.

    Управление системой


    Управление ПО системы осуществляется через:


    • WEB интерфейс доступный через HTTPS.
    • SSH. У меня есть привычка работать через консоль, и SSH крайне желателен.
    • IPMI: управление системой, при незагруженной ОС.

    WEB интерфейс


    Система предоставляет основные сервисы, доступные по HTTPS (в зоне NAS.cloudns.cc из Интернет, либо в зоне nas в локальной сети) :



    Дополнительные подсистемы будут добавлять свои интерфейсы, которые описываются таким же образом.


    Организация прикладных систем


    Предварительный состав систем:


    • Система работы с кодом.
    • Резервное копирование.
    • Облачное хранилище.
    • Загрузка содержимого из Интернет.
    • Медиасистема.

    Каждая из систем будет описана отдельно.


    Служебные компоненты


    СУБД


    Т.к. СУБД требуется для большинства систем, на начальном этапе было желание выбрать одну СУБД, на основе возможностей и требований подсистем, и запустить в единственном экземпляре. Но в итоге, выяснилось, что использовать несколько СУБД, в зависимости от реализации подсистемы, проще и не особенно затратно по ресурсам. На этом варианте я пока остановился.


    Система дополнительного резервирования


    Задачи данной системы:


    • Дублирование конфигурации ОС и систем. Конфигурация резервируется в пул данных.
    • Сохранение промежуточных состояний как корневого пула, так и пула данных.

    Состав:


    • Плагин OMV backup. Отвечает за резервирование конфигурации ОС.
    • zfs-auto-snapshot. Отвечает за сохранение промежуточных состояний пулов, используя ZFS снимки.

    Что не сделано


    • Это статья, в которой описано конкретное проектное решение, а не проектная документация, потому "проектирование" здесь выполнено относительно неформально. Тем не менее, этого достаточно, чтобы реализовать описанную систему. Реализация будет показана далее.
    • По той же причине не построена модель угроз. В данном случае, проект для личного пользования, и модель угроз подразумевается неявно. Желающим построить формальную модель, могу порекомендовать документ ФСТЭК, а также ознакомление с Microsoft SDL. Если будет много желающих, могу написать отдельную статью по построению модели угроз для данной системы.
    • Многие моменты оставлены до этапа реализации, а также отражены не все особенности системы безопасности.
    • В случае длительного отключения питания (более 40 минут), систему придётся включать вручную, и я на это несколько раз попадал. Чтобы это преодолеть, есть возможность вывести в Интернет интерфейс к IPMI, но решать делать так или нет, за того, кто делает NAS по такой схеме, я не буду (для справки в IME уже находили уязвимости, а также развивается утилита по зачистке IME).
    Share post

    Similar posts

    Comments 16

      0
      Чтобы включать через инет достаточно Wake on LAN, чуть-чуть шаманства на роутере, чтобы входящий пакет транслировался в широковещательный и всё. Клиенты есть на все платформы, а так же онлайн сервисы для формирования magic-packet.

      Зачем под систему SSD, если всё реально запускается и работает из контейнеров на HDD? — выкинутые деньги.
        0
        • Дело не в том, чтобы просто включать, а в том, чтобы вводить ключ для расшифрования дисков. Тут WoL уже недостаточно. Если бы этого не требовалось, даже WoL был бы не нужен: достаточно было бы установить в управлении питанием восстановление к прежнему состоянию, и система запускалась бы при появлении питания автоматически (ИБП будет выжидать некоторое время перед подачей питания, чтобы определить, что оно стабильно).
        • Во-первых, размещать систему управляющую хранилищем, на дисках хранилища нельзя (контейнеры с этой точки зрения не являются компонентами ОС, это данные), т.е. под систему нужен отдельный носитель. Во-вторых SSD нужен прежде всего для выноса на него SLOG и кэшей, а так как на нём остаётся достаточно места, туда возможно разместить систему, не устанавливая отдельный носитель под неё.
          +1
          У меня hp microserver gen8 с ILO (под него на сервере отдельный интерфейс).
          При необходимости я по vpn подключаюсь к роутеру, оттуда web морду ilo и оттуда уже получаю доступ в окошке к «экрану» — можно даже в биос попасть.
            0
            Примерно тоже самое обеспечивает IME (хотя, возможно, что в HP и есть IME). Просто в конкретном варианте WEB морды консоль на Java, что неудобно. По VPN подключаться, в принципе, — вариант.
            +1
            Дело не в том, чтобы просто включать, а в том, чтобы вводить ключ для расшифрования дисков.

            Почему вы не рассматриваете ввод ключа шифрования через SSH? Включите в initramfs SSH-сервер, dropbear или OpenSSH, и вводите пароль. Модули для этого есть и для initramfs-tools (Debian, Ubuntu), и dracut (CentOS, Fedora).


            Если вы опасаетесь за сохранность данных только когда сервер выключен, то вы можете хранить ключ шифрования в Trusted Platform Module (TPM). Вы упомянули доверенную загрузку, но, видимо, ошиблись — имели в виду Secure Boot, а не Trusted Boot.

              0

              Про SSH.


              Да я просто не думал о таком варианте. За полезную идею большое спасибо. Сейчас посмотрел, это в Debian уже даже кто-то делал, и всё описано.
              Надо подумать, какие с этим могут быть проблемы, но мне кажется, что это намного безопаснее, чем открывать доступ снаружи к IPMI и проще (ну и удобнее), чем поднимать VPN на роутере.


              Про доверенную загрузку.


              В принципе, использование Secure Boot даёт некоторое повышение уровня безопасности: пропатчить ядро на диске так, чтобы это прошло незамеченным, с ним проблематично для некоторых классов нарушителей.
              Но я имел ввиду именно доверенную загрузку, то что в моём случае реализовано в виде Intel TXT.
              Если вы посмотрите спецификацию к плате, то увидите, что TPM и TXT поддерживаются.
              Другое дело, что на практике я пока это не использую и TPM нет.
              Ну и могу ли я реально хранить ключ в TPM, снова зависит от модели нарушителя.

                0
                Доверенная загрузка сама по себе ничего особо не делает. Статичный корень доверия вообще ничего не делает, Intel TXT (в виде tboot) может максимум проверить политику загрузки.
                  0
                  К слову, вам нужен будет еще и процессор с поддержкой TXT. В i3 и части i5 его нет.
                  0
                  Да, про tboot я почитал, и не особенно увидел, как в моём случае его применить. Но я так понял, в комбинации с TPM, TXT может проверять подпись ядра. Возможно я ошибаюсь, тогда поправьте.
                    +1
                    TXT не работает вне TPM. Для любого способа доверенной загрузки необходим TPM, в этом и суть доверенной загрузки — получить состояние загруженных компонентов в регистрах TPM PCR. Доверенная загрузка, в общем случае, ничего не проверяет самостоятельно и ничего не запрещает исполнять, а нужна для того, чтобы предоставить доступ к каким-либо секретам внутри TPM, или запретить его.

                    Прочитайте мою статью про взлом автоматов Namco System ES1, я немного писал про доверенную загрузку: habr.com/post/304014
                      0
                      Ok, спасибо, почитаю. Буду ещё разбираться с данной темой.
              0
              TPM должен решать проблему вводу ключа. У меня тоже е3. Использовал LUKS
            0
            А выставить в биосе автозапуск при появлении питания нельзя?
              0

              См. комментарий выше. Запустится, но остановится на вводе ключа. Предупреждая вопрос:


              • Возможно вводить только ключи расшифрования томов, и тогда система загрузится, но это увеличивает "поверхность атаки".
              • Возможно хранить ключ вместе с системой, но это имеет мало смысла.
              0
              В случае длительного отключения питания (более 40 минут), систему придётся включать вручную,

              Так UPS для этого придумали. Из самого бюджетного — Inelt Monolith, несколько промышленных гелевых аккумуляторов и можно получить 1-2 часа и более.


              Чтобы это преодолеть, есть возможность вывести в Интернет интерфейс к IPMI,

              apt install dropbear-initramfs

              Only users with full accounts can post comments. Log in, please.