ansible : pipelining + ControlPersist — la course « banner exchange » comprise

Cette fois j'ai garde le journal, et la cause est etablie.

La machine : un seul demarrage toujours en cours, aucune coupure reseau, aucun
redemarrage de sshd. Le « trou » de 72 s dans son journal n'en etait pas un —
l'entree qui le referme est ma propre commande de diagnostic. L'hote n'a rien
fait parce que plus personne ne lui parlait.

La cause : maxstartups 5:30:20 et maxsessions 2 (defauts Debian 10:30:100 et
10). Au-dela de 5 connexions non authentifiees simultanees, sshd en refuse une
partie SANS BANNIERE — et le client rapporte « timed out during banner
exchange », qui accuse le reseau pour un refus applicatif.

Ces valeurs ne viennent d'aucun role : elles sont dans le GABARIT. Un reglage
de securite qui ne vit que dans une image disque est invisible du depot et des
preuves, et gouverne pourtant la voie d'administration.

Corrige cote client : ansible.cfg n'avait AUCUNE section [ssh_connection].
pipelining + ControlPersist + control_path_dir court (un chemin trop long
depasse la limite des sockets UNIX et ferait retomber Ansible sur une
connexion par tache).

Mesure sur le meme play de 30 taches : avant, une session par seconde ; apres,
ZERO nouvelle session.

Reste ouvert : MaxStartups/MaxSessions devraient etre declares par
ssh_baseline plutot que dormir dans le gabarit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-09 12:35:01 -04:00
parent b08130dfdd
commit ed6087d5de
2 changed files with 65 additions and 0 deletions

View file

@ -1,5 +1,50 @@
# CHANGELOG — Set-OPS
## 2026-08-09 — « Banner exchange » : ce n'était ni le réseau, ni l'hôte, ni sshd
La course qui avait interrompu deux déploiements est **comprise**, cette fois — parce que
j'ai gardé le journal.
**Ce que la machine dit d'elle-même** : un seul démarrage, toujours en cours ; aucune
coupure réseau ; aucun redémarrage de `sshd`. Et le « trou » de 72 secondes dans son
journal n'en était pas un — l'entrée qui le referme est *ma propre commande de
diagnostic*. L'hôte n'a rien fait pendant ce temps **parce que plus personne ne lui
parlait**. Ce n'est pas lui qui a disparu, c'est Ansible qui n'entrait plus.
**La cause, mesurée** :
```
maxstartups 5:30:20 defaut Debian : 10:30:100
maxsessions 2 defaut Debian : 10
```
Au-delà de **cinq connexions non authentifiées simultanées**, `sshd` en refuse une partie
**sans envoyer de bannière**. Le client attend une bannière qui ne viendra pas et rapporte
« Connection timed out during banner exchange » — un message qui accuse le réseau pour un
refus applicatif. Les sessions arrivaient à une par seconde juste avant la coupure.
Ces valeurs ne viennent d'aucun rôle : `ssh_baseline` ne les pose pas. **Elles sont dans le
gabarit doré**, où l'exploitant les a durcies. C'est un réglage de sécurité qui ne vit que
dans une image disque — invisible du dépôt, invisible des preuves, et qui gouverne pourtant
la voie d'administration.
**Corrigé côté client, pas en affaiblissant l'hôte.** `ansible.cfg` n'avait *aucune* section
`[ssh_connection]` : ni `pipelining`, ni `ControlPersist` explicite. Ajoutés, avec un
`control_path_dir` court — un chemin trop long dépasse la limite des sockets UNIX et fait
retomber Ansible sur une connexion par tâche, ce qui ramènerait le problème sans qu'on le
voie.
**Mesure avant / après**, sur le même play de 30 tâches :
```
avant : une session SSH par seconde, des centaines par hôte
après : 0 nouvelle session pour tout le play
```
**Ce qui reste ouvert** : `MaxStartups` et `MaxSessions` devraient être déclarés par
`ssh_baseline` plutôt que dormir dans le gabarit. Un durcissement qu'aucun fichier du dépôt
ne mentionne ne peut être ni revu, ni prouvé, ni expliqué à qui reprend la machine.
## 2026-08-09 — L'ancien gabarit supprimé, le nouveau porte son nom
Le cluster ne porte plus qu'un gabarit : **`modeleChezlepro`, VMID 99998**. Le plan le

View file

@ -11,3 +11,23 @@ stdout_callback = default
become = True
become_method = sudo
become_user = root
[ssh_connection]
# Le sshd des hotes est DURCI par le gabarit, bien en dessous des defauts Debian :
# maxstartups 5:30:20 (defaut 10:30:100) maxsessions 2 (defaut 10)
# Au-dela de 5 connexions NON AUTHENTIFIEES simultanees, sshd en refuse une partie
# SANS envoyer de banniere — et l'echec se lit « Connection timed out during banner
# exchange », qui accuse le reseau. Mesure le 2026-08-09 sur infra-dns-01 : les sessions
# arrivaient a une par seconde, puis plus rien ; l'hote n'avait ni redemarre ni perdu son
# reseau, c'est Ansible qui ne parvenait plus a entrer.
#
# On ouvre donc MOINS de connexions au lieu d'affaiblir l'hote :
# pipelining — une seule connexion par tache au lieu de plusieurs allers-retours
# ControlPersist — la connexion maitresse survit entre les taches
# `ControlPath` court : un chemin trop long depasse la limite des sockets UNIX et fait
# retomber Ansible sur une connexion par tache, ce qui ramenerait le probleme.
pipelining = True
ssh_args = -C -o ControlMaster=auto -o ControlPersist=300s -o PreferredAuthentications=publickey
control_path_dir = /tmp/.ansible-cp
retries = 3