Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи?

Написать
Войти
Дайджесты
Иллюстрация к статье о фильтрации сетевого трафика eBPF в Netfence

Фильтрация сетевого трафика на eBPF: архитектура хостового демона Netfence

Демон eBPF-фильтрации Netfence внедряет сетевые правила непосредственно в cgroups и сетевые интерфейсы узлов. Архитектура со встроенным DNS-сервером и автоматическим резолвингом доменов обеспечивает надежную изоляцию контейнеров и блокирует доступ к метаданным облака с минимальными задержками.

Фильтрация сетевого трафика на eBPF: архитектура хостового демона Netfence

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

Открытый проект Netfence предлагает альтернативный подход к обеспечению сетевой безопасности на уровне виртуальных машин и контейнерных узлов. Инструмент выполнен в виде системного демона Linux, который управляет жизненным циклом eBPF-программ (Extended Berkeley Packet Filter — подсистема ядра Linux для выполнения изолированного кода в контексте сетевого стека). Вместо перехвата и обработки пользовательского трафика в пространствах пользователя Netfence динамически внедряет правила фильтрации прямо в точки прикрепления ядра.

Зачем нужна фильтрация сетевого трафика на уровне ядра

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

Netfence решает эту проблему за счет выполнения проверок внутри ядра с помощью eBPF. Программы фильтрации проверяют входящие и исходящие пакеты еще до их поступления в основной сетевой стек или сразу при попытке процесса установить сетевое соединение. Если IP-адрес назначения отсутствует в списке разрешенных правил, пакет отбрасывается на месте. При этом теплое сетевое обращение по разрешенному правилу выполняет проверку в eBPF-карте с минимальными задержками, практически не отличающимися от стандартного установления сокета.

Два уровня фильтрации: сравнение возможностей TC и cgroups

Архитектура Netfence поддерживает два фундаментальных способа прикрепления eBPF-программ к ресурсам системы, каждый из которых предназначен для решения специфических задач безопасности и изоляции:

  1. Прикрепление к сетевому интерфейсу (Traffic Control / TC): eBPF-программа связывается с виртуальным или физическим сетевым интерфейсом (veth, eth, tap). Этот уровень работает непосредственно с сетевыми пакетами на этапе их поступления или отправки устройством. Главное преимущество TC-фильтрации заключается в возможности мгновенного разрыва уже установленных TCP-соединений при изменении правил политики, а также в гарантированном перехвате любого сетевого трафика.
  2. Прикрепление к контрольным группам процессов (cgroups): eBPF-программа подключается к хукам системных вызовов сокета (connect и sendmsg) конкретной группы процессов. Это позволяет изолировать отдельный контейнер или рабочую группу без вмешательства в настройку сетевых устройств хоста.

При проектировании защиты важно учитывать архитектурное ограничение cgroup-хуков: процессы, обладающие привилегией CAP_NET_RAW, способны генерировать необработанные сырые пакеты в обход проверок сокетного уровня. По этой причине для контейнеров с повышенными привилегиями или доступом к сырым сокетам разработчики Netfence рекомендуют использовать исключительно TC-фильтрацию на виртуальном интерфейсе.

Режимы сетевой политики и блокировка облачных метаданных

Демон Netfence поддерживает четыре базовых режима работы сетевых политик для каждого подключенного ресурса:

  • disabled: фильтрация отключена, весь трафик проходит без ограничений;
  • allowlist: разрешены только явным образом указанные сетевые диапазоны CIDR и домены;
  • denylist: разрешен весь трафик, за исключением заблокированных адресов;
  • block-all: полный запрет любых сетевых взаимодействий.

Особое внимание в Netfence уделено защите сервисов метаданных облачных провайдеров. В облачных средах (AWS, GCP, Yandex Cloud) по адресу 169.254.169.254 располагается сервис метаданных экземпляра, отдающий секретные токены доступа и конфигурацию узла. В режиме allowlist диапазон link-local 169.254.0.0/16 не входит в автоматический список исключений. По умолчанию доступ к 169.254.169.254 полностью заблокирован, пока оператор не добавит явное целевое правило 169.254.169.254/32. Это защищает инфраструктуру от утечек учетных данных при компрометации приложений.

