Agence web » Actualités du digital » Comment faire rouler votre propre DNS dynamique avec AWS Route 53

Comment faire rouler votre propre DNS dynamique avec AWS Route 53

Si vous avez des serveurs qui fonctionnent à la maison, vous ne pourrez pas leur acheminer un domaine sans adresse IP statique. Au lieu de payer pour un service DNS dynamique, vous pouvez créer le vôtre à l'aide d'AWS Route 53.

Le DNS dynamique n'est pas compliqué

Le DNS dynamique est assez simple dans son concept. Un démon s'exécute sur la machine cliente et vérifie régulièrement l'adresse IP publique pour toute modification. Si l'adresse IP change, le démon envoie une mise à jour au fournisseur DNS, qui modifie l'enregistrement. Ceci est souvent offert en tant que service payant chez de nombreux registraires de domaine et fournisseurs DNS.

AWS n'a pas de service spécifique pour fournir un DNS dynamique, mais il est assez simple à configurer vous-même. La «façon AWS» de procéder consiste à configurer un événement CloudWatch qui déclenche une fonction Lambda en réponse aux changements d'infrastructure. (Bien que vous deviez probablement simplement utiliser un équilibreur de charge et un groupe de mise à l'échelle automatique dans la plupart des scénarios.)

Cependant, si vous souhaitez configurer un DNS dynamique pour un serveur domestique ou un autre appareil non AWS qui aura de fréquents changements d'adresse IP, l'écriture de scripts est assez facile. Route 53 propose des commandes CLI simples que vous pouvez utiliser pour mettre à jour les enregistrements DNS à partir de la ligne de commande; le raccordement à un travail cron qui recherche une modification de l'adresse IP publique et exécute l'AWS CLI fera le travail.

En ce qui concerne les prix, Route 53 ne coûte pas vraiment cher: des frais fixes de 0,50 $ par mois pour chaque nom de domaine, plus quelques frais mineurs pour les recherches DNS en fonction de l'utilisation. Les enregistrements sont gratuits (la recherche la plus courante), vous ne verrez donc probablement pas plus de quelques centimes par mois sur votre facture, sauf si vous générez un trafic important. À titre de comparaison, le prix de DynDNS commence à 55 $ par an.

Configuration du côté AWS des choses

Pour commencer, rendez-vous sur la console de gestion AWS Route 53. Si vous ne possédez pas de domaine, vous pouvez en enregistrer un sous «Domaines enregistrés» pour un prix relativement bon marché, généralement juste le prix des frais d'enregistrement de l'ICANN. Si votre domaine n'est pas actuellement sur Route 53, vous devrez le transférer, ce qui est un processus simple mais long.

Recherchez ou créez la zone hébergée pour votre domaine, qui contiendra tous les enregistrements. Vous devez noter l'ID de la zone hébergée, car vous en aurez besoin pour le script.

Vous souhaiterez créer un espace réservé A pour que le script ait quelque chose à référencer. Vous pouvez définir cela sur quelque chose qui n'est évidemment pas correct …255.255.255.255 fonctionnerait – pour tester la fonctionnalité du script.

Vous devrez également configurer l'AWS CLI, ce que vous pouvez faire avec:

curl "https://d1vvhvl2y92vvt.cloudfront.net/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

Et configurez-le avec les informations d'identification d'un utilisateur IAM avec:

aws2 configure

Écrire le script

Si vous voulez juste le script, vous pouvez vous référer à cet essentiel, mais nous expliquerons comment il est configuré, car il est cool. Si vous copiez et collez simplement, vous devrez modifier HOSTED_ZONE_ID et NAME variables pour correspondre à l'enregistrement que vous essayez de mettre à jour. Notez que ce script utilise également le aws2 CLI, que vous devrez modifier si vous utilisez la version 1.

Tout d'abord, nous aurons besoin d'un moyen d'obtenir notre adresse IP publique par programmation. Pour cela, nous pouvons utiliser l'API checkip.amazonaws.com d'AWS. C'est entièrement gratuit et il n'y a pas de limite de taux. Vous pouvez également utiliser api.ipify.org à cet effet, qui est également gratuit et illimité. Nous allons le charger dans une variable et l'enregistrer pour plus tard.

IP=$(curl https://api.ipify.org/)

Ensuite, nous devrons valider cela pour nous assurer d'avoir récupéré une adresse IP valide et non un code d'erreur ou quelque chose de mal formé. Il suffit de vérifier que l'entrée est des nombres séparés par des périodes est suffisant à cet effet, donc un peu de regex à côté du =~ L'opérateur (renvoie vrai si l'expression régulière correspond à l'entrée de gauche, très utile) fera l'affaire:

if (( ! $IP =~ ^(0-9){1,3}.(0-9){1,3}.(0-9){1,3}.(0-9){1,3}$ )); then
  exit 1
fi

Nous devrons comparer cela à notre ancienne adresse IP pour voir si quelque chose a changé. Nous pourrions stocker cela sur le disque sous forme de fichier dans /tmp/, mais c'est désordonné et sujet à des erreurs. Au lieu de cela, nous interrogerons Route 53 directement avec list-resource-record-setset filtrer l'adresse IP de l'enregistrement que nous essayons de mettre à jour avec jq:

aws2 route53 list-resource-record-sets --hosted-zone-id Z1VCYR76DBUXPL | 
jq -r '.ResourceRecordSets() | select (.Name == "'"$NAME"'") | select (.Type == "'"$TYPE"'") | .ResourceRecords(0).Value' > /tmp/current_route53_value

Cela le sauve /tmp/current_route53_value, que nous pouvons ensuite utiliser pour vérifier avec grep, ce qui est assez résistant:

if grep -Fxq "$IP" /tmp/current_route53_value; then
   echo "IP Has Not Changed, Exiting"
   exit 1
fi

Enfin, nous préparons la charge utile pour change-resource-record-sets. Cela doit être en JSON, nous allons donc sortir dans un fichier sur le disque et l'envoyer comme argument à la commande.

cat > /tmp/route53_changes.json << EOF
    {
      "Comment":"Updated From DDNS Shell Script",
      "Changes":(
        {
          "Action":"UPSERT",
          "ResourceRecordSet":{
            "ResourceRecords":(
              {
                "Value":"$IP"
              }
            ),
            "Name":"$NAME",
            "Type":"$TYPE",
            "TTL":$TTL
          }
        }
      )
    }
EOF

#update records
aws2 route53 change-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID --change-batch file:///tmp/route53_changes.json 

Tout est réuni pour former le script suivant. Vous voudrez changer le HOSTED_ZONE_ID et NAME variables pour correspondre à l'enregistrement que vous essayez de mettre à jour. Notez que NAME a une période à la toute fin.

#!/bin/bash

#Variable Declaration - Change These
HOSTED_ZONE_ID="XXXXXXXXXXXX"
NAME="example.com."
TYPE="A"
TTL=60

#get current IP address
IP=$(curl http://checkip.amazonaws.com/)

#validate IP address (makes sure Route 53 doesn't get updated with a malformed payload)
if (( ! $IP =~ ^(0-9){1,3}.(0-9){1,3}.(0-9){1,3}.(0-9){1,3}$ )); then
	exit 1
fi

#get current
aws2 route53 list-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID | 
jq -r '.ResourceRecordSets() | select (.Name == "'"$NAME"'") | select (.Type == "'"$TYPE"'") | .ResourceRecords(0).Value' > /tmp/current_route53_value

cat /tmp/current_route53_value

#check if IP is different from Route 53
if grep -Fxq "$IP" /tmp/current_route53_value; then
	echo "IP Has Not Changed, Exiting"
	exit 1
fi


echo "IP Changed, Updating Records"

#prepare route 53 payload
cat > /tmp/route53_changes.json << EOF
    {
      "Comment":"Updated From DDNS Shell Script",
      "Changes":(
        {
          "Action":"UPSERT",
          "ResourceRecordSet":{
            "ResourceRecords":(
              {
                "Value":"$IP"
              }
            ),
            "Name":"$NAME",
            "Type":"$TYPE",
            "TTL":$TTL
          }
        }
      )
    }
EOF

#update records
aws2 route53 change-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID --change-batch file:///tmp/route53_changes.json >> /dev/null

Configurez votre Crontab

Vous pouvez éditer votre crontab avec:

crontab -e

Vous pouvez configurer ce script pour qu'il s'exécute toutes les minutes, car il est assez léger. Donnez à cron un chemin vers votre script sur le disque. Vous pouvez envoyer la sortie vers un fichier journal ou /dev/null si vous ne voulez pas y faire face.

* * * * * /home/user/update_dns.sh >/dev/null 2>&1

★★★★★