Сетевой плагин Calico предоставляет широкий набор сетевых политик с унифицированным синтаксисом для защиты хостов на железе, виртуальных машин и pod’ов. Эти политики могут применяться в рамках namespace или быть глобальными сетевыми политиками, применимыми к host endpoint (для защиты приложений, работающих непосредственно на хосте — хостом может быть непосредственно сервер или виртуальная машина) или к workload endpoint (для защиты приложений, работающих в контейнерах или виртуальных машинах, размещенных на хосте). Политики Calico позволяют применить меры безопасности для различных точек пути пакетов с помощью таких параметров, как preDNAT, unraracked и applyOnForward. Понимание того, как эти опции работают, может помочь повысить безопасность и производительность системы в целом. В этой статье объясняется суть данных параметров политик Calico (preDNAT, unraracked и applyOnForward), применяемых к host endpoints, с акцентом том, что происходит в путях обработки пакетов (цепочек iptabels).
Эта статья предполагает, что у вас есть понимание базовых принципов работы сетевых политик Kubernetes и Calico. Если нет, то рекомендуем попробовать basic network policy tutorial и host protection tutorial используя Calico, прежде чем читать эту статью. Мы так же рассчитываем, что вы имеете базовое понимание работы iptables в Linux.
Calico global network policy позволяет вам применять набор правил доступа по labels (к группам хостов и workloads/pods). Это очень полезно, если вы используйте вместе разнородные системы — виртуальные машины, систему непосредственно на железе или инфраструктуру kubernetes. К тому же, вы можете защитить свой кластер (ноды) с помощью набора декларативных политик и применять сетевые политики к входящему трафику (например, через сервис NodePorts или External IPs).
На фундаментальном уровне, когда Calico подключает pod к сети (см. диаграмму ниже), он подключает его к хосту с помощью виртуального интерфейса Ethernet (veth). Отправленный pod’ом трафик приходит на хост с данного виртуального интерфейса и обрабатывается так же, как если бы он пришел от физического сетевого интерфейса. По умолчанию Calico называет эти интерфейсы caliXXX. Поскольку трафик поступает через виртуальный интерфейс, он проходит через iptables, как если бы pod находился на расстоянии одного hop’a. Поэтому, когда трафик приходит/исходит от pod’a, он пересылается (forwarded) с точки зрения хоста.
На Kubernetes ноде, на которой запущен Calico, вы можете сопоставить виртуальный интерфейс (veth) с workload следующим образом. В приведенном ниже примере вы можете видеть, что veth#10 (calic1cbf1ca0f8) подключен к cnx-manager- * в calico-monitoring namespace.
[centos@ip-172-31-31-46 K8S]$ sudo ip a
...
10: calic1cbf1ca0f8@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default
link/ether ee:ee:ee:ee:ee:ee brd ff:ff:ff:ff:ff:ff link-netnsid 5
inet6 fe80::ecee:eeff:feee:eeee/64 scope link
valid_lft forever preferred_lft forever
...
[centos@ip-172-31-31-46 K8S]$ calicoctl get wep --all-namespaces
...
calico-monitoring cnx-manager-8f778bd66-lz45m ip-172-31-31-46.ec2.internal 192.168.103.134/32
calic1cbf1ca0f8
...
Учитывая, что Calico создает veth-интерфейс для каждого workload, как он применяет политики? Для этого Calico создает хуки в различные цепочки пути обработки пакетов, используя iptables.
На диаграмме ниже показаны цепочки, участвующие в обработке пакетов в iptables (или подсистеме netfilter). Когда пакет поступает через сетевой интерфейс, он сначала проходит через цепочку PREROUTING. Затем принимается решение о маршрутизации, и на основании этого пакет проходит либо через INPUT (направленный на процессы хоста), либо через FORWARD (направленный на pod или на другую ноду в сети). Из локального процесса пакет проходит через цепочку OUTPUT, а затем POSTROUTING перед отправкой по кабелю.
Обратите внимание, что pod также является внешним объектом (подключенным к veth) с точки зрения обработки iptables. Подведем итоги:
- Пересылаемый (forwarded) трафик (nat, маршрутизируемый или в / из pod) проходит через цепочки PREROUTING — FORWARD — POSTROUTING.
- Трафик на локальный хост-процесс проходит через цепочку PREROUTING — INPUT.
- Трафик от локального хост-процесса проходит через цепочку OUTPUT — POSTROUTING.
Calico предоставляет опции для политик, при помощи которых можно применять политики для всех цепочек. Имея это в виду, давайте рассмотрим различные варианты настройки политик, доступных в Calico. Цифры в списке опций ниже соответствуют цифрам на диаграмме выше.
- Workload endpoint (pod) policy
- Host endpoint policy
- Опция ApplyOnForward
- Политика PreDNAT
- Политика Untracked
Давайте начнем с рассмотрения того, как политики применяются к workload endpoints (pod’ам Kubernetes или OpenStack VMs), а затем рассмотрим опции политик для host endpoints.
Workload Endpoints
Workload Endpoint Policy (1)
Это опция для защиты ваших kubernetes pod’ов. В Calico поддерживается работа с Kubernetes NetworkPolicy, но так же он предоставляет дополнительные политики — Calico NetworkPolicy и GlobalNetworkPolicy. Calico создает цепочку для каждого pod’а (workload) и хуки в цепочки INPUT и OUTPUT для workload к таблице фильтров цепочки FORWARD.
Host Endpoints
Host Endpoint Policy (2)
Помимо CNI (container network interface), политики Calico предоставляют возможность защиты непосредственно хоста. В Calico вы можете создать host endpoint задав комбинацию из интерфейса хоста и, если нужно, номеров портов. Применение политик для этой сущности достигается при помощи таблицы фильтров в цепочках INPUT и OUTPUT. Как видно из диаграммы, (2) они применяются к локальным процессам на ноде/хосте. То есть, если вы создали политику, которая применяется к host endpoint, она не повлияет на трафик, идущий к/от ваших pod’oв. Но за счет неё обеспечивается единый интерфейс/синтаксис для блокировки трафика для вашего хоста и pod’ов с помощью политик Calico. Это значительно упрощает процесс управления политиками для разнородной сети. Настройка host endpoint политик для усиления защиты кластера — это ещё один важный случай их использования.
ApplyOnForward Policy (3)
Опция ApplyOnForward доступна в Calico global network policy, чтобы дать возможность применения политик ко всему трафику, проходящему через host endpoint, включая трафик, который будет перенаправляться хостом (forwarded). Этот трафик включает в себя пересылаемый в локальный pod или куда-либо ещё в сеть. Calico требует, чтобы этот параметр был включен для политик, использующих PreDNAT и untracked, см. следующие разделы. Кроме того, ApplyOnForward можно использовать для отслеживания трафика хоста в случаях использования виртуального роутера или программных NAT.
Заметьте, что если вам нужно применить одну и ту же сетевую политику как для хост-процессов, так и для pod’ов, то вам не обязательно использовать опцию ApplyOnForward. Вам достаточно создать label для нужных hostendpoint и workload endpoint (pod). Calico достаточно умен, чтобы применять политику на основании labels, независимо от типа endpoint (hostendpoint или workload).
PreDNAT Policy (4)
В Kubernetes порты сущности service могут быть прокинуты наружу при помощи опции NodePorts или, опционально (при использовании Calico), при помощи объявления их через опции Cluster IPs или External IPs. Kube-proxy балансирует входящий трафик, привязанный к service, к pod’ам соответствующих service, используя DNAT. Учитывая это, как вам применить политики для трафика, поступающего через NodePorts? Чтобы эти политики были применены до того, как трафик будет обработан DNAT (представляющий собой сопоставление хоста: порта и соответствующего service), Calico предоставляет параметр для globalNetworkPolicy, который называется «preDNAT: true».
Когда pre-DNAT включен, эти политики реализуются в (4) на диаграмме — в таблице mangle цепочки PREROUTING — непосредственно перед DNAT. Обычный порядок политик (order) здесь не соблюдается, так как применение этих политик происходит намного раньше по пути обработки трафика. Тем не менее, политики preDNAT соблюдают порядок применения (order) между собой.
При создании политик с pre-DNAT важно быть внимательным к трафику, который вы хотите обработать, и позволять большинству быть отклоненным. Трафик, помеченный как ‘allow’ в политике pre-DNAT больше не будет проверяться hostendpoint-политикой, тогда как трафик при провале прохождения политики pre-DNAT продолжит путь через остальные цепочки.
Calico сделал обязательным включение опции applyOnForward при использовании preDNAT, поскольку по определению пункт назначения трафика еще не выбран. Трафик может быть направлен на хост-процесс, или он может быть перенаправлен на pod или на другую ноду.
Untracked Policy (5)
Сети и приложения могут иметь большие различия в поведении. В некоторых крайних случаях приложения могут генерировать множество кратковременных соединений. Это может привести к нехватке памяти у conntrack (основного компонента сетевого стека Linux). Традиционно для запуска приложений такого типа в Linux вам нужно вручную настроить или отключить conntrack, или написать правила iptables, чтобы обойти conntrack. Untracked policy в Calico — это более простой и эффективный вариант, если вы хотите обрабатывать соединения максимально быстро. Например, если вы используйте массивный memcache или в качестве дополнительной меры защиты от DDOS.
Читайте данный blog post (или наш перевод) для получения дополнительной информации, включая тесты производительности при использовании untracked policy.
Когда вы задаете опцию «doNotTrack: true» в Calico globalNetworkPolicy, она становится **неотслеживаемой** политикой и применяется на самом раннем этапе конвейера обработки пакетов Linux. Если посмотреть на диаграмму выше, политики untracked применяются в цепочках PREROUTING и OUTPUT в таблице raw, прежде чем будет запущено отслеживание соединений (conntrack). Когда пакет разрешен untracked политикой, он помечается, чтобы отключить отслеживание соединения для этого пакета. Это означает:
- Политика untracked применяется для каждого пакета. Нет понятия соединения (или потока). Отсутствие соединений (connection) влечет за собой несколько важных последствий:
- Если вы хотите разрешить как трафик запроса, так и трафик ответа, вам необходимо правило как для входящего, так и для исходящего (поскольку Calico обычно использует conntrack, чтобы отметить ответный трафик как разрешенный).
- Политика untracked не работает для workload Kubernetes (pod’ов), потому что в данном случае нет способа отследить исходящее соединение из pod’а.
- NAT работает некорректно с неотслеживаемыми пакетами (поскольку ядро ??хранит сопоставление NAT в conntrack).
- При прохождении через правило «разрешить все» в untracked-политике все пакеты будут помечены как неотслеживаемые. Это почти всегда не то, что вам нужно, поэтому важно быть очень избирательным к пакетам разрешенным untracked-политиками (и позволять большей части трафика проходить через обычные отслеживаемые политики).
- Untracked-политики применяются в самом начале конвейера обработки пакетов. Это очень важно понимать при создании политик Calico. У вас может быть политика для pod’a с order:1 и untracked-политика с order:1000. Это будет не важно. Untracked-политика будет применена до политики для pod’a. Untracked-политики соблюдают очередность выполнения только между собой.
Поскольку одной из целей политики doNotTrack является принудительное применение политики на самом раннем этапе конвейера обработки пакетов Linux, Calico делает обязательным указание опции applyOnForward при использовании doNotTrack. Обращаясь к диаграмме обработки пакетов, обратите внимание, что политика untracked (5) применяется перед любыми решениями о маршрутизации. Трафик может быть направлен на хост-процесс, или он может быть перенаправлен на pod или на другую ноду.
Итоги
Мы рассмотрели различные опции политик (Host endpoint, ApplyOnForward, preDNAT, и Untracked) в Calico и как они применяются на пути обработки пакетов. Понимание сути их работы помогает в разработке эффективных и безопасных политик. С помощью Calico вы можете использовать global network policy, которая применяется к label (группе нод и pod’ов) и применять политики с различными параметрами. Это позволяет специалистам по безопасности и проектированию сети удобно защищать сразу «всё» (типы endpoints), используя единый язык политик с политиками Calico.
Благодарность: Я хотел бы поблагодарить Шона Крэмптона и Алекса Поллитта за их обзор и за ценную информацию.