/ Linux

Déployer 2 serveurs DNS autoritaires en maitre/esclave avec NSD via Docker

Un peu de contexte avant de passer à la mise en place :

Suite à une attaque DDOS sur un gros prestataire américain (Dyn), certains mastodontes américains (Twitter/Spotify/Netflix/PSN et beaucoups d'autres) ont été injoignables pendant plusieurs heures entre le 21 et 22 octobre 2016.

Dans l'histoire la faute ne revient pas à Dyn, une attaque DDOS de cet ampleur est difficillement parable sauf si on possède une bande passante suffisante, OVH ayant résisté sans trop de soucis à une attaque avec des pics à 1 Tbp/s parce qu'ils possèdent une infrastruture qui a la possibilité de recevoir une telle charge (ils ont une BP totale de 7 Tbp/s).

Mais avoir autant de bande passante c'est pas donné à tout le monde, et Dyn n'a pas pu résister à une telle attaque. Résultat, si Dyn tombe, l'ensemble des serveurs DNS autoritaires hébergés chez ce fournisseur tombent aussi. Ce qui est marrant (pas vraiment...) c'est que tous ces gros sites américains du TOP100 d'Alexa ont tous (presque) choisis Dyn pour gérer leur infra DNS sans prendre la peine de mettre en place un second prestataire en fallback.

Exemple avec twitter.com :

dig NS twitter.com +short

ns4.p34.dynect.net.
ns1.p34.dynect.net.
ns2.p34.dynect.net.
ns3.p34.dynect.net.

Tous les serveurs de noms de twitter sont hébergés chez Dyn et en plus sur le même AS (AS33517), ça sent un peu le sapin.

On va prendre un bon élève qui était toujours joignable pendant l'attaque DDOS : Pornhub. Parce que le porn n'attend pas :

dig NS pornhub.com +short

ns1.p44.dynect.net.
ns2.p44.dynect.net.
ns3.p44.dynect.net.
ns4.p44.dynect.net.
sdns3.ultradns.com.
sdns3.ultradns.net.
sdns3.ultradns.org.
sdns3.ultradns.biz.

Beaucoup mieux, là nous avons deux prestataires différents Dyn et UltraDNS sur deux AS différents (33517, 12008).

Donc actuellement (ça va changer j'imagine) twitter utilise uniquement Dyn pour héberger ses serveurs DNS autoritaires, c'est une mauvaise pratique parce que si ce prestataire tombe (et c'est ce qui est arrivé...), twitter ne sera plus joignable à partir du moment où l'enregistrement ne sera plus en cache du côté des serveurs des TLDs, des FAIs et des clients (à cause du TTL).

Mais déjà à la base, il y a quelque chose qui ne va pas pour que tous ces gros sites américains passent tous par le même prestataire, forcément il y a un réel intérêt pour quelqu'un de malveillant. Cibler un seul point central pour rendre indisponible une dizaine de sites du top 100 d'Alexa aux US et en Europe.... La centralisation c'est mal de toute manière et on en a un très bel exemple ici.

Mise en place

Maintenant que le contexte est posé, on va passer à la mise en place de deux serveurs maitre/esclave avec NSD et Docker.

Je vais être assez bref sur l'installation et la configuration, j'avais quasiment tout expliqué dans cet article : https://blog.meshup.net/deploy-nsd-dnssec-with-docker/

Ici j'ai ajouté la partie pour gérer le mode maitre/esclave fournit avec NSD.

Donc en prérequis, il faut avoir bien entendu deux serveurs différents, chez deux prestataires différents, sur 2 AS distincts. Personnellement, j'ai un serveur chez Ikoula et un serveur chez Online.net

Ensuite il faut déployer nsd sur ces deux serveurs de cette manière :

# https://github.com/hardware/nsd-dnssec

nsd:
  restart: always
  image: hardware/nsd-dnssec
  container_name: nsd
  ports:
    - "53:53"
    - "53:53/udp"
  volumes:
    - /mnt/docker/nsd/conf:/etc/nsd
    - /mnt/docker/nsd/zones:/zones
    - /mnt/docker/nsd/db:/var/db/nsd
mkdir -p /mnt/docker/nsd/{conf,zones,db}
chown -R 991:991 /mnt/docker/nsd

Configuration du serveur primaire

# /mnt/docker/nsd/conf/nsd.conf

server:
  server-count: 1
  ip4-only: yes
  hide-version: yes
  identity: ""
  zonesdir: "/zones"

remote-control:
  control-enable: yes

key:
   name: "sec_key"
   algorithm: hmac-sha256
   secret: "Q0zDiV9TRUNSw4hURQo=" # echo "CLÉ_SECRÈTE" | base64

zone:
  name: domain.tld
  zonefile: db.domain.tld.signed
  notify: IP_SERVEUR_SECONDAIRE sec_key
  provide-xfr: IP_SERVEUR_SECONDAIRE sec_key

Le block key permet de définir une clé secrète pour chiffrer les échanges entre le serveur maitre et le serveur esclave.

Dans le block zone, on retrouve deux directives importantes :

  • notify permet de définir l'adresse IP du serveur secondaire à notifier. NSD utilise un système d'ACL pour permettre la communication des différents serveurs maitre/esclave. La directive Notify permet définir le serveur esclave à contacter lorsque la commande nsd-control notify domain.tld est utilisée.

Exemple (logs du secondaire après un notify du primaire) :

[2016-10-22 14:31:13.895] nsd[7]: info: zone domain.tld serial 2016102201 is updated to 2016102202.
  • provide-xfr permet de définir l'adresse IP des serveurs autorisés à effectuer des requêtes AXFR (via udp) sur le serveur maitre. Un serveur DNS secondaire a besoin de faire ce type de requête pour recevoir le contenu de la zone DNS et être ainsi capable de répondre de manière autoritaire aux clients.

Si vous souhaitez ajouter un serveur DNS public, celui de votre registrar par exemple, il suffit de ne pas préciser de clé avec NOKEY :

notify: IP_SERVEUR_SECONDAIRE NOKEY
provide-xfr: IP_SERVEUR_SECONDAIRE NOKEY

Configuration du serveur secondaire

# /mnt/docker/nsd/conf/nsd.conf

server:
  server-count: 1
  ip4-only: yes
  hide-version: yes
  identity: ""
  zonesdir: "/zones"

remote-control:
  control-enable: yes

key:
   name: "sec_key"
   algorithm: hmac-sha256
   secret: "Q0zDiV9TRUNSw4hURQo="

zone:
    name: domain.tld
    zonefile: db.domain.tld.signed
    allow-notify: IP_SERVEUR_PRIMAIRE sec_key
    request-xfr: AXFR IP_SERVEUR_PRIMAIRE sec_key

De la même manière, on retrouve notre clé secrète sur le secondaire pour le chiffrement des échanges, par contre dans le block zone on retrouve deux nouvelles directives :

  • allow-notify permet de définir l'adresse IP des serveurs autorisés à notifier ce serveur esclave.
  • request-xfr permet de définir l'adresse IP des serveurs à requêter pour récupérer la zone DNS avec AXFR via UDP.

Lancement

docker-compose up -d nsd

Quelques commandes pratiques :

docker exec -ti nsd nsd-control reconfig
docker exec -ti nsd nsd-control reload domain.tld
docker exec -ti nsd nsd-control notify domain.tld

Ne pas oublier de mettre à jour vos NS dans votre zone et de prévenir le registrar de ce changement.

; ZONE : domain.tld
; ------------------------------------------------------------------
$ORIGIN domain.tld.
$TTL 7200

@       IN      SOA    ns1.domain.tld. hostmaster.domain.tld. (
                                        2016102203 ; Serial
                                        72000      ; Refresh
                                        1800       ; Retry
                                        1209600    ; Expire - 2 weeks
                                        86400 )    ; Minimum

; NAMESERVERS

@                   IN                NS                   ns1.domain.tld.
@                   IN                NS                   ns2.domain.tld.

@                   IN                A                    IPv4
ns1                 IN                A                    IPv4
ns2                 IN                A                    IPv4

@                   IN                AAAA                 IPv6
ns1                 IN                AAAA                 IPv6
ns2                 IN                AAAA                 IPv6


Déployer 2 serveurs DNS autoritaires en maitre/esclave avec NSD via Docker
Share this