Швидки підказки стосовно Nftables

ВСТУП
Цей документ знаходиться між брудною методичкою та шпаргалкою. Ми пропонуємо вам прочитати короткий опис деяких цікавих функцій nftables, що допоможе вам полюбити nftables. Для опису архітектури та ідей, що стоять за Nftables, будь ласка, прочитайте анонс першого випуску nftables.
Для отримання додаткової глобальної інформації ви також можете переглянути розмову, яку я виголосив у Ерік Леблонд:«Рецепти ядра», OISF - Nftables.

АРХИТЕКТУРА NFTABLES

Бібліотеки


Потрібні наступні бібліотеки

Цілком можливо, що ваш дистрибутив уже включає libmnl. Але, якщо ні, то встановити обидві бібліотеки досить просто, оскільки вони встановлюються стандартним чином:
./autogen.sh
./configure
make
make install
ldconfig


nftables


Спочатку встановіть залежності:
aptitude install libgmp-dev libreadline-dev


Якщо ви хочете встановити документацію:


aptitude install docbook2x docbook-utils


git clone git://git.netfilter.org/nftables
cd nftables
./autogen.sh
./configure
make
make install
kernel
Якщо у вас ще немає дерева git Linux, запустить:
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


Якщо у вас вже є дерево git Linux, ви можете просто оновити його
cd linux
git pull --rebase


Тепер, коли у вас є джерело, ви можете вибрати опції для nftables:
$ make oldconfig

Netfilter Xtables support (required for ip_tables) (NETFILTER_XTABLES) [M/y/?] m
Netfilter nf_tables support (NF_TABLES) [N/m] (NEW) m
  Netfilter nf_tables payload module (NFT_PAYLOAD) [N/m] (NEW) m
  Netfilter nf_tables IPv6 exthdr module (NFT_EXTHDR) [N/m] (NEW) m
  Netfilter nf_tables meta module (NFT_META) [N/m] (NEW) m
  Netfilter nf_tables conntrack module (NFT_CT) [N/m] (NEW) m
  Netfilter nf_tables rbtree set module (NFT_RBTREE) [N/m] (NEW) m
  Netfilter nf_tables hash set module (NFT_HASH) [N/m] (NEW) m
  Netfilter nf_tables counter module (NFT_COUNTER) [N/m] (NEW) m
  Netfilter nf_tables log module (NFT_LOG) [N/m] (NEW) m
  Netfilter nf_tables limit module (NFT_LIMIT) [N/m] (NEW) m
  Netfilter nf_tables nat module (NFT_NAT) [N/m] (NEW) m
  Netfilter x_tables over nf_tables module (NFT_COMPAT) [N/m/?] (NEW) m

IPv4 nf_tables support (NF_TABLES_IPV4) [N/m] (NEW) m
  nf_tables IPv4 reject support (NFT_REJECT_IPV4) [N/m] (NEW) m
  IPv4 nf_tables route chain support (NFT_CHAIN_ROUTE_IPV4) [N/m] (NEW) m
  IPv4 nf_tables nat chain support (NFT_CHAIN_NAT_IPV4) [N/m] (NEW) m

IPv6 nf_tables support (NF_TABLES_IPV6) [M/n] m
  IPv6 nf_tables route chain support (NFT_CHAIN_ROUTE_IPV6) [M/n] m
  IPv6 nf_tables nat chain support (NFT_CHAIN_NAT_IPV6) [M/n] m

Ethernet Bridge nf_tables support (NF_TABLES_BRIDGE) [N/m/y] (NEW) m


Тепер ви можете створити своє ядро за допомогою звичайних команд.
На debian, для двоядерний машині, ви можете це виконати так:
make -j 2 deb-pkg


Або ви можете по черзі використовувати старий метод:
CONCURRENCY_LEVEL=2 make-kpkg --revision 0.1 --rootcmd fakeroot  --initrd --append-to-version nftables kernel_image kernel_headers


Користувачі Debian також можуть отримати початковий код для ядра з git:
Інші пов'язані пакети доступні в цьому каталозі.

ЗАПУСК

Початкові налаштування

Щоб отримати ланцюг подібний до iptables, використовуйте файл ipv4-filter, наданий у джерелі
nft -f files/nftables/ipv4-filter

