Фильтрация сетевого трафика на eBPF: архитектура хостового демона Netfence
В современной облачной инфраструктуре организация сетевой изоляции виртуальных машин и контейнерных нагрузок традиционно сопровождается компромиссом между гибкостью управления и накладными расходами. Использование пользовательских прокси-серверов или проксирование через L7-архитектуры требует выделения ресурсов и создает дополнительную задержку при передаче пакетов. В свою очередь, создание статических правил на уровне фаервола ОС усложняет динамическое управление доступом к микросервисам и внешним API, когда сетевые адреса целевых ресурсов постоянно меняются.
Открытый проект Netfence предлагает альтернативный подход к обеспечению сетевой безопасности на уровне виртуальных машин и контейнерных узлов. Инструмент выполнен в виде системного демона Linux, который управляет жизненным циклом eBPF-программ (Extended Berkeley Packet Filter — подсистема ядра Linux для выполнения изолированного кода в контексте сетевого стека). Вместо перехвата и обработки пользовательского трафика в пространствах пользователя Netfence динамически внедряет правила фильтрации прямо в точки прикрепления ядра.
Зачем нужна фильтрация сетевого трафика на уровне ядра
Традиционные архитектуры сетевой безопасности в контейнерных средах часто полагаются на боковые прокси-контейнеры (sidecar proxy) или централизованные сервисы маршрутизации. Такой подход упрощает отслеживание протоколов прикладного уровня, однако создает ощутимые накладные расходы на контекстные переключения между пространством ядра и пространством пользователя при каждом сетевом запросе.
Netfence решает эту проблему за счет выполнения проверок внутри ядра с помощью eBPF. Программы фильтрации проверяют входящие и исходящие пакеты еще до их поступления в основной сетевой стек или сразу при попытке процесса установить сетевое соединение. Если IP-адрес назначения отсутствует в списке разрешенных правил, пакет отбрасывается на месте. При этом теплое сетевое обращение по разрешенному правилу выполняет проверку в eBPF-карте с минимальными задержками, практически не отличающимися от стандартного установления сокета.
Два уровня фильтрации: сравнение возможностей TC и cgroups
Архитектура Netfence поддерживает два фундаментальных способа прикрепления eBPF-программ к ресурсам системы, каждый из которых предназначен для решения специфических задач безопасности и изоляции:
- Прикрепление к сетевому интерфейсу (Traffic Control / TC): eBPF-программа связывается с виртуальным или физическим сетевым интерфейсом (veth, eth, tap). Этот уровень работает непосредственно с сетевыми пакетами на этапе их поступления или отправки устройством. Главное преимущество TC-фильтрации заключается в возможности мгновенного разрыва уже установленных TCP-соединений при изменении правил политики, а также в гарантированном перехвате любого сетевого трафика.
- Прикрепление к контрольным группам процессов (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-адрес и порт резолвера для каждого прикрепленного контейнера или виртуальной машины. Взаимодействие устроено по следующей схеме:
- Рабочая нагрузка отправляет DNS-запрос к назначенному локальному эндпоинту Netfence.
- DNS-сервер проверяет имя доменного имени по списку разрешенных правил (поддерживается сопоставление поддоменов с учетом приоритета точных совпадений).
- Если домен разрешен, Netfence выполняет запрос к вышестоящему upstream-серверу по UDP или TCP.
- Полученные в ответе IP-адреса автоматически заносятся в eBPF-карту точных адресов (exact-host hash map) с учетом полученного TTL ответа.
- Только после успешного обновления 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 рекомендуются следующие шаги в инфраструктуре:
- Запуск демона: запустите системный процесс демона с указанием конфигурационного файла:
netfenced start --config /etc/netfence/config.yaml - Проверка статуса: убедитесь в корректности инициализации eBPF-карт:
netfenced status - Прикрепление к интерфейсу или cgroup: подключайте фильтрацию к целевым виртуальным машинам или контейнерам с указанием метаданных:
netfenced attach --interface veth123 --direction ingress --metadata vm_id=abc netfenced attach --cgroup /sys/fs/cgroup/docker/xyz --metadata container_id=xyz - Конфигурация DNS в контейнере: настройте файл
/etc/resolv.confвнутри рабочей нагрузки на выданный IP-адрес локального резолвера Netfence. - Проверка списка ресурсов: убедитесь в наличии активных подключений через CLI:
netfenced list - Отключение при необходимости: отсоединяйте фильтры по идентификатору подключения:
netfenced detach --id <attachment-id>
Подробная документация по настройке gRPC-управления и интеграции доступна в официальной документации Netfence. Перед выводом в промышленную эксплуатацию обязательно проведите нагрузочное тестирование и убедитесь в отсутствии конфликтов с имеющимися CNI-плагинами.

