ebfw — это единственный eBPF-агент уровня узла, который показывает — и контролирует — к каким ресурсам разрешено обращаться каждому поду на узле Kubernetes. Одна программа cgroup_skb, прикреплённая к корневой cgroup узла, видит весь исходящий DNS, TLS SNI, HTTP и новые TCP-соединения от каждого пода; uprobe на SSL_write восстанавливает пути HTTPS-запросов до шифрования. Каждое событие привязывается к конкретному поду (namespace/name). Те же хуки ядра разрешают или запрещают исходящий трафик (egress) для каждого пода по домену / IP / CIDR / порту, управляясь нативными Kubernetes-ресурсами EgressPolicy (CRD). Агент также видит HTTP-пути и заголовки и позволяет политикам фильтровать по методу и пути (проверка уже работает; применение на уровне L7 запланировано в roadmap).
Как это работает
-
Одна программа
cgroup_skb/egressв корневой cgroup v2 узла видит исходящий трафик каждого пода на узле — DNS, TLS ClientHello SNI, обычный HTTP и новые TCP-соединения — без sidecar-контейнера на каждый под. -
Uprobe на
SSL_writeчитает открытый текст HTTPS-запроса до шифрования, восстанавливая пути, которые пакетный уровень увидеть не может. Автоматически обнаруживается для libssl каждого контейнера, работает непрерывно (без семплирования). -
Атрибуция пода выполняется прямо в ядре по идентификатору cgroup источника, а затем обогащается до
namespace/nameчерез Pods informer уровня узла. Те же карты (maps) возвращают вердикты политик обратно в ядро для применения.
flowchart LR
pods["Pods on node"]
subgraph kernel["in-kernel (eBPF)"]
egress["cgroup_skb/egress<br/>DNS, TLS SNI, HTTP, CONNECT"]
uprobe["SSL_write uprobe<br/>HTTPS path + headers"]
end
agent["ebfw agent (Go)<br/>attribute + policy engine"]
informer["k8s Pods informer"]
out["text / JSON<br/>Prometheus /metrics"]
pods --> egress
pods --> uprobe
egress -- "+ cgroup id" --> agent
uprobe -- "+ cgroup id" --> agent
informer -- "namespace/name" --> agent
agent --> out
agent -. "allow / deny verdicts" .-> kernel
Что видно
DNS 10.42.0.9 ? example.com (TypeA) pod=default/probe
TLS 10.42.0.9 -> example.com (104.20.23.154:443) pod=default/probe
HTTP 10.42.0.9 -> GET example.com/foo/bar pod=default/probe
HTTPS [pid=2550689 curl] GET example.com/secret/path?token=abc123 pod=default/probe
CONNECT 10.42.0.9 -> 104.20.23.154:443 pod=default/probe
Или структурированный JSON (EBFW_OUTPUT=json, один объект на строку):
{"ts":"2026-06-28T09:14:01Z","kind":"https","domain":"example.com","method":"GET","path":"/secret/path","pid":2550689,"comm":"curl","pod":{"namespace":"default","name":"probe","uid":"be31e934-…","container":"ad68e835…","qos":"besteffort","node":"k3d-ebfw-server-0"}}
Управление
Описывайте политики исходящего трафика как Kubernetes-ресурсы — EgressPolicy (с привязкой к namespace) и ClusterEgressPolicy (на весь кластер) — агент применяет их в трёх режимах: off (наблюдение без действий), log (добавляет вердикты в журнал, без блокировок) или enforce (блокирует запрещённый исходящий трафик). Сочетание defaultAction: Deny с podSelector ограничивает выбранный набор подов строгим списком разрешённых адресов. Подробнее: docs/egresspolicy.md.
Быстрый старт
helm install ebfw ./helm/ebfw -n ebfw --create-namespace \
--set agent.enforceMode=log # сначала наблюдайте вердикты; переключите на enforce, когда будете готовы
kubectl apply -f config/samples/ebfw_v1_egresspolicy.yaml
Полная инструкция → docs/install.md.
Чем это отличается от Cilium?
Cilium — это CNI, он управляет сетью всего кластера. ebfw работает рядом с тем, что у вас уже есть. Он прикрепляется к корневой cgroup узла, поэтому DaemonSet можно установить на любой узел (с любым CNI или вовсе без Kubernetes), понаблюдать за трафиком в режиме log и убрать его без единого последствия для связности — плоскость данных он не трогает.
Главное отличие: ebfw читает пути и заголовки HTTPS-запросов через uprobe на SSL_write — до шифрования, без прокси и без MITM TLS. Cilium для той же цели требует терминирующий Envoy и подменённые сертификаты.
ebfw — это лёгкий межсетевой экран исходящего трафика и слой видимости L7 на уровне пода; Cilium — полноценная сетевая платформа (с поддержкой применения L7-политик уже сейчас, чего в ebfw пока нет). Полное сравнение по функциям → docs/comparison.md.
Хосты с контейнерами (без Kubernetes)
ebfw не привязан к Kubernetes. Тот же агент — в виде привилегированного контейнера или единственного бинарника на хосте — наблюдает и контролирует исходящий трафик каждого контейнера на обычном хосте Docker / containerd, используя YAML-файл политик вместо CRD (те же возможности видимости, то же применение на уровне узла, без API-сервера и оператора). Подробнее: Запуск в автономном режиме.
Лицензия
MIT © dvrkn.
Создано с использованием eBPF skill для ориентирования в хуках, картах и верификаторе, а также cilium/ebpf (ebpf-go, MIT) в качестве загрузчика.