# DNS : interne et public > **Pour qui :** le **mainteneur** du DNS, et l'**exploitant** d'un site qui publie les noms > de ses locataires. Le nom du fichier date du temps où il ne couvrait que l'interne. Le service DNS interne est la premiere capacite de plateforme. > **Plancher de resolution independant du DNS.** Le socle (`hosts_statiques`, dans > `serveur_debian`) genere `/etc/hosts` sur **chaque** VM depuis l'inventaire : tout > l'ecosysteme se resout par nom **meme serveur DNS eteint** (et au bootstrap, avant > que PowerDNS ne soit la). PowerDNS devient une **commodite** (zone, externe, > dynamique), plus un point de defaillance. ## Vue d'ensemble Deux services distincts, qui ne se parlent pas : - **la résolution interne** — chaque écosystème résout ses propres noms (`*.internal`) et l'Internet pour ses machines. Rien n'en sort. - **le DNS public** — les zones publiques des locataires (`chezlepro.ca`, `technolibre.ca`), écrites chez le locataire, servies à l'Internet par **deux sites**, sous deux noms. ```mermaid flowchart LR NET(("Internet")) subgraph LOC["Les locataires — vivent au site de Chezlepro"] direction TB P1["infra-dns-01 · OPS-Chezlepro · 10.17.19.11
pdns@public :5300
primaire caché, signe DNSSEC"] P2["infra-dns-01 · OPS-Technolibre · 10.23.19.11
pdns@public :5300
primaire caché, signe DNSSEC"] end subgraph SC["Site de Chezlepro"] direction TB BIF["bifrost-1
WAN 69.70.26.62:53"] S1["site-dnspub-01 · 10.37.37.21
dnsdist :1053 → PowerDNS :53
dns1.chezlepro.ca"] BIF -- "redirection :1053" --> S1 end subgraph ST["Site de TechnoLibre"] direction TB REL["relais · VPS OVH
51.79.45.193"] REQ["requin
opt9 RELAIS · opt10 lien"] S2["site-dnspub-01 · 10.31.37.21
dnsdist :1053 → PowerDNS :53
dns1.technolibre.ca"] REL -- "tunnel WireGuard" --> REQ REQ -- "redirection :1053" --> S2 end P1 & P2 -- "NOTIFY · AXFR signé TSIG" --> S1 P1 & P2 -. "NOTIFY · AXFR signé TSIG
par le lien entre les sites" .-> S2 NET -- "53" --> BIF NET -- "53" --> REL ``` | Pièce | Rôle | Où | Section | |---|---|---|---| | plancher `/etc/hosts` | résout la flotte, DNS éteint | chaque VM | [Trois couches](#trois-couches-et-une-seule-est-optionnelle) | | Unbound | LE résolveur d'un écosystème | `infra-dns-01` (locataire), `site-dns-01` (site) | idem | | PowerDNS principal | autorité sur la zone `.internal` | boucle locale, derrière Unbound | idem | | PowerDNS `pdns@public` | primaire caché des zones publiques | `infra-dns-01` du locataire, `:5300` | [Zones publiques](#zones-publiques) | | PowerDNS + dnsdist | serveur de noms public du site, secondaire | `site-dnspub-01` de chaque site | [Deux sites](#deux-sites-deux-serveurs-de-noms) | ## Trois couches, et une seule est optionnelle > **Ce paragraphe decrivait le modele d'avant le 2026-08-24** — un Unbound *sur chaque VM*, > en opt-in. Ce n'est plus le cas : `client_resolveur` **n'installe plus rien**, et son > integration est **universelle**, pas elective. ```text 1. hosts_statiques le PLANCHER : /etc/hosts genere sur chaque VM depuis l'inventaire -> l'ecosysteme se resout DNS eteint. Jamais optionnel. 2. serveur_powerdns l'AUTORITATIF de la zone souveraine (un par ecosysteme) 3. serveur_resolveur le RECURSIF : UN seul Unbound pour tout le tenant, qui recurse depuis la racine et delegue la zone souveraine a PowerDNS client_resolveur l'integration : ecrit /etc/resolv.conf pour designer ce resolveur ``` **`client_resolveur` n'installe plus de demon** (2026-08-24). Il en posait un par VM — N demons identiques de ~21 Mo pour quelques centaines de requetes. Il ne fait plus qu'une chose : **ecrire `/etc/resolv.conf`**. Son integration est marquee `universelle: true`, et elle n'a **aucune exemption, pas meme l'hote qui porte le resolveur** : il se sert lui-meme. L'ancien nom (`client_unbound`) mentait des lors qu'il n'installait plus Unbound. **L'integration suit l'existence du service, elle ne se declare pas.** Aucun `serveur_resolveur` au plan rend `client_resolveur_actif` faux et le role ne touche a rien : l'ecosysteme garde la resolution d'amorcage de cloud-init. C'est un choix valide, pas une panne. ### Le chemin d'une requête interne ```mermaid flowchart TB Q["Une machine du locataire
cherche un nom"] --> H{"/etc/hosts
le plancher"} H -- "machine de la flotte" --> A1["adresse — sans DNS"] H -- "autre nom" --> U["Unbound · infra-dns-01:53
serveur_resolveur"] U -- "*.internal et zone inverse
stub-zone" --> PA["PowerDNS principal
127.0.0.1:5300"] U -- "tout le reste
récursion depuis la racine" --> NET(("Internet")) Q -. "locataire neuf, sans résolveur à lui" .-> SD["site-dns-01
le résolveur du site
serveur_resolveur_site"] ``` - **Le résolveur est la seule porte.** Quand PowerDNS partage l'hôte d'Unbound, il écoute sur la boucle locale (`5300`) : personne ne l'interroge directement (port `derive`, `roles/serveur_powerdns/meta/flux.yml`). - **Le site prête ses noms aux locataires neufs.** Tant qu'un locataire n'a pas son résolveur, `client_resolveur` le fait interroger celui du site (`serveur_resolveur_site`, dont la liste d'autorisation se dérive des locataires hébergés), puis le bascule chez lui. - **Où mène un nom exposé, vu de l'intérieur** : `resolution_interne` dans `plan/domaines.yml`. `service` (le site) : la zone mène au service lui-même — l'edge est pour les personnes. `edge` (défaut, les locataires) : la machine passe par l'edge, parce que certains services n'existent en HTTPS que derrière lui (Keycloak). - **Une machine qui naît** interroge `dns_amorcage` (la patte de la frontière) tant que le résolveur de son site n'existe pas. ## Groupes ```text serveur_powerdns -> autoritatif interne (PowerDNS Authoritative) serveur_resolveur -> LE recursif du tenant (Unbound), un seul client_resolveur -> integration universelle : designe ce resolveur dans /etc/resolv.conf ``` ## Zone initiale La zone initiale est : ```text exemple.internal ``` Elle est definie dans : ```text instance/inventories//group_vars/serveur_powerdns.yml ``` ## Enregistrement automatique Le role `serveur_powerdns` genere la zone a partir de l'inventaire. Les hotes qui remplissent ces conditions sont ajoutes automatiquement : ```text hote dans hotes_actifs ansible_host defini ``` Exemple : ```text web-frontal-01 ansible_host=10.0.2.31 -> web-frontal-01.exemple.internal A 10.0.2.31 ``` Les enregistrements additionnels explicites sont dans `serveur_powerdns_records`. ## Backend PowerDNS Le premier jalon utilise le backend BIND de PowerDNS. Raison : - pas de dependance prematuree a PostgreSQL ; - zone lisible et generee par Ansible ; - idempotence simple ; - bon point de depart pour la supervision. Quand `serveur_postgresql` sera stable, il sera possible de migrer vers un backend SQL si le besoin operationnel le justifie. ## La bascule de `/etc/resolv.conf` est protegee Le role `client_resolveur` ne bascule `/etc/resolv.conf` qu'apres avoir verifie que le resolveur repond **deja** — pour l'interne *et* pour l'Internet : ```yaml client_resolveur_apply: true client_resolveur_confirm: true ``` Sans ces deux variables, le role prépare Unbound mais ne modifie pas `/etc/resolv.conf`. Cette protection est volontaire : une mauvaise configuration DNS peut couper la resolution de noms. C'est la dependance la plus dangereuse du lot — basculer un hote sur un resolveur qui n'est pas encore pret le rend **muet**, et le runner qui devrait reparer tombe avec les autres. Le playbook de groupe applique donc l'hote qui *porte* le resolveur avant ceux qui s'y adressent, et la preuve **P44** refuse tout ecart entre cette declaration et lui. ## Le piege qui a coute deux jours : la racine signee nie notre TLD `internal.` n'est **pas delegue dans la racine**, qui est signee : elle rend donc une preuve NXDOMAIN *validee* pour ce TLD. Or `harden-below-nxdomain` — **actif par defaut** dans Unbound — tient ce « non » pour prouve et repond NXDOMAIN pour **tout** nom sous `internal.` depuis son cache, **sans jamais interroger la `stub-zone`** declaree plus bas. La delegation etait correcte. L'autoritatif repondait juste. Pas une requete ne lui parvenait. Ce qui declenche l'empoisonnement : n'importe quelle question sur un nom inexistant sous `internal.` — y compris la zone d'**un autre ecosysteme**, que ce resolveur ne sert pas et va donc chercher a la racine. Sur un resolveur partage, ca arrive en permanence. Et la panne parait **intermittente** : au redemarrage le cache est vide, tout fonctionne, on conclut que c'est regle. Le remede mesure (2026-09-02) est `harden-below-nxdomain: no` dans `roles/serveur_resolveur/templates/setops.conf.j2` — **pas** `aggressive-nsec`, qui traite un autre symptome. ## Surveillance a prevoir Les premiers checks utiles : - service `pdns` actif ; - port UDP/TCP 53 disponible ; - SOA de `exemple.internal` resoluble ; - enregistrement `ns1.exemple.internal` resoluble ; - enregistrements des hotes actifs presents ; - serial de zone attendu ; - latence de resolution. ## Zones publiques > Ajouté le 2026-09-16. Le mode `primaire-cache` était **validé par le schéma et consommé par > rien** depuis sa création — *une autorité qu'on s'attribue sans l'exercer est une panne > différée*. `plan/domaines.yml` porte un champ `autorite` par domaine. Deux valeurs sont exercées : | `autorite` | Ce que ça veut dire | Qui sert la zone | |---|---|---| | `auto-heberge` | zone **interne** (`.internal`), servie à l'écosystème seul | l'instance principale de `serveur_powerdns`, sur la boucle locale | | `primaire-cache` | zone **publique** : le locataire l'écrit, le site la sert | `pdns@public` chez le locataire (primaire caché), `serveur_dns_public` au site (secondaire public) | `delegue` est accepté par le validateur et **n'est consommé par aucun rôle**. Il ne faut pas le déclarer en croyant qu'il fait quelque chose. **Le locataire écrit, le site sert, un site pair réplique.** Le primaire reste chez le locataire : quand il part, il emporte sa zone. Le détail — et ce que l'épreuve de PowerDNS a appris — est dans `roles/serveur_dns_public/README.md`. Trois règles, chacune payée ou mesurée : - **TSIG seul ouvre le transfert.** `allow-axfr-ips` et TSIG sont *alternatifs* : une adresse listée obtient la zone sans signature. L'instance publique n'autorise que la boucle locale. - **Une instance à part pour le public.** Faire écouter l'instance principale sur l'adresse de l'hôte aurait permis au serveur public du site d'interroger la zone `.internal`. - **Le serial suit le contenu.** Un serial figé ferait garder au secondaire l'ancienne zone pour toujours. **Rien n'est exposé à Internet en phase 1.** P82 refuse d'exposer le serveur public tant que toutes ses zones ne sont pas signées DNSSEC. ### Ce qu'une zone publique porte > Ajouté le 2026-09-16, phase 2. Une zone qui ne portait que ses expositions web aurait coupé > le courriel de production à la minute où le registraire l'aurait suivie. Chaque zone `primaire-cache` déclare ses **enregistrements** au plan (`enregistrements:` dans `plan/domaines.yml`) : A, AAAA, CNAME, MX, TXT, CAA. `valider_domaines` refuse une adresse privée, une cible incomplète, un CNAME à l'apex ou à côté d'un autre type, un MX sans priorité, un TXT avec guillemets ou hors ASCII, un nom écrit en absolu (`mx.chezlepro.ca` sous `chezlepro.ca`), et tout enregistrement dans une zone que Set-OPS n'écrit pas. Le **SOA et les NS** ne se déclarent pas : ils désignent le serveur de noms du site, sous le nom que **le site** déclare (`dns_public_nom`, contrat du site, reçu par chaque locataire). Seule la zone qui contient ce nom porte son A. Le premier choix, `ns1.`, aurait déplacé en silence un `ns1.chezlepro.ca` qui existe en production vers une autre adresse. **Avant de basculer : `make dns-bascule-devis`.** Il compare le plan au DNS en service, nom par nom et type par type, sur les noms déclarés et une liste de sondes usuelles. Il rend ce qui serait **perdu**, **changé**, **ajouté**, ou **abandonné en connaissance de cause** (les marques `heritage=external-dns`), et les préalables : le serveur de noms doit déjà résoudre publiquement, et il en faut **deux** (exigence du registre `.ca`). Une mesure qui échoue rend « mesure impossible », jamais « absent ». Sa limite est écrite à chaque rapport : sans transfert de zone, un export chez le fournisseur actuel reste la seule preuve d'exhaustivité. Le devis sonde aussi **la colle de chaque serveur désigné** — ceux du site et ceux des pairs ([Deux sites](#deux-sites-deux-serveurs-de-noms)). Au 2026-10-14 : les deux zones sont servies par les deux sites, signées, au même serial ; **aucune n'est basculée chez son registraire**. `chezlepro.ca` reproduit la production (rien ne serait perdu). La décision pour `technolibre.ca` revient au responsable désigné de TechnoLibre. ### Signature DNSSEC : le locataire signe, avec la clé de sa voûte > Ajouté le 2026-09-16, phase 2. Éprouvé sur les machines réelles avant d'être codé. `dnssec: true` sur une zone `primaire-cache` la fait signer **par le primaire du locataire**, avec **une** clé CSK ECDSA P-256 tenue dans **sa** voûte (`vault_dnssec_`). Le site ne détient aucune clé : il reçoit la zone déjà signée et la sert telle quelle (PowerDNS pose `PRESIGNED` au transfert). | Geste | Commande | Écrit ? | |---|---|---| | Créer la clé d'une zone | `python3 scripts/dnssec.py generer ` | la voûte du locataire (copie de sûreté chiffrée, relue avant et après) | | Lire le DS à remettre au registraire | `make dnssec-ds` | rien — calculé depuis la voûte, sans la machine | | Voûte, plan et registre concordent-ils ? | `make dnssec-verifier` | rien | Pourquoi la clé ne naît pas sur la machine : une reconstruction depuis zéro signerait avec une **autre** clé, le DS du registraire ne correspondrait plus, et le domaine deviendrait **BOGUS** pour tout résolveur validant, sans qu'aucune machine soit en panne. Trois règles, chacune mesurée : - **Changer la clé ou retirer la signature pendant qu'un DS est publié est refusé** par l'outil de la machine (`setops-dnssec-zone`) comme par `dnssec.py`. Une mesure du DS qui échoue vaut refus. - **Le serial servi est l'heure (`SOA-EDIT EPOCH`).** PowerDNS renouvelle ses signatures chaque semaine (inception au début de la semaine précédente, expiration deux semaines après le début de la semaine courante). `INCEPTION-EPOCH`, essayé d'abord, ne dépassait notre serial qu'au moment où les signatures du site expiraient. Avec l'heure, le site retire la zone à chaque rafraîchissement ; les signatures servies gardent 7 à 14 jours. - **L'état DNSSEC fait partie du corps de la zone.** Signer ne change aucun enregistrement : sans la ligne `; DNSSEC : …`, le serial n'aurait pas bougé et le site aurait gardé la version non signée. La sonde `zones-publiques` du site alerte sur une zone signée servie **nue**, avertit sous 6 jours de signature restante, et alerte sous 3. **Ordre de la mise en service** : basculer les serveurs de noms (zone signée, sans DS : le domaine reste « non sécurisé », pas cassé), vérifier, **puis** remettre le DS au registraire. Jamais l'inverse. ## Deux sites, deux serveurs de noms > Ajouté le 2026-10-14. Le registre des `.ca` exige deux serveurs de noms ; deux serveurs > sur le même réseau tomberaient ensemble. Le second est au site de TechnoLibre, tenu par une > autre organisation, sur un autre réseau. **Chaque site sert les zones publiques de tous les locataires qu'il connaît : les siens, et ceux de son pair.** Les deux serveurs sont **secondaires** l'un comme l'autre, et tirent chacun la zone **directement du primaire du locataire** — jamais l'un de l'autre (`disable-axfr=yes` au site). Un site qui tombe n'emporte donc pas la copie de l'autre. | Site | Serveur | Nom public | Adresse publique | Chemin depuis l'Internet | |---|---|---|---|---| | Chezlepro | `site-dnspub-01` · `10.37.37.21` | `dns1.chezlepro.ca` | `69.70.26.62` | WAN de `bifrost-1` → `:1053` | | TechnoLibre | `site-dnspub-01` · `10.31.37.21` | `dns1.technolibre.ca` | `51.79.45.193` | relais (VPS) → tunnel `opt9` de `requin` → `:1053` | ### Publier une zone ```mermaid sequenceDiagram autonumber participant X as Exploitant du locataire participant P as pdns@public
infra-dns-01 du locataire participant C as site-dnspub-01
site de Chezlepro participant T as site-dnspub-01
site de TechnoLibre X->>P: rôle serveur_powerdns — la zone est rendue depuis le plan Note over P: SOA et NS = dns1 du site + dns1 de chaque pair
serial = suit le contenu · signée avec la clé de la voûte P-)C: NOTIFY (only-notify : les seuls serveurs du contrat) P-)T: NOTIFY, par le lien entre les sites C->>P: SOA ? (UDP 5300) C->>P: AXFR signé TSIG (TCP 5300) P-->>C: zone déjà signée — servie telle quelle (PRESIGNED) T->>P: SOA ? puis AXFR signé TSIG, par le lien P-->>T: zone déjà signée ``` - **Le locataire écrit, les sites servent.** Les deux sites ne détiennent ni la zone en source, ni la clé DNSSEC. - **`only-notify` et `also-notify`** bornent les notifications aux adresses du contrat du site (`dns_public_site` et `dns_public_pairs`). Sans eux, le primaire notifierait les adresses publiques de ses NS, depuis l'intérieur du locataire. - **Le transfert passe par le lien** quand le secondaire est sur l'autre site : la frontière du site où vit le locataire laisse entrer le transfert et sortir les NOTIFY ; celle du site qui réplique pose une route `/32` vers chaque primaire. Le devis les dérive de la fiche que porte chaque locataire (où il vit), et P24 juge ces routes à part. ### Une requête de l'Internet ```mermaid sequenceDiagram participant R as Résolveur sur Internet participant F as Frontière
bifrost-1 ou requin participant D as dnsdist :1053 participant A as PowerDNS :53 R->>F: chezlepro.ca MX ? (port 53) Note over F: TechnoLibre : arrive par le relais et le tunnel opt9,
et repart par lui (reply-to RELAIS_GW) F->>D: redirection vers :1053 Note over D: refuse NOTIFY, UPDATE, AXFR · tronque ANY en UDP
débit borné par /24 D->>A: requête admise A-->>D: réponse signée D-->>R: réponse ``` **Sans `reply-to`, la réponse du site de TechnoLibre se perdrait** : elle repartirait par la route par défaut, le WAN, qui n'a qu'une adresse privée en amont (mesuré le 2026-10-13). ### Les flux | Flux | De | Vers | Port | Chemin | |---|---|---|---|---| | Requête publique | Internet | dnsdist du site | 53 → 1053, UDP et TCP | redirection de la frontière ; par le relais au site de TechnoLibre | | Requête admise | dnsdist | PowerDNS du site | 53, boucle de l'hôte | local | | NOTIFY | `pdns@public` du locataire | PowerDNS de chaque site | 53/UDP | local ; par le lien vers l'autre site | | SOA, puis AXFR TSIG | PowerDNS de chaque site | `pdns@public` du locataire | 5300, UDP puis TCP | local ; par le lien depuis l'autre site | | Résolution interne | machine du locataire | Unbound de son écosystème | 53 | dans l'écosystème | | Zone `.internal` | Unbound | PowerDNS principal | 5300, boucle locale | local | | Récursion | Unbound | Internet | 53 | sortie de la frontière | Ces flux sont déclarés par les rôles (`meta/flux.yml` de `serveur_dns_public`, `serveur_powerdns`, `serveur_resolveur`) et par le lien (`opnsense_liens_sites`) ; le devis de la frontière et le pare-feu Proxmox en dérivent leurs règles. Aucun n'est écrit à la main sur une frontière. ### Ce qui se déclare, et où | Clé | Fichier | Ce qu'elle décide | |---|---|---| | `autorite: primaire-cache`, `dnssec`, `enregistrements` | `plan/domaines.yml` du **locataire** | la zone est publique, signée, et ce qu'elle porte | | `dns_public_nom` | `plan/10-intrants.yml` du **site** | le nom de SON serveur de noms (`dns1.`) | | `dns_public_pairs` | plan du **site**, des deux côtés | le site pair qui réplique ; `inactif` n'émet rien | | `opnsense_liens_sites` | `opnsense.yml` du **site** | le tunnel que prennent NOTIFY et transferts | | `opnsense_wan_ip` | `opnsense.yml` du **site** | l'adresse publique de son serveur de noms | Le **contrat du site** (`make site-intrants`) en tire, pour chaque locataire, ce qu'il dépose dans sa fiche (`fiche-site.yml`) : `dns_public_site`, `dns_public_pairs`, `dns_public_nom` et `dns_public_noms_pairs` (le nom et l'adresse publique du serveur de chaque pair, lus dans **son** plan et **sa** carte, par les mêmes fonctions que pour le site lui-même). ### Les NS d'une zone ```mermaid flowchart LR PC["plan du site de Chezlepro
dns_public_nom: dns1.chezlepro.ca"] --> K["contrat du site
fiche du locataire"] PT["plan du site de TechnoLibre
dns_public_nom: dns1.technolibre.ca
+ opnsense_wan_ip"] -- "dns_public_noms_pairs" --> K K --> Z["zone-publique.db.j2
chez le locataire"] Z --> NS["chezlepro.ca — NS dns1.chezlepro.ca, NS dns1.technolibre.ca
A de dns1.chezlepro.ca : seulement dans chezlepro.ca
A de dns1.technolibre.ca : seulement dans technolibre.ca"] ``` - **Un site, un nom** : `dns1` sous le domaine de l'organisation qui tient le site. Pas `ns1`/`ns2`, qui existent en production à d'autres adresses. - **Seule la zone qui contient un nom en porte le A**, à l'adresse publique de **son** site. Les autres zones ne le désignent que par son nom. - **Sans pair, le rendu est identique octet pour octet** à celui d'un site seul. ### Les gardes | Garde | Où | Ce qu'elle refuse | |---|---|---| | relation des deux côtés | P82 (`prouver._dns_paires`) | un pair déclaré d'un seul côté — le second serveur serait vide sans que personne le voie | | un pair nomme son serveur | P82 (`prouver._dns_paires`) | un pair actif sans `dns_public_nom` — ses zones n'en désigneraient qu'un, alors qu'il les sert | | signé avant exposé | P82 | exposer un serveur public dont une zone n'est pas signée | | nom et adresse du pair | `serveur_powerdns` (`zones-publiques.yml`) | un nom mal formé, une adresse privée, un nom égal au nôtre, un nom redéclaré | | contrat déposé | `make site-intrants-verifier` | une fiche de locataire qui diffère du contrat (une adresse faussée la rend NON CONFORME) | | routes du lien | P24 | une route `/32` qu'aucune règle du lien n'utilise | | zone servie nue | sonde `zones-publiques` | une zone signée servie sans signature ; signatures sous 6 jours (avertit), sous 3 (alerte) | ### Basculer chez un registraire L'ordre, pour chaque domaine : 1. **`make dns-bascule-devis`** — rien ne serait perdu, et chaque serveur désigné résout déjà publiquement. 2. **La colle** chez le registraire du domaine qui contient le nom : `dns1.chezlepro.ca` chez celui de `chezlepro.ca`, `dns1.technolibre.ca` chez celui de `technolibre.ca`. 3. **Les deux NS** chez le registraire de la zone basculée. Zone signée, sans DS : le domaine reste « non sécurisé », pas cassé. 4. **Vérifier** depuis l'Internet, sur les deux adresses. 5. **Puis seulement le DS** (`make dnssec-ds`). Jamais l'inverse. **État au 2026-10-14** : les deux sites servent `chezlepro.ca` et `technolibre.ca` au même serial, chacune avec deux NS signés. **Ni la colle ni les NS ne sont encore chez les registraires.**