RHEL / CentOS Maintenant pour ajouter des règles nftable à firewalld au démarrage du système?

Dec 15 2020

J'utilise firewalld sur RHEL 8 et je dois également ajouter quelques règles nftable.

(Les règles nftable sont basées sur la réponse à CentOS 8 en tant que routeur NAT avec nft et firewalld - comment le faire passer TFTP? )

Dans un pare-feu en cours d'exécution, cela fonctionne bien avec la commande nft -f.

Cependant, cela se perd lors d'un redémarrage.

La documentation RedHat (derrière le paywall) suggère d'utiliser le service nftables.service pour charger les règles au redémarrage, mais cela ne fonctionne pas en conjonction avec firewalld. Les deux services sont répertoriés comme étant en conflit, et même s'ils ne l'étaient pas, firewalld viderait probablement les règles nftable.

Existe-t-il un autre moyen de charger les règles nftable au redémarrage?

Réponses

2 A.B Dec 15 2020 at 18:45

L' utilitaire firewalld , lors de l'utilisation du backend nftables , ne videra pas les tables qui ne lui appartiennent pas :

Ne vider que les règles de firewalld

Puisque nftables autorise les espaces de noms (via des tables), firewalld ne fait plus un vidage complet des règles de pare-feu . Cela videra uniquement les règles de la table firewalld . Cela évite les scénarios dans lesquels des règles utilisateur personnalisées ou des règles installées par d'autres outils sont effacées de manière inattendue lorsque firewalld a été redémarré ou rechargé.

La même chose doit être faite lors de la gestion d'autres tables.

En fait , dans la réponse précédente, il est déjà fait: les nftables règles supprime idempotently que leur propre table: handletftp.

Malheureusement, ce n'est pas le cas nftables.servicepour l' action d' arrêt :

ExecStop=/sbin/nft flush ruleset

Il faut simplement s'assurer que la partie d'arrêt du service systemd ne vide pas directement toutes les règles tout en faisant le travail. Ce travail sera délégué dans des règles nftables dédiées pour l' action d' arrêt .

Voici donc une méthode pratique: dupliquer (par exemple systemctl cat nftables.services:) et modifier nftables.serviceen une version instanciée [email protected]à insérer /etc/systemd/system/[email protected]:

[Unit]
Description=Idempotent nftables rules for %I
Wants=network-pre.target
Before=network-pre.target

[Service]
Type=oneshot
ProtectSystem=full
ProtectHome=true
ExecStart=/sbin/nft -f /etc/nftables/idempotent/%I.nft
# As the rules are idempotent, ExecReload is same as ExecStart
ExecReload=/sbin/nft -f /etc/nftables/idempotent/%I.nft
# The stop rules should only have the first boilerplate parts
ExecStop=/sbin/nft -f /etc/nftables/idempotent/stop-%I.nft
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Créez le répertoire de configuration dédié utilisé ci-dessus:

mkdir -p /etc/nftables/idempotent

Placez les règles qui pour chaque table définie, commencent toujours comme ceci, donc le chargement des règles est indépendant des autres tables et idempotent (exemple avec des tables ip fooet bridge bar):

table ip foo
delete table ip foo

table bridge bar
delete table bridge bar

table ip foo {
    ...
}

table bridge bar {
    ....
}

ou utilisez simplement une table par fichier. La flush rulesetdéclaration est interdite car elle est globale.

La raison pour laquelle une table est créée, supprimée et recréée est d'obtenir le résultat idempotent: alors que la suppression d'une table inexistante est une erreur et ferait échouer atomiquement tout le chargement, déclarant une table existante sans la définir (en ajoutant une table vide) n'échoue jamais et ne fait rien sauf le créer vide s'il n'existait pas auparavant. Dans les deux cas (n'existait pas au démarrage, existe au rechargement), la suppression peut maintenant fonctionner, laissant la place pour vraiment définir la table juste après. Tout cela se passe dans la même transaction et est toujours atomique: aucun paquet ne sera jamais évalué avec une table ip foo manquante si elle existait auparavant pendant cela.

Préparez une version d' arrêt de ci-dessus qui supprimera uniquement (ici, les déclarations vides ne sont pas strictement nécessaires et pourraient être supprimées s'il n'y avait qu'une seule table, mais devraient être conservées s'il y a plus d'une table: l'échec concerne toute la transaction):

table ip foo
delete table ip foo

table bridge bar
delete table bridge bar

et mettez tout à leur emplacement:

/etc/nftables/idempotent/foobar.nft
/etc/nftables/idempotent/stop-foobar.nft

Cela peut maintenant être activé avec:

systemctl enable --now local-idempotent-nft@foobar

Exemple tiré de la question du précédent OP:

dans /etc/nftables/idempotent/handletftp.nft:

table ip handletftp
delete table ip handletftp

table ip handletftp {
    ct helper helper-tftp {
        type "tftp" protocol udp
    }

    chain sethelper {
        type filter hook forward priority 0; policy accept;
        ip saddr 192.168.1.0/24 ip daddr 10.0.10.10 udp dport 69 ct helper set "helper-tftp"
    }
}

Dans /etc/nftables/idempotent/stop-handletftp.nft

table ip handletftp
delete table ip handletftp

Activation et démarrage:

systemctl enable --now local-idempotent-nft@handletftp

L'arrêter:

systemctl stop local-idempotent-nft@handletftp

ce qui laissera les règles de firewalld en place. De même, l'arrêt ou le redémarrage de firewalld laissera ces règles en place.

Il y a probablement des améliorations à faire:

  • nftables a une instruction include qui pourrait être utilisée d'une manière ou d'une autre pour éviter la duplication du passe-partout.
  • l'exemple spécifique de TFTP repose sur le chargement de nf_nat_tftpce qui ne se fera pas automatiquement (contrairement à nf_conntrack_tftpce qui est automatiquement chargé à partir de référence dans les règles ou contrairement à firewalld qui se chargerait nf_nat_tftpexplicitement). Donc, les configurations liées mais non strictement nftables doivent être gardées à l'esprit (ce paramètre peut simplement être mis en place /etc/modules-load.d/).