Gérer ses noms de domaine avec Knot et NSD

Publié le 12/06/2022 et écrit par Vincent Finance, dans la catégorie : #infra

Dans la vie d'un adminsys, chaque service / brique logicielle a son niveau de criticité et son importance. Parmi eux, l'un des plus cruciaux n'est autre que le DNS. Ici, je vais donc vous décrire comment je gère mes différentes zones DNS et quelle configuration est actuellement en place, notamment pour Automario.

Les configurations présentes dans cet article ont été testées avec succès sur OpenBSD 6.8/6.9/7.0/7.1 et sur CentOS 8.

Principes de base

DNS

Le DNS (Domain Name System ou système de nom de domaine) est un service distribué qui sert à traduire les noms de domaine en adresses IP, afin de faciliter les connexions entre machines avec une série de caractères facilement mémorisables. Concrètement, il s'agit d'un système combinant plusieurs "annuaires" et les distribuant partout sur Internet, ce qui permet à n'importe qui d'aller sur une des machines hébergeant le site de Wikipedia en tapant www.wikipedia.org.

DNSSEC

DNSSEC est un protocole standardisé qui est utilisé pour protéger une zone DNS et régler certains problèmes de sécurité au niveau du DNS. Le principe est de signer la zone DNS et de publier cette signature dans la zone, afin de récupérer celle-ci et donc de valider son origine.
Ce protocole permet notamment de lutter contre le DNS cache poisoning, un type d'attaque qui consiste à faire passer comme légitime une requête DNS contenant une autre adresse IP que celle qui est réellement utilisée, pour renvoyer le visiteur sur une autre machine, notamment pour faire de l'hameçonnage et récupérer des mots de passe ou des informations personnelles.

Serveur d'autorité principal