Архитектура встроенного DNS-сервера и динамическое обновление правил

Одной из наиболее сложных проблем при создании сетевых белых списков является работа с внешними сервисами, использующими динамические IP-адреса и CDN. Простая запись статических IP-адресов быстро утрачивает актуальность.

Netfence содержит встроенный асинхронный DNS-сервер, выделяющий изолированный IP-адрес и порт резолвера для каждого прикрепленного контейнера или виртуальной машины. Взаимодействие устроено по следующей схеме:

  1. Рабочая нагрузка отправляет DNS-запрос к назначенному локальному эндпоинту Netfence.
  2. DNS-сервер проверяет имя доменного имени по списку разрешенных правил (поддерживается сопоставление поддоменов с учетом приоритета точных совпадений).
  3. Если домен разрешен, Netfence выполняет запрос к вышестоящему upstream-серверу по UDP или TCP.
  4. Полученные в ответе IP-адреса автоматически заносятся в eBPF-карту точных адресов (exact-host hash map) с учетом полученного TTL ответа.
  5. Только после успешного обновления eBPF-карты DNS-ответ возвращается клиенту.

Такой подход гарантирует, что к моменту, когда приложение получит IP-адрес целевого сервиса, ядро Linux уже будет готово пропустить трафик к этому адресу. Если из-за исчерпания памяти или лимитов занесение адреса в карту невозможно, DNS-сервер возвращает ошибку SERVFAIL, предотвращая отправку непроверенных адресов приложению.

Ограничения производительности, LRU-кеширование и защита от перегрузок

Для предотвращения атак типа «отказ в обслуживании» и исчерпания ресурсов ядра Netfence реализует жесткое нормирование памяти и контролируемый churn budget (бюджет динамических изменений):

  • Лимиты exact-карт: по умолчанию на каждый ресурс выделяется емкость до 4096 IP-адресов и 1024 отслеживаемых доменов.
  • LRU-вытеснение: при заполнении карт устаревшие записи с истекшим TTL или наименее используемые динамические адреса вытесняются алгоритмом LRU (Least Recently Used).
  • Скользящий бюджет изменений: система ограничивает максимальное количество операций обновления карт в минуту. При превышении порога новые доменные запросы временно отклоняются с кодом SERVFAIL.

При этом защищенные правила CIDR, установленные администратором, хранятся в независимых LPM-картах (Longest Prefix Match) и никогда не подвергаются вытеснению LRU-алгоритмом.

Регламент развертывания и пошаговый чеклист безопасности

При практическом внедрении Netfence рекомендуются следующие шаги в инфраструктуре:

  1. Запуск демона: запустите системный процесс демона с указанием конфигурационного файла:
    netfenced start --config /etc/netfence/config.yaml
    
  2. Проверка статуса: убедитесь в корректности инициализации eBPF-карт:
    netfenced status
    
  3. Прикрепление к интерфейсу или cgroup: подключайте фильтрацию к целевым виртуальным машинам или контейнерам с указанием метаданных:
    netfenced attach --interface veth123 --direction ingress --metadata vm_id=abc
    netfenced attach --cgroup /sys/fs/cgroup/docker/xyz --metadata container_id=xyz
    
  4. Конфигурация DNS в контейнере: настройте файл /etc/resolv.conf внутри рабочей нагрузки на выданный IP-адрес локального резолвера Netfence.
  5. Проверка списка ресурсов: убедитесь в наличии активных подключений через CLI:
    netfenced list
    
  6. Отключение при необходимости: отсоединяйте фильтры по идентификатору подключения:
    netfenced detach --id <attachment-id>
    

Подробная документация по настройке gRPC-управления и интеграции доступна в официальной документации Netfence. Перед выводом в промышленную эксплуатацию обязательно проведите нагрузочное тестирование и убедитесь в отсутствии конфликтов с имеющимися CNI-плагинами.