Débarrassez-vous de DynDNS en utilisant l'API de Gandi

Posté le 1 mars 2012

Amis auto-hébergés, cet article vous est principalement destiné et surtout si votre nom de domaine a été acheté chez Gandi. Pour les autres, l'information qui suit peut peut-être s'avérer intéressante, on ne sait jamais...

Si comme moi, votre FAI ne vous fourni malheureusement pas d'adresse IP fixe, la solution généralement utilisée afin de mettre à jour votre IP est de créer un compte chez un fournisseur tel que DynDNS ou encore No-IP qui vous propose alors de choisir un domaine dans une liste imposée (ex. : homelinux.org). Vous pourrez alors déclarer l'enregistrement d'un hôte (limité à un seul chez DynDNS) dans ce domaine et ainsi mettre à jour cet enregistrement via un outil tel que Ddclient. Vous devrez ensuite créer des alias (CNAME) sur votre propre domaine et les faire pointer vers votre enregistrement DynDNS nouvellement créé (ex. toto.homelinux.org).

Une autre solution, si vous avez la main sur les serveurs DNS qui hébergent votre domaine (il faut dans ce cas que ces serveurs aient, eux, une ip fixe), est d'utiliser cette méthode proposée par GuiguiAbloc. Je confirme que cela fonctionne très bien, je l'utilise en production au boulot.

Enfin, la solution que je vous propose maintenant ne fonctionne qu'avec les noms de domaines enregistrés et gérés chez Gandi puisqu'elle s'appuie sur leur nouvelle API. Cette API en XML RPC permet d'automatiser ce qu'il est possible de faire via l'interface d'administration grâce à des scripts. La doc officielle fourni des exemples pour les langages suivants: python, php, nodejs, perl, ruby et C.

J'ai écrit le script suivant en Python 2.x (si une version en Python 3.x vous intéresse, laissez-moi un commentaire.). Un simple interpréteur Python suffit à le faire fonctionner sur toutes les plateformes supportées par le langage. La mise en place est très simple, copiez-le où bon vous semble sur votre serveur, rendez-le exécutable et modifiez les constantes en entête de fichier pour les faire correspondre à vos besoins. Planifiez ensuite son exécution à intervalles réguliers à l'aide d'une tâche cron et c'est tout.

A noter que l'activation de l'API et la génération de la clé s'effectuent depuis l'interface Gandi la première fois, cette dernière permet de s'affranchir d'une authentification par mot de passe.

Voici donc le script commenté:

# -*- coding: UTF-8 -*-
import xmlrpclib, urllib2, time, re, sys

# API de Production
api = xmlrpclib.ServerProxy('https://rpc.gandi.net/xmlrpc/')

############ A Modifier #############

# URL de la page retournant l'ip publique
url_page = 'http://ifconfig.me/ip'

# Renseignez ici votre clef API générée depuis l'interface Gandi:
apikey = 'dshjhkqsdk566456dsjhgdj82k65hgdsuytzz'

# Domaine concerné
mydomain = 'mondomaineamoi.org'

# Enregistrement à modifier
myrecord = {'name': 'monserveur', 'type': 'A'}

# TTL
myttl = 300

# id de la zone concernée (à récupérer depuis l'interface Gandi) 
zone_id = xxxxxx

####################################

# Récupération de l'ancienne ip
oldip = api.domain.zone.record.list(apikey, zone_id, 0, myrecord)[0].get('value')

try:
    # Récupération de l'ip actuelle
    f = urllib2.urlopen(url_page, None, 10)
    data = f.read()
    f.close()
    pattern = re.compile('\d+\.\d+\.\d+\.\d+')
    result = pattern.search(data, 0)
    if result == None:
        print("Pas d'ip dans cette page.")
        sys.exit() 
    else:
        currentip = result.group(0)

    # Comparaison et mise à jour si besoin
    if oldip != currentip:
        # On cree une nouvelle version de la zone
        version = api.domain.zone.version.new(apikey, zone_id)
        # Mise a jour (suppression puis création de l'enregistrement)
        api.domain.zone.record.delete(apikey, zone_id, version, myrecord)
        myrecord['value'] = currentip
        myrecord['ttl'] = myttl
        api.domain.zone.record.add(apikey, zone_id, version, myrecord)
        # On valide les modifications sur la zone
        api.domain.zone.version.set(apikey, zone_id, version)
        api.domain.zone.set(apikey, mydomain, zone_id)
        print("Modification de l'enregistrement effectuée avec l'ip: %s" % currentip)
except urllib2.HTTPError, xmlrpclib.ProtocolError:
    print("Site indisponible.")
finally:
    sys.exit()

Vous pouvez également le télécharger en cliquant sur ce lien.

MAJ du 19/03/2012: Plusieurs personnes m'ont demandé comment retrouver l'id de zone dans l'interface Gandi, il suffit de se positionner sur le domaine de son choix, puis de cliquer sur le lien "Voir" en face de "Fichier de zone" dans la colonne "Serveur de noms". Une fenêtre s'ouvre permettant de visualiser le fichier de zone, l'id se trouve dans l'url de cette fenêtre: https://www.gandi.net/admin/domain/zone/XXXXXX/see/ (représenté par des X ici)

MAJ du 03/10/2012: Charly Caulet a fait quelques modifs en se basant sur ce script et a packagé le tout. Vous pourrez trouver tout cela sur son dépôt.

Commentaires

#1

utodeb, le 2 mars 2012 à 07:32 :

Bonjour,

L'équivalent est possible si l'on a acheté son ndd chez ovh :

http://guide.ovh.net/DynDns

A+

#2

Virtualced, le 2 mars 2012 à 08:25 :

Bonjour,

