Я хочу попросить вас дать совет по созданию прозрачного брандмауэра.
У меня есть 2 сегмента сети и серв CentOS с 2 интерфейсами 10G. Я хочу фильтровать / отслеживать / ограничивать / отбрасывать трафик между сегментами. Трафик помечен. Должен ли я снимать теги с трафика для фильтрации и тегировать его обратно или nftable может обрабатывать его с тегами?
Теперь схема выглядит так:
PCs--| |--PCs
PCs--|--untag--[Switch]--tag--[Switch]--untag--|--PCs
PCs--| |--PCs
Я хочу:
PCs--| |--PCs
PCs--|--untag--[Switch]--tag--**[Firewall]**--tag--[Switch]--untag--|--PCs
PCs--| |--PCs
TL; DR: nftables на уровне моста может точно обрабатывать как тегированные, так и немаркированные пакеты, используя несколько другие правила. Всю работу с тегами можно выполнить на стороне Linux, используя мост с поддержкой vlan, поэтому никаких изменений конфигурации на коммутаторах не требуется, независимо от выбора, сделанного в брандмауэре для nftables.
В этой серии блогов можно найти много интересной документации о тестировании VLAN (особенно в части IV, даже если некоторые сведения могут быть не совсем точными):
Развлечение с veth-устройствами, мостами Linux и VLAN в безымянных пространствах имен сети Linux я II III IV V VI VII VIII
Поместим две минималистичные модели межсетевого экрана (в сетевое пространство имен). trunk100
и trunk200
связаны с двумя коммутаторами, отправляющими помеченные пакеты vlan 100 с левых компьютеров и помеченные пакеты vlan 200 с правых компьютеров. Обратите внимание, что здесь тегам VLAN явно разрешено появляться на другой стороне либо путем создания субинтерфейса с идентификатором VLAN другой стороны, либо путем прямого добавления идентификатора VLAN другой стороны в интерфейс магистрали.
суб-интерфейсы vlan, помещающие немаркированные пакеты в мост
ip link add fw0 type bridge vlan_filtering 1
ip link set fw0 up
for trunk in 100 200; do
for vlan in 100 200; do
ip link add link trunk$trunk name trunk$trunk.$vlan type vlan id $vlan
ip link set trunk$trunk.$vlan master fw0
bridge vlan add vid $vlan pvid untagged dev trunk$trunk.$vlan
bridge vlan del vid 1 dev trunk$trunk.$vlan
ip link set trunk$trunk.$vlan up
done
done
bridge vlan del vid 1 dev fw0 self
В этом случае тегированные пакеты, поступающие через trunk100 и trunk200, разделяются на субинтерфейсы для каждого vlan, и пакеты не тегируются. Мост все еще внутренне осведомлен об используемых VLAN и применяет фильтрацию vlan к источникам и получателям. nft
добавит свои ограничения. Исходящие пакеты будут помечены повторно, как только они будут доставлены на интерфейс родительской магистрали.
помеченные пакеты прямо в мост
ip link add fw0 type bridge vlan_filtering 1
ip link set fw0 up
for trunk in 100 200; do
ip link set trunk$trunk master fw0
for vlan in 100 200; do
bridge vlan add vid $vlan tagged dev trunk$trunk
done
bridge vlan del vid 1 dev trunk$trunk
ip link set trunk$trunk up
done
bridge vlan del vid 1 dev fw0 self
В этом более простом случае тегированные пакеты проходят через мост, сохраняя свой тег vlan.
Вот единый набор правил nftables, показывающий, как обрабатываются оба случая. iifname
был выбран здесь вместо iif
поэтому один и тот же набор правил может работать в обоих случаях (без ошибки из-за отсутствия интерфейса). Как обычно iif
следует предпочесть. Есть дополнительные записи счетчика, чтобы просто проверить, что именно совпадает, а что нет (с nft list ruleset -a
):
#!/usr/sbin/nft -f
flush ruleset
table bridge filter {
chain input {
type filter hook input priority -200; policy drop;
}
chain forward {
type filter hook forward priority -200; policy drop;
counter
arp operation request counter
arp operation reply counter
vlan type arp arp operation request counter
vlan type arp arp operation reply counter
arp operation request counter accept
arp operation reply counter accept
vlan type arp arp operation request counter accept
vlan type arp arp operation reply counter accept
ip protocol icmp icmp type echo-request counter
ip protocol icmp icmp type echo-reply counter
vlan type ip icmp type echo-request counter
vlan type ip icmp type echo-reply counter
iifname trunk100.100 ip protocol icmp icmp type echo-request counter accept
oifname trunk100.200 ip protocol icmp icmp type echo-reply counter accept
vlan id 100 vlan type ip icmp type echo-request counter accept
vlan id 200 vlan type ip icmp type echo-reply counter accept
}
chain output {
type filter hook output priority 200; policy drop;
}
}
Обратите внимание, что эти правила можно было бы написать еще более подробно. Пример:
iifname "trunk100.100" ether type ip ip protocol icmp icmp type echo-request
или
ether type vlan vlan id 200 vlan type ip ip protocol icmp icmp type echo-reply
Когда используется первая настройка (немаркированные пакеты через подчиненные интерфейсы), будут соответствовать только классические правила. Когда используется вторая настройка, будут совпадать только правила, явно использующие vlan. Таким образом, этот набор двойных правил, позволяющий базовое разрешение ARP, а также позволяющий VLAN 100 проверять связь с VLAN 200, но не наоборот, будет работать в обоих случаях.
Этот набор правил должен работать при использовании с CentOS nftables v0.6 (не тестировалось на ядре CentOS) или текущей nftables v0.8.3.
Текущие известные ограничения:
Nftables начиная с v0.8.3 не может использовать conntrack так, как это было возможно с взаимодействиями ebtables / iptables. Похоже, есть планы на этот счет, см. Этот PDF: мостовая фильтрация с nftables. Это затрудняет реализацию правил с отслеживанием состояния.
Также обратите внимание, что nftables все еще имеет (по состоянию на 0.8.3) проблемы с отображением: nft list ruleset -a
упадет vlan
из "декомпилированных" правил, если ни одна из его опций не используется. Например, эти два правила:
nft add rule bridge filter forward ip protocol icmp counter
nft add rule bridge filter forward vlan type ip ip protocol icmp counter
При отображении обратно с nft list ruleset -a
(v0.8.3):
ip protocol icmp counter packets 0 bytes 0 # handle 23
ip protocol icmp counter packets 0 bytes 0 # handle 24
Это только с nft --debug=netlink list ruleset -a
который сбросит байт-код, ясно, что это действительно два разных правила (данные здесь с прямым порядком байтов):
bridge filter forward 23 22
[ payload load 2b @ link header + 12 => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
[ payload load 1b @ network header + 9 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
[ counter pkts 0 bytes 0 ]
bridge filter forward 24 23
[ payload load 2b @ link header + 12 => reg 1 ]
[ cmp eq reg 1 0x00000081 ]
[ payload load 2b @ link header + 16 => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
[ payload load 1b @ network header + 9 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
[ counter pkts 0 bytes 0 ]
CentOS 'v0.6 (проверено на ядре 4.15) также имеет свои собственные различные проблемы с отображением "декомпиляции":
ip protocol icmp icmp type echo-request
отображается как:
icmp type echo-request counter
что дает синтаксическую ошибку, если попытаться, как в v0.6 (но нормально в v0.8.3).