web-dev-qa-db-fra.com

Quelle est la différence entre "iifname" et "iif" dans nftables?

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

Y a-t-il une différence entre iifname (en dehors du nom est une chaîne) et iif et ce qui est recommandé?

6
mvorisek

iif recherche et compare l'index d'interface du paquet reçu, tandis que iifname fait une comparaison de chaînes avec le nom de l'interface. Les deux présentent des avantages et des inconvénients.

Donc iif utilise moins de ressources, car l'index de l'interface est un nombre simple déjà stocké dans le paquet traversant la pile réseau et nftables et donc immédiatement disponible pour comparaison. Mais son inconvénient est que si l'interface est supprimée (et probablement recréée, mais avec une valeur d'index plus récente), la règle correspondante dans nftables ne correspondra plus. Le seul index d'interface garanti à tout moment est l'interface de bouclage (nommée lo par défaut): c'est toujours la première créée dans l'espace de noms et ne peut pas être supprimée (ni ajoutée une deuxième fois), donc sa valeur d'index est toujours 1.

iifname d'un autre côté, tout comme --in-interface iptables fait une comparaison de chaînes avec le nom de l'interface actuelle. Cela utilise plus de ressources, mais permet de créer une règle pour une interface non existante, à l'avance, avec un nom déterministe, ce que iif ne fera pas facilement. iifname peut également faire des correspondances génériques, comme dans iifname "ppp*", ce que iif ne peut pas faire et peut être pratique lorsque les interfaces sont souvent créées et supprimées, mais en conservant une convention de dénomination ( comme commencer par ppp pour les liens PPP).

Exemple (en utilisant 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
    }
}

L'interface étant partie, sa valeur d'index est affichée à la place. De même, une valeur d'index peut être utilisée, même à l'avance, lors de l'ajout d'une règle:

# 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
    }
}

Étant donné que les valeurs d'index d'interface ne sont pas recyclées dans l'espace de noms mais augmentent uniquement, la règle concernant l'index 2 est "perdue" (elle n'aura plus aucune chance de correspondre). La prochaine interface créée, dummy4 a obtenu l'index 3, qui se résout maintenant en dummy4 Dans le jeu de règles. dummy0 a reçu la valeur d'index 4, qui n'est référencée dans aucune règle iif mais correspondra toujours à la règle iifname .


Qu'est-ce qui est recommandé?

Mon conseil:

Vous devez utiliser iif pour les interfaces "stables" qui ne changeront pas une fois créées, comme les interfaces Ethernet physiques disponibles au démarrage, avant l'application de la règle (si vous utilisez la nouvelle convention de dénomination stable des interfaces physiques, cela ne changera pas changer si l'ordre d'énumération change), et bien sûr l'interface lo . Cela n'a pas été montré dans l'exemple, mais vous pouvez toujours faire correspondre une liste d'interfaces avec iif, comme iif { lo, dummy4 }. Ainsi, vous pouvez toujours avoir une seule instruction iif correspondant à plusieurs interfaces.

Vous devez utiliser iifname pour les interfaces dynamiques inconnues au démarrage (et lors de la création des règles) mais qui devraient apparaître plus tard, ou pour faire correspondre un groupe d'interfaces avec une convention de dénomination lors de l'utilisation d'une correspondance générique.

Peu connu, pour optimiser, au lieu d'utiliser des caractères génériques, vous pouvez affecter un groupe à chaque interface nouvellement créée, (par exemple en utilisant ip link set dev interface group 99), Puis faire correspondre le groupe d'interface avec iifgroup plutôt que iifname + caractère générique. Mais cela nécessite un mécanisme supplémentaire pour regrouper les interfaces nouvellement créées.

Vous pouvez également utiliser l'interface ensembles nommés , conservant ainsi les règles génériques en utilisant iif et iifname et en modifiant le contenu des ensembles nommés, plutôt que les règles elles-mêmes. Notez que le lien wiki précédent ne dit pas sur l'utilisation des interfaces dans les ensembles, mais il n'est tout simplement pas à jour. Plus d'informations à ce sujet dans ma réponse UL SE à cette question: Comment puis-je créer un ensemble nommé de chaînes dans nftables (pour les noms d'interface)? .

6
A.B