Централизованный фаервол Rambler Group
Зачем мы его создали?
Долгое время мы в Rambler Group использовали трёхуровневую архитектуру сети ЦОД, в которой каждый проект или инфраструктурный компонент жил в выделенном влане. Весь трафик – как между вланами, так и между дата-центрами – шел через оборудование edge-уровня.
Edge-оборудование – это дорогие маршрутизаторы, способные выполнять множество различных функций, соответственно, порты на нем тоже дорогие. Со временем рос горизонтальный трафик (machine-to-machine – например, репликация базы данных, запросы в различные сервисы и т.д.), и в какой-то момент встал вопрос утилизации портов на пограничных маршрутизаторах.
Одна из основных функций таких устройств – фильтрация трафика. В связи с этим управлять ACL также стало сложнее: приходилось делать все вручную, плюс исполнение задачи смежным отделом тоже занимало время. Дополнительное время уходило и на настройку портов на уровне Access. Нужно было выполнять не только ручные действия тех же NOC, но и выявлять потенциальные проблемы безопасности, ведь хосты меняют свое расположение, соответственно, могут получить нелегитимный доступ в чужие вланы.
Пришло время что-то менять, и на помощь пришли сети Клоза или, как их ещё называют, IP-фабрики.
Несмотря на внешнюю схожесть, принципиальное отличие этой архитектуры от предыдущей заключается в том, что каждое устройство, включая leaf-уровень, выполняет роль маршрутизатора, а шлюзом для сервера по умолчанию является Top-of-Rack. Таким образом, горизонтальный трафик между любыми хостами различных проектов теперь может проходить через уровень spine, а не через edge.
Кроме того, на том же уровне spine мы можем соединить ЦОДы друг с другом, а на пути между двумя любыми серверами теперь лежат не более четырех сетевых устройств. Edge-оборудование в данной архитектуре нужно лишь для подключения операторов связи и пропускает только вертикальный трафик (В интернет и ИЗ него).
Главная особенность сети Клоза – в ней отсутствует место, где можно фильтровать трафик между хостами. Поэтому выполнять эту функцию необходимо непосредственно на сервере. Централизованный фаервол – это программа, которая занимается фильтрацией трафика на самом хосте, принимающем трафик.
Требования
Необходимость внедрения централизованного фаервола была продиктована сразу несколькими факторами:
- конечными потребителями и
- существующей инфраструктурой.
Поэтому требования к приложению были следующими:
- Фаервол должен уметь работать и создавать правила на хосте и виртуалках. Причем список правил не должен отличаться от того окружения, где запущен фаервол. То есть правила идентичны.
- Агент фаервола при установке не должен блокировать весь трафик. То есть должен существовать набор дефолтных правил, который предоставляется сразу вместе с агентом – ssh, порты экспортеров (у нас используется Prometheus), доступы для различных сканеров безопасников и так далее.
- Агент может работать без сервера, используя только файлы-правил.
- Агент не принимает никаких решений, его задача – применить список правил из указанных источников.
- Вся логика работает на сервере.
- Запрещающая политика по умолчанию: «что не разрешено, то запрещено».
Облако Rambler Group достаточно динамично: виртуалки создаются и удаляются, серверы устанавливаются и демонтируются. Поэтому мы не используем доступы «точка-точка», в нашей инфраструктуре есть понятие «хостгруппа».
Хостгруппа – это разметка группы серверов, которая однозначно описывает их роль. Например, news-prod-coolstream-blue.
Отсюда вытекает еще одно требование: пользователи должны оперировать высокоуровневыми сущностями – хостгруппами, проектами и так далее.
Идея и реализация
Туллинг
Централизованный фаервол – большая и сложная штука, которая требует настройки агента. Поиск проблем может занять больше пяти минут, поэтому вместе с агентом и сервером появилась тулза, которая рассказывает пользователю, правильно ли настроен агент и что нужно исправить. Например, важное требование к хосту – существование в хостгруппе или PTR записи в DNS. Про все это и многое другое расскажет тулза (ее функции описаны ниже).
Единый фаервол
Мы стараемся придерживаться следующего принципа: приложение, которое настраивает фаервол на хосте, должно быть единственным, чтобы не получить «моргающих правил». То есть если на сервере уже есть свое средство настройки (например, если правила настраиваются другим агентом), то нашему приложению там не место. Ну, и обратное условие тоже действует: если есть наш агент фаервола, то правила настраивает только он – здесь принцип тотального контроля.
Фаервол это не iptables
Как вы знаете, iptables – это всего лишь утилита командной строки для работы с netfilter. Чтобы переносить фаервол на разные платформы (Windows, BSD-системы), агент и сервер работают со своей моделью. Об этом более подробнее чуть ниже, в разделе «Архитектура».
Агент не пытается решить логические ошибки
Как было сказано выше, агент не принимает никаких решений. Если вы хотите закрыть порт 443, на котором уже работает ваш HTTP-сервер, – нет проблем, закрывайте!
Архитектура
В архитектуре такого приложения сложно придумать что-то новое.
- У нас есть агент, он настраивает правила на хосте.
- У нас есть сервер, он отдает user-defined-правила.
- У нас есть библиотека и тулза.
- У нас есть высокоуровневый резолвер – он меняет ip-адреса на хостгруппы/проекты и наоборот. Подробнее обо всём этом ниже.
В Rambler Group много хостов и еще больше виртуалок, и все они так или иначе принадлежат какой-нибудь сущности:
- VLAN
- Сеть
- Проект
- Хостгруппа.
Последняя описывает принадлежность хоста к проекту и его роль. Например, news-prod-backend-api, где: news – проект; prod – его env, в данном случае это production; backend – роль; api – произвольный пользовательский тег.
Резолвер
Фаервол работает на сетевом и/или транспортном уровне, а хостгруппы и проекты – это высокоуровневые сущности. Поэтому чтобы их «подружить» и понять, кому принадлежит хост (или виртуалка), нужно получить список адресов – этот компонент мы назвали «High Level Resolver». Он меняет высокоуровневые имена на набор адресов (в понятиях резолвера это «contained» – «состоит») и, наоборот, адрес на имя сущности («contains» – «содержит»).
Библиотека – Core
Для унификации и объединения некоторых компонентов появилась библиотека, она же – Core. Это модель данных со своими контроллерами и вьюхами, которые позволяют ее наполнять и читать. Такой подход в разы упрощает код серверной части и агента, а также помогает сравнить текущие правила на хосте с правилами, полученными с сервера.
Источников для наполнения модели у нас несколько:
- файлы правил (два разных вида: упрощенные и полностью описывающие правило)
- правила, полученные с сервера
- правила, полученные с самого хоста.
Агент
Агент – это не обвязка над iptables, а самостоятельное приложение, которое работает c использованием враппера над Си-библиотеками libiptc, libxtables. Сам агент не принимает никаких решений, а только настраивает правила на хосте.
Роль агента минимальная: прочитать файлы правил (в том числе дефолтные), получить данные с сервера (если он настроен на удаленную работу), слить правила в один набор, проверить, отличаются ли они от прошлого состояния, и, если отличаются, – применить.
Другая важная роль агента – не превратить хост в тыкву при первоначальной установке или при получении невалидного ответа от сервера. Чтобы избежать этого, мы по умолчанию поставляем в пакете набор правил, например, таких как ssh, доступы для мониторинга и так далее. В случае если агент фаервола получает не 200-й код ответа, агент не будет пытаться выполнять какие-либо действия и оставит предыдущее состояние. Но он не защищает от логических ошибок, если запретить доступ по 80, 443 портам, то агент все равно выполнит свою работу, даже при запущенном веб-сервисе на хосте.
Тулза
Тулза предназначена для системных администраторов и разработчиков, сопровождающих проект. Цель невероятно проста: в «один клик» получить все данные о работе агента. Утилита способна рассказать о том:
- запущен ли демон агента
- существует ли PTR-запись для хоста
- в каких хостгруппах состоит хост
- были ли изменены конфиги пользователем.
Этой информации вполне достаточно, чтобы диагностировать проблемы на раннем этапе.
Сервер
Сервер – это приложение + база данных. Всю логику работы выполняет именно он. Важная особенность сервера – он не хранит в себе IP-адреса. Сервер работает только с верхнеуровневыми объектами – именами hostgroup, project и т.д.
Правила в базе лежат в таком виде: Action: Accept Src: project-B, project-C Dst: Project-B Proto: tcp Ports: 80, 443.
Как сервер понимает, какие правила и кому отдавать? Из требований следует, что правила должны быть идентичны вне зависимости от того, где запущен агент, будь то хост или виртуалка.
Запрос от агента приходит к серверу всегда с одним значением – IP-адресом. Важно помнить, что каждый агент просит правила для самого себя, то есть он – destination.
Для простоты понимания работы сервера рассмотрим процесс получения правил хоста, принадлежащий какому-либо проекту.
Первым в работу вступает резолвер. Его задача поменять IP-адрес на имя хоста, а потом узнать, в какой сущности содержится этот хост. HL-Resolver отвечает серверу, что хост содержится в проекте А. HL-Resolver обращается к Datasource (про который мы раньше не упоминали). Datasource – это некая база знаний компании о серверах, проектах, хостгруппах и т.д.
Далее сервер ищет все правила для проекта с destination=имя проекта. Так как в базе у нас не содержатся адреса, нужно разименовать имена проектов в хостенеймы, а затем в адреса, поэтому запрос снова отправляется в Datasource через резолвер. HL-Resoler возвращает список адресов, после чего агент получает готовый список правил.
Если наш destination – это хост с виртуалками, то такой же сценарий выполняется не только для хоста, но и для каждой виртуалки на нем.
Ниже схема, которая показывает простой случай: хост (железка или виртуалка) получает правила для хоста в Project-A.
Релизы
Не трудно догадаться, что имея централизованное управление фаерволом, можно также централизованно все сломать. Поэтому релизы для агента и сервера осуществляются поэтапно.
Для сервера – Blue-Green + A/B-тестирование
Blue-Green – это стратегия деплоя, которая подразумевает наличие двух групп хостов. А переключение идет порциями 1,3,5,10...100%. поэтому если возникнут проблемы с новым релизом, пострадает только небольшая часть сервисов.
Для агента – Canary
Canary (или канареечный деплой) чем-то похож на A/B-тестирование. Мы обновляем только часть агентов и смотрим на метрики. Если все хорошо, берем еще кусочек побольше и так до 100%.
Заключение
В итоге мы сделали self-service для системных инженеров, который позволяет управлять сетевыми доступами из одной точки. Таким образом, мы:
- избавили системных инженеров от рутинных задач
- получили возможность аудита доступов с понятным HTTP-API
- исключили возможность получения нелегитимных доступов
- и конечно же получили большой опыт разработки такого приложения.