Pour info, si on a un nom de domaine chez OVH, il y a cette option ainsi que les clients qui vont bien, pour tous les OS... Et en prime les noms de domaine sont moins chers que chez Gandi. (J'ai pas d'actions chez eux, juste client satisfait depuis 1998)

#3

Fred, le 2 mars 2012 à 10:16 :

Merci pour cet article, il tombe à point en ce qui me concerne! (construction d'un petit serveur de mail perso).

En plus c'est vrai que la solution nom de domaine acheté + dyndns est assez sale, même si ça fonctionne.

Il y a cependant une alternative un peu plus élégante avec freedns.afraig.org (on peut choisir parmi les noms de domaines proposés, ou ajouter son propre domaine que l'on a acheté)

#4

Michel, le 3 mars 2012 à 20:47 :

Merci pour le boulot...
Juste une petite question:
J'ai récupéré mon API key chez Gandi mais je suis un peu dubitatif par la ligne suivante dans ton appli:
myrecord = {'name': 'monserveur', 'type': 'A'}
C'est quoi name, monserveur et type ? Je dois modifier cette ligne ?
Merci pour la réponse
mi

#5

Comète, le 3 mars 2012 à 22:53 :

@Michel: myrecord est ce qu'on appelle un dictionnaire, c'est un ensemble de clés : valeurs.
Si tu préfères, tu peux comparer 'name' et 'type' à des champs et 'monserveur' et 'A' à leurs valeurs respectives.

En clair, tu ne dois pas modifier 'name' et 'type' mais uniquement leurs valeurs. La valeur de 'name' ('monserveur') doit être remplacée par le nom de l'enregistrement DNS que tu veux mettre à jour. La valeur de 'type' est généralement 'A' dans ce cas précis d'utilisation mais peut aussi être remplacée par 'MX' pour un serveur SMTP par exemple.

#6

Mike, le 4 mars 2012 à 14:40 :

Remarque intéressante de @aegiap sur IRC : "les zones sur les serveurs {a,b,c}.dns.gandi.net sont reloadées toutes les 20/25 minutes"

#7

Bastien, le 6 mars 2012 à 11:57 :

Bonjour, et merci pour ce script bien pratique.

J'ai une petite question cependant, c'est la plate-forme de production que tu utilise et pas la plate-forme OT&E ?

Car j'ai activé la OT&E mais j'ai un message d'erreur au lancement du script :
xmlrpclib.Fault: <Fault 500037: 'Error on object : OBJECT_UNKNOWN (CAUSE_BADPARAMETER) [apikey: Invalid API key]'>

Merci

#8

Comète, le 6 mars 2012 à 14:39 :

@Bastien: Non c'est bien celle de Production que j'utilise, la plateforme OT&E est celle de test uniquement. Elle a une clé qui lui est propre aussi et une URL bien spécifique: https://rpc.ote.gandi.net/xmlrpc

d'où ton message d'erreur...

#9

Stéphane, le 10 mars 2012 à 12:52 :

Bonjour,

Merci pour ce script qui va me servir prochainement.

Juste 2 petites questions :

- la valeur de 'name' c'est bien un des serveur dns de gandi, par exemple : 'a.dns.gandi.net' ?

# Enregistrement à modifier
myrecord = {'name': 'a.dns.gandi.net', 'type': 'A'}

- l'id de la zone concerné à récupérer depuis l'interface Gandi, je ne vois pas à quoi cela correspond ni où la récupérer ?

Merci d'avance.

#10

Comète, le 10 mars 2012 à 17:17 :

@Stéphane:

Non la valeur de 'name' représente un enregistrement de type 'A' sur ton propre domaine. C'est l’adresse ip correspondant à cet enregistrement qui sera mise à jour par le script.

Par exemple, si ton serveur web est joignable à cette adresse http://www.monjolidomaine.org, dans ce cas tu as un enregistrement 'www' de déclaré dans ta zone. Du coup, la valeur de 'name' ici sera 'www' et c'est l'adresse ip de l'enregistrement 'www' qui sera mise à jour par le script régulièrement.

Suis-je bien clair ?

#11

BOUY, le 19 mars 2012 à 06:43 :

Même question que précédemment: l'id de zone... apparemment on la trouve dans le fichier de zone de Gandhi. Me concernant, il était indiqué 10300 mais à l'utilisation de cette valeur, ton appli me renvoit une erreur (cet utilisation ne peut utiliser cet id de zone)
Pourquoi ?
Merci pour la réponse

#12

Comète, le 19 mars 2012 à 15:11 :

@BOUY:

Désolé j'avais oublié de répondre à cette question. Je viens de mettre à jour l'article (à la fin) pour expliquer comment retrouver cet ID.

#13

mutuelle, le 12 avril 2012 à 15:17 :

Bien cool ce script pour les utilisateurs de gandhi !! ;)

#14

alexandre, le 12 avril 2012 à 15:24 :

Super info. voila une astuce qui va me servir rapidement

#15

Michael, le 19 mai 2012 à 09:35 :

Bonjour,

Merci pour ce script.

Je me demandais quel était le temps d'exécution idéal du script par cron ?

#16

michael, le 19 mai 2012 à 11:35 :

Si j'ai tout compris, cela signifie que l'on doit retirer des zones DNS le nom de domaine Dyndns et faire pointer les sous-domaines sur le nom de domaine Gandi ?

#17

Comète, le 19 mai 2012 à 18:55 :

@Michael: pour ma part, ma tâche cron s'exécute toutes les 5 minutes.
Sinon, oui si tes enregistrements pointaient vers ton enregistrement DynDNS, il faut évidemment le remplacer par un enregistrement de type A sur ton propre domaine et faire pointer les autres dessus.