From 8603ec4c19cf92533f22583b0c29808ecf290b7d Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Wed, 30 Sep 2026 22:50:35 -0400 Subject: [PATCH] connectivite : ignorer ses propres adresses ; un flux sans service est une information Co-Authored-By: Claude Opus 5.5 --- .../templates/sonde-connectivite.sh.j2 | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/roles/nftables_baseline/templates/sonde-connectivite.sh.j2 b/roles/nftables_baseline/templates/sonde-connectivite.sh.j2 index 5a554f2..71c83fb 100644 --- a/roles/nftables_baseline/templates/sonde-connectivite.sh.j2 +++ b/roles/nftables_baseline/templates/sonde-connectivite.sh.j2 @@ -16,7 +16,10 @@ # # CE QUE L'ERRNO DIT — mesure du 2026-09-30, depuis web-frontal-01 de Technolibre : # ouvert le flux passe -> OK -# ECONNREFUSED le paquet est PASSE, personne n'ecoute sur ce port -> AVERTISSEMENT +# ECONNREFUSED le paquet est PASSE, personne n'ecoute sur ce port -> INFORMATION +# (pas une coupure : un flux declare que rien ne sert — p. ex. une +# interface liee en local derriere la passerelle SSO. Nomme et compte, +# mais pas en jaune : un avertissement permanent apprend a ignorer le jaune) # EHOSTUNREACH REJETE (pare-feu Proxmox : icmp host-prohibited), ou # machine injoignable -> CRITIQUE # delai JETE en silence (politique `drop` de nftables) -> CRITIQUE @@ -84,6 +87,14 @@ def lignes(cmd): return [] ecoute = {l.split()[3].rsplit(":", 1)[1] for l in lignes(["ss", "-Hltn"]) if len(l.split()) >= 4} +# MES PROPRES ADRESSES : une machine qui se parle a elle-meme par son adresse (Loki sur +# obs-01, port 9096) passe par la boucle locale, jamais par un pare-feu. Vu au premier +# deploiement : `obs-01` se declarait « hors des regles » envers lui-meme. +moi = set() +for l in lignes(["ip", "-o", "addr", "show"]): + c = l.split() + if len(c) >= 4 and c[2] in ("inet", "inet6"): + moi.add(c[3].split("/")[0]) reseaux = {} for e in d.get("entrees") or []: if e.get("proto") == "tcp": @@ -102,7 +113,7 @@ for l in lignes(["ss", "-Hnt", "state", "established"]): adr = ipaddress.ip_address(pair) except ValueError: continue - if adr.is_loopback: + if adr.is_loopback or str(adr) in moi: continue permis = False for r in reseaux.get(lport, []): @@ -124,16 +135,16 @@ if coupes: print(f"COUPE : {len(coupes)}/{len(resultats)} flux sortant(s) ne passent pas — {nomme(coupes)}. {perf}") sys.exit(2) avert = [] -if personne: - avert.append(f"{len(personne)} flux passent mais personne n'ecoute — {nomme(personne)}") +info = (f" ; {len(personne)} flux declare(s) sans service (rien n'ecoute) — {nomme(personne)}" + if personne else "") if hors: avert.append(f"{len(hors)} connexion(s) entrante(s) hors des regles declarees — " + ", ".join(sorted(hors)[:5])) if avert: - print(f"{ouverts}/{len(resultats)} flux sortants ouverts ; " + " ; ".join(avert) + f". {perf}") + print(f"{ouverts}/{len(resultats)} flux sortants ouverts{info} ; " + " ; ".join(avert) + f". {perf}") sys.exit(1) if not resultats: print(f"Aucun flux sortant declare pour {d.get('hote', 'cet hote')} ; aucune entree hors des regles. {perf}") sys.exit(0) -print(f"Connectivite : {ouverts}/{len(resultats)} flux sortants ouverts ; aucune entree hors des regles. {perf}") +print(f"Connectivite : {ouverts}/{len(resultats)} flux sortants ouverts{info} ; aucune entree hors des regles. {perf}") PY