На уровне ядра предоставляется лишь общий интерфейс, не зависящий от конкретного протокола и предоставляющий базовые функции извлечения данных из пакетов, выполнения операций с данными и управления потоком. Непосредственно логика фильтрации и специфичные для протоколов обработчики компилируются в байткод в пространстве пользователя, после чего данный байткод загружается в ядро при помощи интерфейса Netlink и выполняется в специальной виртуальной машине, напоминающей BPF (Berkeley Packet Filters). Подобный подход позволяет значительно сократить размер кода фильтрации, работающего на уровне ядра и вынести все функции разбора правил и логики работы с протоколами в пространство пользователя.
Основные новшества:
- Поддержка IPsec, позволяющая выполнять сопоставление адресов туннелей в привязке к пакету, идентификатору запроса IPsec и тегу SPI (Security Parameter Index). Например,
... ipsec in ip saddr 192.168.1.0/24
Также возможна проверка прохождения маршрута через туннель IPsec. Например, для блокирования трафика не через IPSec —
... filter output rt ipsec missing drop"
- Поддержка протокола IGMP (Internet Group Management Protocol). Например, для отбрасывания входящих IGMP-запросов принадлежности к группе можно использовать правило
nft add rule netdev foo bar igmp type membership-query counter drop
- Возможность использования переменных для определения цепочек перехода (jump / goto). Например:
add rule ip foo bar jump $dest";
- Поддержка масок для идентификации операционных систем (OS Fingerprint) на основе значений TTL в заголовке. Например, для пометки пакетов в зависимости от ОС отправителя можно использовать команду:
... meta mark set osf ttl skip name map { "Linux" : 0x1, "Windows" : 0x2, "MacOS" : 0x3, "unknown" : 0x0 } ... osf ttl skip version "Linux:4.20"
- Возможность сопоставления ARP-адреса отправителя и IPv4-адреча целевой системы. Например, для увеличения счётчика ARP-пакетов, отправленных с адреса 192.168.2.1 можно использовать правило:
table arp x { chain y { type filter hook input priority filter; policy accept; arp saddr ip 192.168.2.1 counter packets 1 bytes 46 } }
- Поддержка прозрачного проброса запросов через прокси (tproxy). Например, для перенаправления обращений к 80 порту на порт прокси 8080:
table ip x { chain y { type filter hook prerouting priority -150; policy accept; tcp dport 80 tproxy to :8080 } }
- Поддержка пометки сокетов с возможностью для дальнейшего получения установленной метки через setsockopt() в режиме SO_MARK. Например:
table inet x { chain y { type filter hook prerouting priority -150; policy accept; tcp dport 8080 mark set socket mark } }
- Поддержка указания текстовых наименований приоритетов для цепочек. Например:
nft add chain ip x raw { type filter hook prerouting priority raw; } nft add chain ip x filter { type filter hook prerouting priority filter; } nft add chain ip x filter_later { type filter hook prerouting priority filter + 10; }
- Поддержка меток SELinux (Secmark). Например, для определения метки «sshtag» в привязке к контексту SELinux можно запустить:
nft add secmark inet filter sshtag \"system_u:object_r:ssh_server_packet_t:s0\"
А затем использовать эту метку в правилах:
nft add rule inet filter input tcp dport 22 meta secmark set "sshtag" nft add map inet filter secmapping { type inet_service : secmark\; } nft add element inet filter secmapping { 22 : "sshtag" } nft add rule inet filter input meta secmark set tcp dport map @secmapping
- Возможность указания закреплённых за протоколами портов в текстовом виде, как они определены в файле /etc/services. Например:
# nft add rule x y tcp dport \"ssh\" # nft list ruleset -l table x { chain y { ... tcp dport "ssh" } }
- Возможность проверки типа сетевого интерфейса. Например:
add rule inet raw prerouting meta iifkind "vrf" accept
- Улучшена поддержка динамического обновления содержимого наборов (sets) через явное указание флага «dynamic». Например, для обновления набора «s» с добавлением исходного адреса и сбросом записи в случае отсутствия пакентов в течение 30 секунд:
add table x add set x s { type ipv4_addr; size 128; timeout 30s; flags dynamic; } add chain x y { type filter hook input priority 0; } add rule x y update @s { ip saddr }
- Возможность задания отдельный условия наступления таймаута для потоков. Например, для переопределния таймаута по умолчанию для пактов, пришедших на порт 8888 можно указать:
table ip filter { ct timeout agressive-tcp { protocol tcp; l3proto ip; policy = {established: 100, close_wait: 4, close: 4} } chain output { ... tcp dport 8888 ct timeout set "agressive-tcp" } }
- Поддержка NAT для семейства inet:
table inet nat { ... ip6 daddr dead::2::1 dnat to dead:2::99 }
- Улучшены средства вывода информации об ошибках из-за опечаток:
nft add chain filtre test Error: No such file or directory; did you mean table ‘filter’ in family ip? add chain filtre test ^^^^^^
- Возможность указания имён интерфейсов в наборах (sets):
set sc { type inet_service . ifname elements = { "ssh" . "eth0" } }
- Обновлённый синтаксис правил flowtable:
nft add table x nft add flowtable x ft { hook ingress priority 0\; devices = { eth0, wlan0 }\; } ... nft add rule x forward ip protocol { tcp, udp } flow add @ft
- Улучшена поддержка JSON.
Источник: http://www.opennet.ru/opennews/art.shtml?num=50952