Начало


Популярность современных UTM-решений, связана в первую очередь с их многофункциональностью. Возможность быстро решить все ИТ-задачи компании, да еще и из одного веб-интерфейса привлекает многих сисадминов.

Наше решение, Интернет Контроль Сервер, также относится к классу UTM-продуктов, объединяя в себе функции защиты сети, управления Интернет-подключениями, контентной фильтрации и многие другие.

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

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

В этом случае, сисадмин собирает свой шлюз из “кирпичиков”-компонентов, устанавливая только нужные ему модули. Весь инструментарий находится в облаке разработчика, а пользователь скачивает и устанавливает необходимые пакеты. Этот принцип стал основополагающим для наших будущих разработок.

Исторически сложившаяся экосистема FreeBSD нас устраивала и была достаточно хорошо изучена. В качестве наиболее подходящего метода дистрибуции пакетов мы выбрали традиционную утилиту установки пакетов во FreeBSD — pkg. В нашем облаке собирается репозиторий, а на клиенте прописывается доступ к нему в традиционном конфиге pkg.

Что мы планировали сделать


Система должна представлять собой конструктор в виде ядра, на которое нанизываются компоненты. Пользователь получает дистрибутив, в который входят только минимально необходимые плагины (router, fierwall и т.д.). Остальное устанавливается по мере необходимости.

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

  • система — модифицированное ядро FreeBSD
  • core — специальный пакет с настройками продукта, являющийся родительской зависимостью для всех плагинов
  • плагины — каждый из них — это собранный пакет, который штатным образом устанавливается утилитой pkg

Структура плагинов


Как уже говорилось, плагин — это обычный пакет. Он может быть установлен утилитой pkg.
Для того, чтобы поддерживать обратную совместимость, решили, что новая мажорная версия плагина будет отдельным пакетом, не связанным с предыдущей мажорной версией. Например plugin-v1 и plugin-v2. Причина — у них могут быть совершенно разные зависимости, возможно даже противоречащие друг другу.

У минорной версии просто меняется номер версии пакета, тут все как обычно.

Работа с плагинами


Для того, чтобы система работала так, как нам нужно, была создана утилита-надстройка над pkg.

Основным инструментом для работы будут команды pkg query и pkg rquery.

Первая собирает информацию по установленным в системе плагинам, вторая обращается к репозиторию.

Для того, чтобы утилита контролировала корректность выполнения команд в системе, выполнение каждой команды проверяется на код возврата. Если получен код возврата 0, значит команда выполнилась, если что-то иное, значит возникла ошибка. Таким образом можно отследить, к примеру, проблемы с сетевым соединением.

Здесь возник интересный нюанс. Если выполнить например поиск всех пакетов по шаблону:



то в случае, если ни один установленный пакет не попадает под условие шаблона, возвращается ошибка 69 без сообщения об ошибке. Разработчики утилиты посчитали, что если поиск ничего не вернул, то это ненормальное поведение. Ну, ОК. Пришлось обрабатывать такой случай специальным образом.

Проблемы обновления


Дальше начинаются проблемы с версионностью при обновлении плагинов.

Во-первых, утилита pkg при выполнении команды pkg upgrade <pkg_name> также обновляет ВСЕ прямые зависимости пакета, такое поведение заложено разработчиками. Но в нашем случае это включает в себя обновление и core, если для него вышла минорная версия, что нежелательно, поскольку core меняет системные параметры, а также требует перезагрузки системы после обновления.

То есть, если у нас в системе установлены 2 пакета — pkg-1 и pkg-2, и в зависимостях pkg-1 указан pkg-2, то если мы выполним команду pkg upgrade pkg-1, то обновится также и pkg-2.

Пойдем другим путем.

Построим дерево зависимостей пакета вверх и вниз.
Находим имена всех пакетов, от которых зависит наш пакет:

pkg rquery %rn <pkg_name>

Теперь всех пакетов, которые зависят от нашего пакета:

pkg rquery %dn <pkg_name>

Удалим все зависимые от пакета сущности. Далее начнем удалять сущности, от которых зависит наш пакет вверх по дереву до тех пор, пока не окажемся в core (его удалять не будем конечно). Теперь можно восстановить дерево, установив последние минорные версии всех пакетов в нем.



Например, на рисунке выше мы видим, что пакет ics-plugin-a-v1 зависит от плагина ics-plugin-b-v1. Если нам нужно обновить пакет до версии ics-plugin-v2 то это повлечет и обновление пакета ics-plugin-b-v1, для которого существуют 2 мажорные версии — ics-plugin-b-v2 и ics-plugin-b-v3. При этом ни одна из них не поддерживает плагин ics-plugin-c-v1. То есть, при обновлении сначала будет установлен пакет ics-plugin-b-v2 или -v3, затем ics-plugin-a-v1, а ics-plugin-c будет удален и установлен не будет.

Кроме того мажорная версия может быть у core, в этом случае весь состав плагинов должен быть обновлен для соответствия.



Для установки пакета ics-plugin-a, который зависит от ics-core-v2 нужно обновить ics-core, после чего установятся только пакеты мажорных версий, которые зависят от ics-core-v2.

Резервное копирование базы


При работе с репозиторием возможна ситуация, когда во время обновления пропадет связь (возникает системная ошибка код 70 или 3). Кроме того, для того, чтобы корректно удалить плагин, системе необходима действующая база pkg в системе. При выполнении команды pkg update, если нет связи, база сообщает об ошибке и даже локально не выполняет свои функции пока апдейт не выполнится корректно.

Чтобы избежать таких ситуаций, воспользуемся утилитой pkg backup. Перед любой операцией, в процессе которой есть вероятность не получить нужный результат, сохраняем базу:

pkg backup -d <backup_dir>

Если операция завершилась некорректно, возвращаем базу на место:

pkg backup -r <backup_dir>

Ядро


Тут пока все достаточно просто. Если вышло обновление для ядра, то:

  1. скачиваем новый образ ядра в архиве
  2. создаем новый датасет в zfs
  3. монтируем датасет в систему
  4. распаковываем образ
  5. устанавливаем специальный пакет с нужными опциями ядра для нормальной работы
  6. прописываем новый образ как загрузочный
  7. ???

Profit?


Пока еще нет.

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

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

Что делать?

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

Затем наша утилита сгенерирует файл конфига репозитория с указанием пути до папки с распакованным архивом.

Для FreeBSD это будет файл <repo_name>.conf в папке /usr/local/etc/repos или /etc/repos. Здесь стоит обратить внимание, что путь пишется следующим образом: url: “file:///path_to_repo” (3 слэша!)

Сохраняем данные об установленных плагинах и проверяем их совместимость с будущей версией ядра (если есть несовместимые, сообщим об этом пользователю).

Вот теперь можно перезагружаться.

Последнее


После обновления системы утилите pkg требуется инициализация (bootstrap). Поэтому если выполнить любую команду, возникнет запрос на нее. В нашем случае, утилита-обвязка не поймет, что он нее хотят и посчитает что операция выполнена некорректно.

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

pkg -y

Pkg делает бутстрап, и дальше можно работать в штатном режиме.

Итого


Вот так мы построили наш репозиторий. Пока это прототип, и в будущем он, скорее всего, будет изменяться и усложняться, но проектная база заложена и останется неизменной.

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

Триал-период, бесплатная версия на 9 пользователей, демо-онлайн и отзывчивая техподдержка.

Следите за новостями и оставайтесь с нами!