Some checks are pending
verifier / verifier (push) Waiting to run
Le site ne servait aucun PTR. `serveur_powerdns_zone_inverse` derivait d'un supernet /16 — la forme d'un TENANT, qui tire tout de son index. Un site ne derive pas : il declare plusieurs /24 et n'a pas de supernet unique, si bien que la derivation rendait une chaine vide et qu'aucune zone n'etait generee. Le site revendique desormais exactement ce qu'il occupe : 31.0.10.in-addr.arpa 32.0.10.in-addr.arpa 33.0.10.in-addr.arpa 34.0.10.in-addr.arpa Revendiquer `0.10.in-addr.arpa` d'un seul geste aurait ete plus simple et faux : cette zone couvre aussi la frontiere, le transit et les hyperviseurs, qui ne sont pas a lui. Une autorite qu'on s'attribue sans l'exercer est une panne differee — le resolveur repondrait NXDOMAIN pour des adresses qu'un autre sait nommer. LA DERIVATION VIT DANS UN FILTRE (`zones_inverses`) parce qu'elle a DEUX appelants : `serveur_powerdns` ecrit ces zones, `serveur_resolveur` les delegue a l'autoritatif. Deux calculs separes finiraient par diverger, et la divergence ne se verrait qu'au premier PTR interroge. Le nom d'une zone dit sa profondeur — trois etiquettes numeriques valent un /24, deux valent un /16 — et le modele en deduit seul la forme du PTR. DEUX CHEMINS MORTS TROUVES EN ROUTE. Les zones etaient servies, et personne ne les demandait. `serveur_resolveur` deleguait la zone directe par une `stub-zone` mais pas les inverses : `dig -x` rendait vide depuis les cinq machines alors que la meme requete posee directement a l'autoritatif repondait juste. Un service correct derriere un chemin que rien n'emprunte. Puis, les stubs poses, Unbound repondait toujours NXDOMAIN avec le drapeau `aa` — une reponse AUTORITAIRE, sans jamais consulter le stub. Il embarque des `local-zone` pour tout l'espace RFC1918 inverse. `nodefault` n'y change rien : ce mode n'agit que si le nom correspond EXACTEMENT a une zone par defaut, et la sienne est `10.in-addr.arpa`, le /8 entier. C'est `transparent` qui laisse la requete suivre son cours — pour nos quatre zones seulement, la ou `unblock-lan-zones` aurait ouvert tout l'espace prive. Rien ne distinguait ce blocage d'une absence : le meme NXDOMAIN qu'un nom qui n'existe pas. AUSSI : les zones inverses sont desormais validees par `named-checkzone` comme la directe (un fichier mal forme etait refuse en silence par PowerDNS), et une zone qu'un ecosysteme cesse de revendiquer est retiree du repertoire. VERIFICATION. Les cinq PTR resolvent depuis les cinq hotes par le resolveur, les huit noms directs par le plancher ET par le DNS, et les deux roles sont idempotents (changed=0). P47 evalue la derivation sur cinq cas — un site a quatre zones, un tenant a une, deux machines d'un meme /24 qui n'en font qu'une, aucune adresse, une adresse illisible. Controle negatif verifie. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
72 lines
3.5 KiB
Django/Jinja
72 lines
3.5 KiB
Django/Jinja
# GÉNÉRÉ par Set-OPS (rôle serveur_resolveur). NE PAS éditer à la main.
|
|
server:
|
|
{% for a in serveur_resolveur_ecoutes %}
|
|
interface: {{ a }}
|
|
{% endfor %}
|
|
{% for r in serveur_resolveur_reseaux_autorises %}
|
|
access-control: {{ r }} allow
|
|
{% endfor %}
|
|
access-control: 127.0.0.0/8 allow
|
|
hide-identity: yes
|
|
hide-version: yes
|
|
prefetch: yes
|
|
do-ip6: no
|
|
# La zone souveraine n'est pas signée : on ne la soumet pas à la validation DNSSEC.
|
|
domain-insecure: "{{ serveur_resolveur_zone_interne }}"
|
|
{% for zone_inverse in serveur_resolveur_zones_inverses | default([]) %}
|
|
# Les zones inverses ne le sont pas davantage — et `in-addr.arpa`, LUI, est signé
|
|
# publiquement. Sans cette ligne, la validation chercherait une chaîne de confiance
|
|
# vers une délégation qui n'existe pas, et tous les PTR rendraient SERVFAIL.
|
|
domain-insecure: "{{ zone_inverse }}"
|
|
# UNBOUND BLOQUE L'INVERSE PRIVÉ PAR DÉFAUT (2026-08-25).
|
|
#
|
|
# Il embarque des `local-zone` pour tout l'espace RFC1918 inversé, et y répond
|
|
# lui-même. Avec la `stub-zone` pourtant bien déclarée, `dig -x` rendait NXDOMAIN
|
|
# avec le drapeau `aa` — une réponse AUTORITAIRE d'Unbound, qui n'avait jamais
|
|
# interrogé l'autoritatif. Le même NXDOMAIN qu'un nom qui n'existe pas : rien ne
|
|
# distinguait le blocage de l'absence.
|
|
#
|
|
# `transparent` laisse la requête suivre son cours — donc atteindre la `stub-zone`
|
|
# ci-dessous — pour CETTE zone seulement.
|
|
#
|
|
# Pas `nodefault` : ce mode ne retire un blocage que si le nom correspond EXACTEMENT
|
|
# à une zone par défaut d'Unbound. La sienne est `10.in-addr.arpa`, le /8 entier ; nos
|
|
# `/24` n'y correspondent pas, et la ligne restait sans effet — mesuré, le NXDOMAIN
|
|
# autoritaire persistait après rechargement.
|
|
#
|
|
# Pas `unblock-lan-zones: yes` non plus : il aurait débloqué tout l'espace privé
|
|
# inversé, y compris ce que cet écosystème ne sert pas.
|
|
local-zone: "{{ zone_inverse }}" transparent
|
|
{% endfor %}
|
|
# UNBOUND REFUSE D'INTERROGER UNE LOOPBACK PAR DÉFAUT (2026-08-24).
|
|
#
|
|
# `do-not-query-localhost` vaut `yes` d'origine — une protection contre les boucles.
|
|
# Or l'autoritatif de l'écosystème vit désormais SUR 127.0.0.1:5300, derrière ce
|
|
# résolveur. Sans cette ligne, toute la zone souveraine rend SERVFAIL.
|
|
#
|
|
# Et la panne était MASQUÉE : le plancher /etc/hosts répondait pour les noms de la
|
|
# flotte, si bien qu'un `getent hosts forge.genese.internal` semblait prouver que la
|
|
# résolution marchait. Seul un `dig` explicite l'a montrée.
|
|
do-not-query-localhost: no
|
|
|
|
stub-zone:
|
|
name: "{{ serveur_resolveur_zone_interne }}"
|
|
stub-addr: {{ serveur_resolveur_autoritatif }}@{{ serveur_resolveur_autoritatif_port }}
|
|
{# LES ZONES INVERSES SE DELEGUENT COMME LA DIRECTE (2026-08-25). Sans ces stubs,
|
|
l'autoritatif servait les PTR et personne ne les lui demandait : `dig -x` rendait vide
|
|
depuis les cinq machines, alors que la meme requete posee directement a l'autoritatif
|
|
repondait juste. Un service correct derriere un chemin que rien n'emprunte. #}
|
|
{% for zone_inverse in serveur_resolveur_zones_inverses | default([]) %}
|
|
|
|
stub-zone:
|
|
name: "{{ zone_inverse }}"
|
|
stub-addr: {{ serveur_resolveur_autoritatif }}@{{ serveur_resolveur_autoritatif_port }}
|
|
{% endfor %}
|
|
{% if serveur_resolveur_transitaires %}
|
|
|
|
forward-zone:
|
|
name: "."
|
|
{% for f in serveur_resolveur_transitaires %}
|
|
forward-addr: {{ f }}
|
|
{% endfor %}
|
|
{% endif %}
|