Назад | Перейти на главную страницу

В чем разница между «iifname» и «iif» в nftables?

https://wiki.nftables.org/wiki-nftables/index.php/Quick_reference-nftables_in_10_minutes#Meta

Есть ли разница между iifname (вне имени строка) и iif а что рекомендуется?

iif ищет и сравнивает индекс интерфейса полученного пакета, а iifname выполняет сравнение строки с именем интерфейса. У обоих есть достоинства и недостатки.

Так iif использует меньше ресурсов, потому что индекс интерфейса простой номер, уже сохраненный в пакете проходит через сетевой стек и nftables и, таким образом, сразу же доступен для сравнения. Но его недостатком является то, что если интерфейс удален (и, скорее всего, воссоздан, но с более новым значением индекса), то соответствующее правило в nftables больше не будет соответствовать. Единственный всегда гарантированный индекс интерфейса - это интерфейс обратной связи (названный lo по умолчанию): он всегда создается первым в пространстве имен и не может быть удален (или добавлен во второй раз), поэтому его значение индекса всегда 1.

iifname с другой стороны, как и iptables ' --in-interface выполняет сравнение строки с именем текущего интерфейса. Это использует больше ресурсов, но позволяет заранее создать правило для несуществующего интерфейса с детерминированным именем, которое iif не справится легко. iifname также может соответствовать подстановочным знакам, например, в iifname "ppp*", который iif не может и может быть удобно, когда интерфейсы часто создаются и удаляются, но при этом сохраняется соглашение об именах (например, начиная с ppp для ссылок PPP).

Пример (с использованием nftables 0.9.2):

$ unshare -r -n
# ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
# nft add table ip filter
# nft add chain ip filter input '{ type filter hook input priority 0; policy accept; }'
# nft add rule ip filter input iif lo counter
# nft add rule ip filter input iif dummy0 counter
Error: Interface does not exist
add rule ip filter input iif dummy0 counter
                             ^^^^^^
# nft add rule ip filter input iifname dummy0 counter
# ip link add name dummy0 type dummy
# ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 4a:09:68:3a:34:91 brd ff:ff:ff:ff:ff:ff
# nft add rule ip filter input iif dummy0 counter
# nft list ruleset
table ip filter {
    chain input {
        type filter hook input priority filter; policy accept;
        iif "lo" counter packets 0 bytes 0
        iifname "dummy0" counter packets 0 bytes 0
        iif "dummy0" counter packets 0 bytes 0
    }
}
# ip link delete dev dummy0
# nft list ruleset
table ip filter {
    chain input {
        type filter hook input priority filter; policy accept;
        iif "lo" counter packets 0 bytes 0
        iifname "dummy0" counter packets 0 bytes 0
        iif 2 counter packets 0 bytes 0
    }
}

Интерфейс отсутствует, вместо него отображается его индексное значение. Точно так же можно использовать значение индекса, даже заранее, при добавлении правила:

# nft add rule ip filter input iif 3 counter
# nft list ruleset
table ip filter {
    chain input {
        type filter hook input priority filter; policy accept;
        iif "lo" counter packets 0 bytes 0
        iifname "dummy0" counter packets 0 bytes 0
        iif 2 counter packets 0 bytes 0
        iif 3 counter packets 0 bytes 0
    }
}
# ip link add name dummy4 type dummy
# ip link add name dummy0 type dummy
# nft list ruleset
table ip filter {
    chain input {
        type filter hook input priority filter; policy accept;
        iif "lo" counter packets 0 bytes 0
        iifname "dummy0" counter packets 0 bytes 0
        iif 2 counter packets 0 bytes 0
        iif "dummy4" counter packets 0 bytes 0
    }
}

Поскольку значения индекса интерфейса не рециркулируются в пространстве имен, а только увеличиваются, правило индекса 2 «потеряно» (у него больше никогда не будет возможности совпадать). Следующий созданный интерфейс, манекен4 получил индекс 3, который теперь разрешается в dummy4 в наборе правил. манекен0 получено значение индекса 4, на которое нет ссылок ни в одном iif правило, но все равно будет соответствовать iifname правило.


Что рекомендуется?

Мой совет:

Вы должны использовать iif для «стабильных» интерфейсов, которые не изменятся после создания, например, физических интерфейсов Ethernet, доступных при загрузке, до применения правила (при использовании нового соглашения об именах стабильного физического интерфейса, которое не изменится при изменении порядка перечисления), и конечно вот интерфейс. Это не было показано в примере, но вы все равно можете сопоставить список интерфейсов с iif тоже нравится iif { lo, dummy4 }. Так что вы все еще можете иметь сингл iif оператор, соответствующий нескольким интерфейсам.

Вы должны использовать iifname для динамических интерфейсов, которые неизвестны при загрузке (и при создании правил), но, как ожидается, появятся позже, или для сопоставления группы интерфейсов с соглашением об именах при использовании сопоставления с подстановочными знаками.

Не очень известно, для оптимизации вместо использования подстановочных знаков вы можете назначить группу для каждого вновь созданного интерфейса (например, используя ip link set dev interface group 99), а затем сопоставьте группу интерфейса с iifgroup скорее, чем iifname + подстановочный знак. Но для этого требуется некоторый дополнительный механизм для группировки тегов вновь созданных интерфейсов.

Вы также можете использовать интерфейс именованные наборы, таким образом сохраняя общие правила, используя iif и iifname и изменение содержимого названных наборов, а не самих правил. Обратите внимание, что предыдущая ссылка на вики не говорит об использовании интерфейсов в наборах, но она просто устарела. Больше информации об этом в моем ответе UL SE на этот вопрос: Как создать именованный набор строк в nftables (для имен интерфейсов)?.