From 37753984a7838f98228eee861eb030cafe6bdeea Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Tue, 29 Sep 2026 16:09:31 -0400 Subject: [PATCH] services publics des locataires : web frontal 80/443, soumission 587/465 ; externe ouvre a tous chez les locataires Le web frontal devient la porte publique (80/443 externe) ; Postfix publie la soumission 587 et ajoute le 465 (TLS direct). Le generateur nftables ouvrait un flux externe combine a une source nommee a cette seule source : l Internet etait refuse par l hote. Corrige chez les locataires ; au site, rien ne s elargit. Co-Authored-By: Claude Opus 5.5 --- docs/registre-flux.md | 9 ++++++--- roles/serveur_postfix/defaults/main.yml | 3 ++- roles/serveur_postfix/meta/flux.yml | 13 +++++++++++-- roles/serveur_postfix/tasks/main.yml | 14 +++++++++++++- roles/serveur_web_frontal/meta/flux.yml | 16 ++++++++++++++++ scripts/resoudre_flux.py | 13 +++++++++++++ 6 files changed, 61 insertions(+), 7 deletions(-) diff --git a/docs/registre-flux.md b/docs/registre-flux.md index 607646b..44ed5a9 100644 --- a/docs/registre-flux.md +++ b/docs/registre-flux.md @@ -94,7 +94,8 @@ | `serveur_ops_site` | egress | 8006 | tcp | fabric | tls-requis | API de l'hyperviseur : créer, cloner et détruire les VM de la fabric. Le seul flux par lequel un écosystème peut en matérialiser un autre. | | `serveur_ops_tenant` | ingress | 22 | tcp | runner_site | ssh | Insémination : le runner du SITE amorce ce runner-ci — socle, moteur, plan, plancher de résolution — jusqu'à ce qu'un humain lui remette sa voûte. Vers cette machine seule, jamais vers le reste de l'écosystème. | | `serveur_postfix` | ingress | 25 | tcp | externe, client_smtp | starttls | SMTP entrant : courrier externe (MX) et notifications internes (client_smtp). | -| `serveur_postfix` | ingress | 587 | tcp | flotte | starttls | Soumission authentifiée (submission) pour les agents internes qui envoient du courrier. | +| `serveur_postfix` | ingress | 465 | tcp | flotte, externe | tls-requis | Soumission authentifiée en TLS direct (submissions, RFC 8314) : clients de courriel des utilisateurs. | +| `serveur_postfix` | ingress | 587 | tcp | flotte, externe | starttls | Soumission authentifiée (STARTTLS obligatoire) : agents internes et clients de courriel des utilisateurs. | | `serveur_postfix` | egress | 24 | tcp | serveur_dovecot | tls-requis | Remise finale par LMTP au mailstore (Dovecot), en TLS vérifié. | | `serveur_postfix` | egress | 25 | tcp | externe | starttls | Relais sortant vers les MX distants (STARTTLS opportuniste). | | `serveur_postfix` | egress | 636 | tcp | serveur_openldap | tls-requis | Tables virtuelles (domaines/alias/boîtes) résolues sur l'annuaire (LDAPS). | @@ -124,14 +125,16 @@ | `serveur_web_dorsal` | ingress | 80 | tcp | edge | clair | Front nginx local des webapps, proxie par l'edge (TLS termine a l'edge). | | `serveur_web_dorsal` | egress | 443 | tcp | flotte | tls | git clone/pull du depot de chaque app (Forgejo souverain) au deploiement. | | `serveur_web_frontal` | ingress | 80 | tcp | edge | clair | Contenu statique servi au navigateur via l'edge (TLS termine a l'edge). | +| `serveur_web_frontal` | ingress | 80 | tcp | externe | clair | HTTP public — le premier contact d'un navigateur, et le defi HTTP d'ACME ; renvoie vers HTTPS. | +| `serveur_web_frontal` | ingress | 443 | tcp | externe | tls-requis | HTTPS public — les sites et services que le locataire publie sur l'Internet. | | `serveur_web_frontal` | egress | 443 | tcp | flotte | tls | git clone/pull du depot du site (Forgejo souverain) au deploiement. | ## Synthèse chiffrement -- **clair** : 50 flux +- **clair** : 51 flux - **n-a** : 8 flux - **ssh** : 8 flux - **starttls** : 6 flux - **tls** : 11 flux - **tls-cible** : 2 flux -- **tls-requis** : 34 flux +- **tls-requis** : 36 flux diff --git a/roles/serveur_postfix/defaults/main.yml b/roles/serveur_postfix/defaults/main.yml index e528e63..bc45287 100644 --- a/roles/serveur_postfix/defaults/main.yml +++ b/roles/serveur_postfix/defaults/main.yml @@ -39,7 +39,8 @@ serveur_postfix_lmtp_port: 24 # --- Soumission :587 (clients authentifiés) --- # SASL délégué à Dovecot (passdb LDAP prouvé) sur le nœud mail-store, via son auth réseau. -# Interne uniquement : STARTTLS requis, seuls les authentifiés relaient. Pas de sortie internet. +# 587 (STARTTLS requis) et 465 (TLS direct) ; seuls les authentifiés relaient. Publics depuis le +# 2026-09-29 : les clients de courriel y arrivent par l'adresse publique du locataire. serveur_postfix_submission_actif: false serveur_postfix_sasl_hote: "{{ serveur_postfix_mailstore_hote }}" serveur_postfix_sasl_port: 12345 diff --git a/roles/serveur_postfix/meta/flux.yml b/roles/serveur_postfix/meta/flux.yml index 837d5ee..94742d8 100644 --- a/roles/serveur_postfix/meta/flux.yml +++ b/roles/serveur_postfix/meta/flux.yml @@ -8,12 +8,21 @@ flux: chiffrement: starttls poste: false raison: "SMTP entrant : courrier externe (MX) et notifications internes (client_smtp)." + # LA SOUMISSION EST PUBLIQUE (2026-09-29) : les clients de courriel des utilisateurs + # envoient depuis n'importe ou, par l'adresse publique du locataire. Toujours chiffree, + # toujours authentifiee (SASL Dovecot) ; seuls les authentifies relaient. - sens: ingress port: 587 protocole: tcp - pair: flotte + pair: [flotte, externe] chiffrement: starttls - raison: "Soumission authentifiée (submission) pour les agents internes qui envoient du courrier." + raison: "Soumission authentifiée (STARTTLS obligatoire) : agents internes et clients de courriel des utilisateurs." + - sens: ingress + port: 465 + protocole: tcp + pair: [flotte, externe] + chiffrement: tls-requis + raison: "Soumission authentifiée en TLS direct (submissions, RFC 8314) : clients de courriel des utilisateurs." - sens: egress port: 24 protocole: tcp diff --git a/roles/serveur_postfix/tasks/main.yml b/roles/serveur_postfix/tasks/main.yml index d375f20..2fd91fa 100644 --- a/roles/serveur_postfix/tasks/main.yml +++ b/roles/serveur_postfix/tasks/main.yml @@ -189,7 +189,10 @@ mode: "0644" notify: Redémarrer postfix -- name: Activer la soumission :587 (clients authentifiés, SASL Dovecot distant) +# 465 (`submissions`, TLS DIRECT, 2026-09-29) A COTE DU 587 (STARTTLS). La RFC 8314 recommande +# le TLS direct pour la soumission : aucun echange en clair avant le chiffrement. Memes +# restrictions que le 587 : authentifie, sinon refuse. +- name: Activer la soumission :587 et :465 (clients authentifiés, SASL Dovecot distant) ansible.builtin.blockinfile: path: /etc/postfix/master.cf marker: "# {mark} SETOPS SUBMISSION 587" @@ -203,6 +206,15 @@ -o smtpd_sasl_security_options=noanonymous -o smtpd_client_restrictions=permit_sasl_authenticated,reject -o smtpd_relay_restrictions=permit_sasl_authenticated,reject + submissions inet n - y - - smtpd + -o syslog_name=postfix/submissions + -o smtpd_tls_wrappermode=yes + -o smtpd_sasl_auth_enable=yes + -o smtpd_sasl_type=dovecot + -o smtpd_sasl_path=inet:{{ serveur_postfix_sasl_hote }}:{{ serveur_postfix_sasl_port }} + -o smtpd_sasl_security_options=noanonymous + -o smtpd_client_restrictions=permit_sasl_authenticated,reject + -o smtpd_relay_restrictions=permit_sasl_authenticated,reject when: serveur_postfix_submission_actif | bool notify: Redémarrer postfix diff --git a/roles/serveur_web_frontal/meta/flux.yml b/roles/serveur_web_frontal/meta/flux.yml index f069086..4d789a0 100644 --- a/roles/serveur_web_frontal/meta/flux.yml +++ b/roles/serveur_web_frontal/meta/flux.yml @@ -7,6 +7,22 @@ flux: pair: edge chiffrement: clair raison: "Contenu statique servi au navigateur via l'edge (TLS termine a l'edge)." + # LE WEB FRONTAL EST LA PORTE PUBLIQUE DU LOCATAIRE (2026-09-29). L'edge expose les services + # INTERNES a l'administration ; ce qui est publie sur l'Internet l'est ici, par l'adresse + # publique que le site attribue au locataire (redirection a la frontiere). Le 443 attend son + # TLS (Let's Encrypt) : la redirection est prete avant lui. + - sens: ingress + port: 80 + protocole: tcp + pair: externe + chiffrement: clair + raison: "HTTP public — le premier contact d'un navigateur, et le defi HTTP d'ACME ; renvoie vers HTTPS." + - sens: ingress + port: 443 + protocole: tcp + pair: externe + chiffrement: tls-requis + raison: "HTTPS public — les sites et services que le locataire publie sur l'Internet." - sens: egress port: 443 protocole: tcp diff --git a/scripts/resoudre_flux.py b/scripts/resoudre_flux.py index a6bb20f..35315d9 100644 --- a/scripts/resoudre_flux.py +++ b/scripts/resoudre_flux.py @@ -732,6 +732,19 @@ def generer_nftables(flux_par_role: dict[str, list[dict]], site: bool = False) - f"source — aucune regle emise pour {hote} (une source vide " f"ouvrirait le port a tous).", file=sys.stderr) continue + # `externe` COMBINE A UNE SOURCE NOMMEE OUVRE A TOUS (2026-09-29). Le 25 de + # Postfix est `[externe, client_smtp]`, la soumission `[flotte, externe]` : la + # source nommee se resolvait, et la regle ne gardait QU'ELLE — l'Internet, + # que la frontiere redirige et que Proxmox laisse passer, etait refuse par + # l'hote lui-meme. « Tout le monde » inclut la flotte. Sauf le SSH : son + # `externe` est celui de la gestion, reserve a l'administration partout. + # CHEZ LES LOCATAIRES SEULEMENT : eux seuls exposent au public. Au site, la + # soumission du relais courriel (declaree publique par le meme role) reste + # a sa flotte — le site ne publie que ce qu'il redirige (`port_public`). + _ssh = (str(fl.get("protocole", "tcp")).lower() != "icmp" + and "22" in [str(x) for x in ports]) + if _public and not local and not _ssh and not site: + saddr = "" for port in ports: if local and not srcs: continue # lo deja accepte