Un serveur d'autorité principal est un serveur DNS qui sert de référence pour une zone précise : c'est lui qui fournit toutes les informations concernant un nom de domaine et ses sous-domaines. Le serveur principal est également en charge des modifications : c'est sur lui qu'on effectue les modifications qui affecteront toute la zone (ajout, suppression ou modification d'entrées).

Serveur d'autorité secondaire

Un serveur d'autorité secondaire remplit la même mission qu'un serveur d'autorité principal, à un détail près : il ne gère pas les modifications, mais sert de serveur de secours. Si le serveur principal n'est pas joignable, c'est lui qui prend la suite des requêtes DNS. Cela permet ainsi de garder la zone synchronisée avec le reste d'Internet.
Une zone peut avoir plusieurs serveurs secondaires, multipliant ainsi les solutions de repli en cas de panne. Par exemple, Automario en a deux dans deux AS (Autonomous System) différents.

Description de ma configuration

Mes noms de domaines sont gérés selon le principe suivant :

Si on compile ça dans un schéma, on obtient ceci :

 +--------------+                                    +--------------+
 |              |                       +----------->+              |
 |  VPN @ home  +<--------+             v            |   obsda.ms   |
 |              |         v xxxx   xxxxxx            |              |
 +--------------+        xxx   xxxx     xx           +--------------+
                        xxx              xxx
                       xx                 xxx
                       xx     Internet       xx
                        x                     xx
                        xxx                xxxx
 +--------------+         xxxx  xx         x ^       +--------------+
 |              |          ^ xxxxx       xxx |       |              |
 |   ARN FAI    +<---------+      xxxxxxxx   |       | ledzep / NS1 |
 |              |                            +------>+              |
 +--------------+                                    +--------------+

Mise en place d'un serveur DNS principal

Avec NSD

NSD est un serveur DNS plus jeune que BIND et qui a l'avantage d'être léger et plus simple à utiliser que ce dernier. Il est très bien pour faire office de serveur d'autorité et pour gérer des noms de domaine, mais il ne peut pas servir de résolveur comme BIND ou Unbound.
Dans cet exemple, je vais mettre en place un serveur principal (ou master) pour deux zones DNS distinctes. Il communiquera avec deux autres serveurs DNS qui seront utilisés comme serveur secondaire (ou slave), à l'aide d'une clé TSIG pour l'authentification. Cela permet d'identifier les serveurs et surtout de bloquer les autres machines qui chercheraient à contrôler la zone DNS. Le serveur écoutera en IPv4 et en IPv6.

## Config file for NSD
# Master DNS

server:
    server-count: 2
    hide-version: yes
    ip-address: x.x.x.x
        ip-address: 2a00:xxxx:yyyy:zzz::10
        debug-mode: no
        verbosity: 2
    zonesdir: "/etc/nsd/zones/"

remote-control:
        control-enable: yes
    control-interface: /var/run/nsd.sock

key:
        name: "clesecrete"
        algorithm: hmac-sha256
        secret: "masuperchainedecarac="

zone:
    name: "vinishor.xyz"
    zonefile: "vinishor.xyz"
    notify: y.y.y.y clesecrete
    provide-xfr: y.y.y.y clesecrete
    notify: z.z.z.z clesecrete
        provide-xfr: z.z.z.z clesecrete
        notify: 2100:xxxx:yyyy:zzz::20 clesecrete
    provide-xfr: 2100:xxxx:yyyy:zzz::20 clesecrete
    notify: 2100:xxxx:yyyy:zzz::30 clesecrete
        provide-xfr: 2100:xxxx:yyyy:zzz::30 clesecrete

zone:
    name: "automario.eu"
    zonefile: "automario.eu"
    notify: y.y.y.y clesecrete
    provide-xfr: y.y.y.y clesecrete
    notify: z.z.z.z clesecrete
        provide-xfr: z.z.z.z clesecrete
        notify: 2100:xxxx:yyyy:zzz::20 clesecrete
    provide-xfr: 2100:xxxx:yyyy:zzz::20 clesecrete
    notify: 2100:xxxx:yyyy:zzz::30 clesecrete
        provide-xfr: 2100:xxxx:yyyy:zzz::30 clesecrete

La variable server-count sert ici à lancer plusieurs instances de NSD, notamment pour assurer son bon fonctionnement. hide-version est quant à lui un moyen de masquer la version de NSD, ce qui permet de ne pas divulguer cette information sur Internet et de ralentir les petits malins qui voudraient exploiter une potentielle faille (technique de la sécurité par l'obscurité). Les adresses IPv4 et IPv6 sont spécifiés séparément.
Les options notify et provide-xfr servent enfin à envoyer les informations de la zone aux serveurs secondaires et à initier la connexion entre les machines.

Avec Knot

Knot fonctionne de la même manière que NSD, mais il a l'avantage d'utiliser YAML pour sa syntaxe et de gérer tout seul DNSSEC, ce qui est un gros plus par rapport à NSD et BIND. Dans le cas de la zone pour openbsd.fr.eu.org, vu que DNSSEC avait été mis en place auparavant, cela me semblait être un gros plus. Comme avec NSD, l'exemple montre la configuration d'un serveur principal qui utilise une clé TSIG pour l'authentification avec les serveurs secondaires et des listes d'accès (ACL) :

# This is the main configuration for Knot DNS
# See knot.conf(5) or refer to the server documentation.

server:
    version: ""
    rundir: "/var/run/knot"
    user: _knot:_knot
    listen: [ x.x.x.x@53, 2a00:xxxx:yyyy:zzz::10@53 ]

log:
  - target: syslog
    any: info

database:
    storage: "/var/db/knot"

key:
  - id: clesecrete
    algorithm: hmac-sha256
    secret: masupercledecarac=

remote:
  - id: arn
    address: [y.y.y.y@53, 2100:xxxx:yyyy:zzz::20@53]
    key: clesecrete

  - id: ledzep
    address: [z.z.z.z@53, 2100:xxxx:yyyy:zzz::30@53]
    key: clesecrete

acl:
  - id: key_rule
    key: clesecrete
    action: [transfer, notify, update]

template:
  - id: classic
    storage: "/var/db/knot/main"
    file: "%s.zone"
    semantic-checks: on
    zonefile-load: difference

  - id: secondary
    storage: "/var/db/knot/secondary"
    file: "%s.zone"
    semantic-checks: on
    zonefile-load: difference

  - id: secure
    storage: "/var/db/knot/secure"
    file: "%s.zone"
    semantic-checks: on
    dnssec-signing: on
    dnssec-policy: default
    zonefile-load: difference

zone:
    # Zone with DNSSEC
  - domain: openbsd.fr.eu.org
    template: secure
    notify: [ledzep, arn]
    acl: key_rule

Voici quelques précisions concernant cette configuration :

Mise en place d'un serveur DNS secondaire

Avec NSD

Sur le serveur secondaire, la configuration de NSD ressemble beaucoup à celle présente au-dessus, tout en étant plus courte :

## Config file for NSD
# Secondary DNS

server:
        server-count: 2
    ip-address: y.y.y.y
        ip-address: 2100:xxxx:yyyy:zzz::20
        debug-mode: no
        verbosity: 2
    zonesdir: "/var/nsd/zones/"

remote-control:
        control-enable: yes
    control-interface: /var/run/nsd.sock

key:
        name: "clesecrete"
        algorithm: hmac-sha256
        secret: "masuperchainedecarac="

# Secondaires
zone:
        name: "vinishor.xyz"
        zonefile: "slave/vinishor.xyz"
    allow-notify: x.x.x.x clesecrete
        request-xfr:  x.x.x.x clesecrete
        allow-notify: 2a00:xxxx:yyyy:zzz::10 clesecrete
        request-xfr:  2a00:xxxx:yyyy:zzz::10 clesecrete

zone:
        name: "automario.eu"
        zonefile: "slave/automario.eu"
    allow-notify: x.x.x.x clesecrete
        request-xfr:  x.x.x.x clesecrete
        allow-notify: 2a00:xxxx:yyyy:zzz::10 clesecrete
        request-xfr:  2a00:xxxx:yyyy:zzz::10 clesecrete

On notera ainsi que la section zone utilise l'adresse IP du serveur principal avec les instructions allow-notify et request-xfr. Ces deux instructions servent à envoyer les requêtes pour récupérer les zones DNS et leurs mises à jour et autoriser les flux entre les deux serveurs. La clé secrète est également identique, vu qu'elle sert d'équivalent mot de passe.
Cette configuration fonctionne aussi bien pour une zone classique que pour une zone utilisant DNSSEC. C'est pour cette raison que je n'utilise que NSD dans le cas d'un serveur secondaire.

Avec Knot

Même si mon serveur principal sous Knot sert aussi de serveur secondaire pour certaines de mes zones, voici la configuration correspondante pour obtenir un serveur secondaire :

# This is a sample of a minimal configuration file for Knot DNS.
# See knot.conf(5) or refer to the server documentation.

server:
    version: ""
    rundir: "/var/run/knot"
    user: _knot:_knot
    listen: [ y.y.y.y@53, 2100:xxxx:yyyy:zzz::20@53 ]

log:
  - target: syslog
    any: info

database:
    storage: "/var/db/knot"

key:
  - id: clesecrete
    algorithm: hmac-sha256
    secret: masupercledecarac=

remote:
  - id: main
    address: [x.x.x.x@53, 2a00:xxxx:yyyy:zzz::10@53]
    key: clesecrete

acl:
  - id: key_rule
    key: clesecrete
    action: [transfer, notify, update]

template:
  - id: classic
    storage: "/var/db/knot/main"
    file: "%s.zone"
    semantic-checks: on

  - id: secondary
    storage: "/var/db/knot/secondary"
    file: "%s.zone"
    semantic-checks: on

  - id: secure
    storage: "/var/db/knot/secure"
    file: "%s.zone"
    semantic-checks: on
    dnssec-signing: on
    dnssec-policy: default
    zonefile-load: difference

zone:
    # Secondary zone
  - domain: vinishor.xyz
    template: secondary
    master: main
    acl: key_rule

Quelques commandes pour utiliser Knot au quotidien

Afficher les clés DS pour DNSSEC

Pour terminer la configuration de DNSSEC sur une zone DNS, il convient de publier chez votre registraire ce qu'on appelle les clés DS. Ces clés sont calculées à partir des clés ZSK et KSK et permettent d'identifier et de confirmer l'origine des requêtes DNS. Pour une utilisation quotidienne, on utilise les clés DS générées sur la clé KSK.
Par défaut, au premier lancement, Knot génère tout seul le nécessaire, mais n'affiche pas les clés DS. Pour les afficher, on peut alors utiliser deux méthodes :

# keymgr openbsd.fr.eu.org list
xxxxxxxxxxxxxxxxxxxxxxxxxx ksk=no  zsk=yes tag=58970 algorithm=13 size=256  public-only=no  pre-active=0 publish=1653669698 ready=0 active=1653669698 retire-active=0 retire=0 post-active=0 revoke=0 remove=0
yyyyyyyyyyyyyyyyyyyyyyyyyy ksk=yes zsk=no  tag=45098 algorithm=13 size=256  public-only=no  pre-active=0 publish=1653669698 ready=1653669698 active=0 retire-active=0 retire=0 post-active=0 revoke=0 remove=0

# keymgr openbsd.fr.eu.org ds 45098 # 45098 = id de la clé KSK
openbsd.fr.eu.org. DS 45098 13 2 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
openbsd.fr.eu.org. DS 45098 13 4 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
$ drill @dns.openbsd.fr.eu.org -s openbsd.fr.eu.org DNSKEY
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 44910
;; flags: qr aa rd ; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0 
;; QUESTION SECTION:
;; openbsd.fr.eu.org.   IN  DNSKEY

;; ANSWER SECTION:
openbsd.fr.eu.org.  86400   IN  DNSKEY  256 3 13 xxxxxxxxxxxxxxxxxxx== ;{id = 58970 (zsk), size = 256b}
openbsd.fr.eu.org.  86400   IN  DNSKEY  257 3 13 yyyyyyyyyyyyyyyyyyy== ;{id = 45098 (ksk), size = 256b}

;; AUTHORITY SECTION:

;; ADDITIONAL SECTION:

;; Query time: 22 msec
;; SERVER: 46.23.94.78
;; WHEN: Sun Jun  5 18:18:07 2022
;; MSG SIZE  rcvd: 195
;
; equivalent DS records for key 58970:
; sha1: openbsd.fr.eu.org.  86400   IN  DS  58970 13 1 fffffffffffffffff
; sha256: openbsd.fr.eu.org.    86400   IN  DS  58970 13 2 ffffffffffffffffffffffffffffffffff
;
; equivalent DS records for key 45098:
; sha1: openbsd.fr.eu.org.  86400   IN  DS  45098 13 1 eeeeeeeeeeeeeeeee
; sha256: openbsd.fr.eu.org.    86400   IN  DS  45098 13 2 eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

Il suffit alors de copier-coller les enregistrements DS fournis par la console dans l'interface de votre registraire et d'attendre un peu le temps que le tout se synchronise. DNSSEC sera ensuite opérationnel sur votre domaine.

Gérer sa zone DNS avec Knot

Au premier lancement, Knot lit le fichier contenant votre zone DNS et le remplace par un format modifié, ce qui complique les modifications manuelles. Pour gérer les zones DNS, on peut utiliser le mode interactif de Knot : cela consiste à activer l'édition, entrer les modifications et valider le tout en commitant.
Un exemple valant mille mots, voici comment ajouter une entrée dans la zone DNS de openbsd.fr.eu.org :

# knotc zone-begin openbsd.fr.eu.org
# knotc zone-set openbsd.fr.eu.org @ 86400 SOA dns.openbsd.fr.eu.org. linuxmario.linuxmario.net. 2022052708 10800 3600 1209600 3600
# knotc zone-set openbsd.fr.eu.org www 86400 CNAME openbsd.fr.eu.org.
# knotc zone-diff openbsd.fr.eu.org
# knotc zone-commit openbsd.fr.eu.org

On a donc l'ordre :

Si vous faites beaucoup de modifications et que vous voulez éviter de tout casser sur votre zone, cette section de la documentation Knot vous permet de geler les mises à jour de zone par sécurité.

Conclusion

Avec cet article, vous avez maintenant toutes les cartes en main pour gérer proprement et simplement vos zones DNS. Après tout, pourquoi laisser son registraire s'occuper de vos DNS quand vous pouvez le faire vous-même !


Sources de l'article :


Un commentaire à ajouter ?

Pour ajouter votre commentaire, envoyez directement un mail ici