Потім ви можете подивитися ланцюг:
nft list table filter
Зауважте, що filter це назва таблиці яка має ланцюг output, input. Хоча може бути використана будь-яка інша назва.

Основні правила управління

Щоб скинути (дропнути) вихідні дані до пункту призначення
nft add rule ip filter output  ip daddr 1.2.3.4 drop

Лічильники правил необов’язкові для nftables, а для його активації потрібно використовувати ключове слово:
nft add rule ip filter output ip daddr 1.2.3.4 counter drop

Щоб додати правило стосовно мережі, ви можете вказати мережу:
nft add rule ip filter output ip daddr 192.168.1.0/24 counter

Щоб скинути пакет який заходе на порт 80, застосуйте наступний синтаксис:
nft add rule ip filter input tcp dport 80 drop

Щоб прийняти запит відлуння ICMP (ping):
nft add rule filter input icmp type echo-request accept

Щоб поєднати фільтрацію, ви маєте просто вказати кілька разів синтаксис ip:
nft add rule ip filter output ip protocol icmp  ip daddr 1.2.3.4 counter drop

Щоб видалити всі правила в ланцюгу:
nft delete rule filter output

Щоб видалити одне конкретне правило, вам потрібно виконати nft опцію -a, щоб отримати номер правила:
# nft list table filter -a
table filter {
        chain output {
                ip protocol icmp ip daddr 1.2.3.4 counter packets 5 bytes 420 drop # handle 10
...

Потім можна видалити правило 10 за допомогою команди:
nft delete rule filter output handle 10

Ви також можете очистити таблицю фільтру:
nft flush table filter

Можливо вставити правило:
nft insert rule filter input tcp dport 80 counter accept

Можливо вставити або додати правило у певну позицію. Для цього вам потрібно отримати позначку правила, до якого або після якого додати нове правило.
Це робиться за допомогою опції -a в операції з параметром list:
# nft list table filter -n  -a
table filter {
        chain output {
                type filter hook output priority 0;
                ip protocol tcp counter packets 82 bytes 9680 # handle 8
                ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7
        }
}
# nft  add rule filter output position 8 ip daddr 127.0.0.8 drop
# nft list table filter -n -a
table filter {
        chain output {
                type filter hook output priority 0;
                ip protocol tcp counter packets 190 bytes 21908 # handle 8
                ip daddr 127.0.0.8 drop # handle 10
                ip saddr 127.0.0.1 ip daddr 127.0.0.6 drop # handle 7
        }
}


Тут ми додали правило спираючись на правило з позначкою 8. Для додавання перед правилом із заданою позначкою ви можете використовувати:
nft insert rule filter output position 8 ip daddr 127.0.0.12 drop

Якщо ви хочете співставити лише протокол, ви можете скористатись щось на кшталт:
nft insert rule filter output ip  protocol tcp counter


IPv6

Подібно до IPv4, вам потрібно створити кілька ланцюгів. Для цього ви можете використовувати:
nft -f files/nftables/ipv6-filter

Потім ви можете додати правило:
nft add rule ip6 filter output ip6 daddr home.regit.org counter

Перелік правил можна отримати за допомогою:
nft list table ip6 filter

Щоб прийняти динамічну конфігурацію IPv6 та виявлення сусіда, можна використовувати:
nft add rule ip6 filter input icmpv6 type nd-neighbor-solicit accept
nft add rule ip6 filter input icmpv6 type nd-router-advert accept


Відстеження підключення

Щоб прийняти всі вхідні пакети встановленого з'єднання: nft ins
nft insert rule filter input ct state established accept
 
Фільтр по інтерфейсу

Щоб прийняти всі пакети, що виходять з інтерфейсу loopback:
nft insert rule filter output oif lo accept

і пакети, які надходять на eth2:
nft insert rule filter input iif eth2 accept

Зверніть увагу, що oif насправді є цілим числом, що є індексом інтерфейсу всередині ядра. Користувацька область перетворює задане ім'я в індекс інтерфейсу, коли оцінюється правило nft (перед тим, як надсилати у ядро). Наслідком цього є те, що правило не можна додавати, якщо інтерфейс не існує.

Іншим наслідком є те, що якщо інтерфейс буде видалено та створено заново, індекс не співпадє, оскільки індекс доданих інтерфейсів у ядрі монотонно зростає. Таким чином, oif - це швидкий фільтр, але він може спричинити деякі проблеми при використанні динамічних інтерфейсів.

Можливо зробити фільтр за назвою інтерфейсу, але він має меншу продуктивність, оскільки виконується порівняння рядків замість цілого числа. Щоб зробити фільтр на ім'я інтерфейсу, потрібно використовувати oifname:
nft insert rule filter input oifname ppp0 accept


Ведення журналів


Ведення журналів активується через ключове слово log. Тепичне правило для ведення журналу і дозволу буде виглядати десь так:
nft add rule filter input tcp dport 22 ct state new log prefix \"SSH for ever\" group 2 accept


За допомогою nftables можна зробити одним правилом те, що в iptables треба було робити різними строками (NFLOG та ACCEPT).


Якщо префікс prefix - це лише стандартний параметр префікса, параметр групи group містить групу nfnetlink_log, якщо цей режим використовується в якості основи ведення журналів.


Фактично, для ведення журналу в nftables використовується бібліотека ведення журналу Netfilter. Це означає, що ведення журналу залежить від завантаженого модуля ядра.


Доступні модулі ядра:
  • xt_LOG: ведення журналу на основі printk, виведення всього в syslog (той самий модуль, що і той, який використовується для iptables LOG target)
  • nfnetlink_log: ведення журналу на основі netlink, цє модуль який вимагає встановити ulogd2 для отримання подій (той самий модуль, який використовується для iptables NFLOG target)
Щоб використовувати один з двох модулів, завантажте їх з modprobe.


Потім можна налаштувати ведення журналу на основі per-protocol. Конфігурація доступна в /proc:
# cat /proc/net/netfilter/nf_log
0 NONE (nfnetlink_log)
1 NONE (nfnetlink_log)
2 nfnetlink_log (nfnetlink_log,ipt_LOG)
3 NONE (nfnetlink_log)
4 NONE (nfnetlink_log)
5 NONE (nfnetlink_log)
6 NONE (nfnetlink_log)
7 nfnetlink_log (nfnetlink_log)
8 NONE (nfnetlink_log)
9 NONE (nfnetlink_log)
10 nfnetlink_log (nfnetlink_log,ip6t_LOG)
11 NONE (nfnetlink_log)
12 NONE (nfnetlink_log)


Як ми бачимо nfnetlink_log був завантажений зразу  і ulogd запрацював. Наприклад, якщо ви хочете використовувати ipt_LOG для IPv4 (2 у списку), ви можете зробити:
echo "ipt_LOG" >/proc/sys/net/netfilter/nf_log/2 


Це активує ipt_LOG для ведення журналів IPv4:
# cat /proc/net/netfilter/nf_log
0 NONE (nfnetlink_log)
1 NONE (nfnetlink_log)
2 ipt_LOG (nfnetlink_log,ipt_LOG)
3 NONE (nfnetlink_log)
4 NONE (nfnetlink_log)
5 NONE (nfnetlink_log)
6 NONE (nfnetlink_log)
7 nfnetlink_log (nfnetlink_log)
8 NONE (nfnetlink_log)
9 NONE (nfnetlink_log)
10 nfnetlink_log (nfnetlink_log,ip6t_LOG)
11 NONE (nfnetlink_log)
12 NONE (nfnetlink_log)


Якщо ви хочете зробити просте тестування, просто завантажте модуль xt_LOG перед nfnetlink_log. Він прив’яже протокол IPv4 та IPv6 та забезпечить ведення журналу.


Використовуючи один єдиний ланцюг


Ланцюги визначені користувачем і можуть бути організовані будь-яким способом. Наприклад, можно використовувати один єдиний ланцюг для введення. Для цього створіть файл onechain з таким вмістом:
#! nft -f

table global {
        chain one {
                type filter hook input priority   0;
        }
}


і запустить
nft -f onechain


Потім ви можете додати правило:
nft add rule ip global one ip daddr 192.168.0.0/24


Перевагою цієї настройки є те, що фільтрація Netfilter буде активною лише для пакетів, що надходять у коробку (наш host ???).


Набіри


Ви можете використовувати безіменний набір із таким синтаксисом:
nft add rule ip Filter Output ip daddr {192.168.1.1, 192.168.1.4} drop


Ім'яний набір може бути використаний у файлі. Наприклад, ви можете створити файл simple:
define ip_set = {192.168.1.2, 192.168.2.3}
add rule filter output ip daddr $ip_set counter


і виконати:
nft -f simple


Можливо також використовувати названий набір. Для оголошення одного набору, що містить ipv4 адресу:
nft add set filter ipv4_ad { type ipv4_address\;}


Щоб додати елементи до набору:
nft add element filter ipv4_ad { 192.168.3.4 }
nft add element filter ipv4_ad { 192.168.1.4, 192.168.1.5 }


Відображення набору здійснюється за допомогою:
nft list set filter ipv4_ad


Набір може бути використаний у правилі:
nft add rule ip filter input ip saddr @ipv4_ad drop


Можна видалити елемент із існуючого набору:
nft delete element filter ipv4_ad { 192.168.1.5 }


і видалити набір:
nft delete set Filter myset


Mapping - відображення


Map - це специфічний тип набору, який веде себе як словник. Наприклад, можна вказати ipv4_address для обмежання:
# nft -i
nft> add map filter verdict_map { type ipv4_address : verdict; }
nft> add element filter verdict_map { 1.2.3.5 : drop}
nft> add element filter verdict_map { 1.2.3.4 : accept}

nft> add rule filter output ip daddr vmap @verdict_map


Щоб видалити один елемент відображення, ви можете використовувати той самий синтаксис, що і при виділені набіру:
nft> delete element filter verdict_map 1.2.3.5


Щоб видалити один набір, ви можете використовувати:
nft delete set filter verdict_map


Mapping також може використовуватися анонімно:
nft add rule filter output ip daddr vmap {192.168.0.0/24 : drop, 192.168.0.1 : accept}


Щоб відобразити конкретне відображення:
nft list set filter nat_map -n


NAT



Перш за все, необхідний модуль nat:
modprobe nft_nat


Далі вам потрібно повідомити ядро про NAT для протоколу (тут IPv4):
modprobe nft_chain_nat_ipv4


Тепер ми можемо створити спеціальний ланцюг NAT:
nft add table nat
nft add chain nat post { type nat hook postrouting priority 0 \; }
nft add chain nat pre { type nat hook prerouting priority 0 \; }


Тепер ми можемо додати правила NAT:
nft add rule nat post ip saddr 192.168.56.0/24 oif wlan0 snat 192.168.1.137
nft add rule nat pre udp dport 53 ip saddr 192.168.56.0/24 dnat 8.8.8.8:53


У першому рядку увесь трафік виходячий з 192.168.56.0/24 до інтерфейсу wlan0 до IP 192.168.1.137. У другому - перенаправлення всього трафіку DNS з 192.168.56.0/24 на сервер 8.8.8.8.
Можливо здійснити NAT на діапазон адрес:
nft add rule nat post ip saddr 192.168.56.0/24 oif wlan0 snat 192.168.1.137-192.168.1.140


IPv6 NAT також можливий. Спочатку вам потрібно завантажити модуль, щоб оголосити можливість NAT для IPv6:
modprobe nft_chain_nat_ipv6


Після цього ви можете додати такі правила, як:
table ip6 nat {
    chain postrouting {
        type nat hook postrouting priority -150;
        ip6 saddr 2::/64 snat 1::3;
    }
}

 

ПОЧАТКОВІ НАЛАШТУВАННЯ



Наступний набір правил - це типовий набір правил для захисту одного ноутбука в IPv4 та IPv6:
# IPv4 filtering
table Filter {
        chain Input {
                type filter hook input priority 0;
                ct state established accept
                ct state related accept
                iif lo accept
                tcp dport ssh counter accept
                counter log drop
        }

        chain Output {
                type filter hook output priority 0;
                ct state established accept
                ct state related accept
                oif lo accept
                ct state new counter accept
        }
}
#IPv6 filtering
table ip6 Filter {
        chain Input {
                type filter hook input priority 0;
                ct state established accept
                ct state related accept
                iif lo accept
                tcp dport ssh counter accept
                icmpv6 type { nd-neighbor-solicit, echo-request, nd-router-advert, nd-neighbor-advert } accept
                counter log drop
        }

        chain Output {
                type filter hook output priority 0;
                ct state established accept
                ct state related accept
                oif lo accept
                ct state new counter accept
        }

}

Орігінальна статья  https://home.regit.org/netfilter-en/nftables-quick-howto/