--- - name: Installer nftables ansible.builtin.apt: name: nftables state: present - name: Vérifier la présence du ruleset résolu (généré par make flux) ansible.builtin.stat: path: "{{ nftables_baseline_ruleset_genere }}" delegate_to: localhost become: false changed_when: false register: nftables_baseline_ruleset_stat - name: Déployer le ruleset nftables résolu (moindre privilège, généré) ansible.builtin.copy: src: "{{ nftables_baseline_ruleset_genere }}" dest: /etc/nftables.conf owner: root group: root mode: "0644" notify: Reload nftables when: - nftables_baseline_enabled | bool - nftables_baseline_ruleset_stat.stat.exists - name: Déployer la configuration nftables Set-OPS (gabarit plat — repli) ansible.builtin.template: src: nftables.conf.j2 dest: /etc/nftables.conf owner: root group: root mode: "0644" notify: Reload nftables when: - nftables_baseline_enabled | bool - not nftables_baseline_ruleset_stat.stat.exists # ARMER LE PARE-FEU COUPE LA MAIN QUI L'ARME (mesure du 2026-08-30). # # Une session SSH ouverte AVANT le demarrage de nftables n'a aucune entree conntrack. # Des que le ruleset s'installe, ses paquets arrivent en `invalid` et tombent sur # `ct state invalid drop` — la session meurt. Les connexions NEUVES passent sans # probleme (SYN -> NEW -> suivi) : le pare-feu est correct, c'est la continuite qui # ne l'est pas. # # CE N'EST PAS UN VERROUILLAGE, ET C'EST CE QUI LE REND DANGEREUX. Rien n'echoue : # Ansible attend une reponse qui ne viendra jamais, sans delai. Le 2026-08-30, un # deploiement est reste suspendu CINQUANTE-HUIT MINUTES sur six machines, pendant que # les quinze repondaient parfaitement a qui se connectait a neuf. # # `async` + `poll: 0` : on lance et on ne guette pas la reponse — elle ne peut pas # revenir. `reset_connection` jette la session morte, `wait_for_connection` en ouvre # une neuve, qui elle sera suivie par conntrack des sa poignee. - name: Activer nftables si demandé (sans attendre la reponse) ansible.builtin.systemd: name: nftables enabled: true state: started async: 60 poll: 0 when: nftables_baseline_enabled | bool - name: Jeter la session que le pare-feu vient de couper ansible.builtin.meta: reset_connection # LE DELAI EST UNE ATTENTE, PAS UN VERDICT : si l'hote ne revient pas, c'est un vrai # verrouillage — la garde `nftables_admin_ssh` a manque sa cible — et il faut le dire # fort plutot que de laisser un playbook pendre. - name: Reprendre la main sur l'hote qu'on vient d'armer ansible.builtin.wait_for_connection: delay: 3 timeout: 90 when: nftables_baseline_enabled | bool - name: Désactiver nftables si demandé ansible.builtin.systemd: name: nftables enabled: false state: stopped when: not (nftables_baseline_enabled | bool) failed_when: false # --- LA SONDE « connectivite » (2026-09-30) ------------------------------------------------ # # Ce que ce pare-feu promet, verifie chaque minute depuis la machine qui doit pouvoir # joindre — et non plus seulement au moment d'une activation. Deposee dans le repertoire # des sondes A LA MINUTE, que le porteur `client_sante` joue en mode `minute`. - name: La liste des flux de cet hote est-elle generee ? ansible.builtin.stat: path: "{{ nftables_baseline_connectivite_genere }}" delegate_to: localhost become: false changed_when: false register: nftables_baseline_connectivite_stat - name: Assurer le repertoire des sondes a la minute ansible.builtin.file: path: /usr/local/lib/setops/sondes-minute state: directory owner: root group: root mode: "0755" # PAS DANS /etc/setops : cette liste n'a rien de secret, et ce repertoire-la — celui des # secrets — a deja ses gardiens (0700 chez les locataires, 0755 au site). Un troisieme avis # sur ses droits le faisait basculer a chaque passage (vu en simulation au site). - name: Deposer la liste des flux a tester ansible.builtin.copy: src: "{{ nftables_baseline_connectivite_genere }}" dest: /usr/local/lib/setops/connectivite.json owner: root group: root mode: "0644" when: nftables_baseline_connectivite_stat.stat.exists - name: Retirer l'ancien emplacement de la liste (premier deploiement, 2026-09-30) ansible.builtin.file: path: /etc/setops/connectivite.json state: absent - name: Deposer la sonde « connectivite » ansible.builtin.template: src: sonde-connectivite.sh.j2 dest: /usr/local/lib/setops/sondes-minute/connectivite.sh owner: root group: root mode: "0750"