connectivite : ignorer ses propres adresses ; un flux sans service est une information

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-09-30 22:50:35 -04:00
parent d2e2bb8990
commit 8603ec4c19

View file

@ -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