Auto-hébergement, IP dynamique et DNS Gandi

Nicolas Mesnier

Mis à jour le 27/02/2022.

Si vous auto-hébergez vos services personnels Internet, chez vous, que vous avez un nom de domaine chez Gandi mais que votre fournisseur d’accès Internet (FAI), comme Orange, ne vous offre pas d’IP publique fixe, il vous faudra mettre à jour vos enregistrements DNS à chaque changement d’adresse IP (pouvant survenir n’importe quand, le plus souvent au redémarrage ou à la mise à jour de votre box) ; ce qui peut vite devenir très pénible car cela implique :

Si certain⋅e⋅s s’y soumettent un temps, il est proprement impensable de faire comme cela dans un contexte automatisé visant la plus grande disponibilité. Malheureusement, on trouve sur Internet assez peu de ressources vulgarisées (j’ai vu ça, ou ça, qui pointe sur ça), alors qu’en se basant sur la documentation de la dernière version de l’API de gandi et en s’inspirant de ce script, la mise à jour de votre IP publique peut être réalisée simplement avec le script bash :

#!/usr/bin/env bash
IP=$(curl -s4 http://me.gandi.net)
API="https://api.gandi.net/v5/livedns"
APIKEY=<VOTRE API KEY>
DOMAIN=<VOTRE DOMAINE>
RECORD="@"
DATA='{"rrset_values": ["'$IP'"]}'
curl -s -XPUT -d "${DATA}" \
     -H"Authorization: Apikey ${APIKEY}" \
     -H"Content-Type: application/json" \
     "${API}/domains/${DOMAIN}/records/${RECORD}/A"

Évidemment, avant de l’ajouter tel quel à votre crontab, il est préférable de ne solliciter l’API que si l’IP publique a changé. On gardera sa trace dans un fichier PublicIP.log dont on ne conservera que les 100 derniers changements (pour limiter l’inflation du fichier, en mode rotation à l’ancienne).

#!/usr/bin/env bash
LOGFILE="PublicIP.log"
API="https://api.gandi.net/v5/livedns"
APIKEY=<VOTRE API KEY>
DOMAIN=<VOTRE DOMAINE>
RECORD="@"

# Get current IP
IP=$(curl -s4 http://me.gandi.net)

__UPDATE_IP__(){
    # change IP using gandi's API
    DATA='{"rrset_values": ["'${IP}'"]}'
    curl -s -XPUT -d "${DATA}" \
        -H"Authorization: Apikey ${APIKEY}" \
        -H"Content-Type: application/json" \
        "${API}/domains/${DOMAIN}/records/${RECORD}/A"
}

__LOGS__(){
    # rotate and update logs
    echo "$(tail -n99 ${LOGFILE})">${LOGFILE}
    echo -e "${IP}\t IP changed $(date +'on %d/%m/%Y at %T')."\
        >>${LOGFILE}
}

if [[ -f ${LOGFILE} ]]; then
    # Read current API IP
    CIP=$(tail -n1 ${LOGFILE} | cut -d" " -f1)
    if [ ${IP} != ${CIP} ];then
        __UPDATE_IP__ && __LOGS__ 
    fi
else
    # create log file
    echo -e "${IP}">${LOGFILE}
fi

Enregistrez-le sous le nom gandi.sh dans votre home d’administrateur puis éditez votre crontab

$ crontab -e

pour planifier la vérification/mise à jour toutes les 10 minutes en ajoutant la ligne

*/10 * * * * /bin/bash /home/$(whoami)/gandi.sh


BONUS

On peut même envisager d’informer par mail l’administrateur du nom de domaine du changement d’IP publique pour garder une trace. Pour cela :

Il vient alors le script gandi.sh de gestion dynamique d’enregistrement DNS chez Gandi, reproduit ci-dessous :

#!/usr/bin/env bash
#=======================================================================
#  Shell script to update my public IP on gandi.net 
#  using their API (https://api.gandi.net/docs/livedns/)
#  and send me an email to keep track of change.
#
#  Copyright (C) 2022 Nicolas Mesnier <nmesnier@free.fr>
# 
#  This shell script is free software: you can redistribute it and/or
#  modify it under the terms of the GNU GPL version 3 or above.
#=======================================================================
LOGFILE="PublicIP.log"
API="https://api.gandi.net/v5/livedns"
APIKEY=<VOTRE API KEY>
DOMAIN=<VOTRE DOMAINE>
RECORD="@"
DEST=<EMAIL ADMIN>

# Get current IP
IP=$(curl -s4 http://me.gandi.net)

__UPDATE_IP__(){
    # change IP using gandi's API
    DATA='{"rrset_values": ["'${IP}'"]}'
    curl -s -XPUT -d "${DATA}" \
        -H"Authorization: Apikey ${APIKEY}" \
        -H"Content-Type: application/json" \
        "${API}/domains/${DOMAIN}/records/${RECORD}/A"
}

__SEND_MAIL__(){
    # send mail to admin
    mail -s "update public IP on gandi" ${DEST} <<-EOT
    This this an automatic email to keep track of your public IP change
    for ${DOMAIN}
    from old public IP: ${CIP}
    to new public IP: ${IP}
    EOT
}

__LOGS__(){
    # rotate and update logs
    echo "$(tail -n99 ${LOGFILE})">${LOGFILE}
    echo -e "${IP}\t IP changed $(date +'on %d/%m/%Y at %T')."\
        >>${LOGFILE}
}

if [[ -f ${LOGFILE} ]]; then
    # Read current API IP
    CIP=$(tail -n1 ${LOGFILE} | cut -d" " -f1)
    if [ ${IP} != ${CIP} ];then
        __UPDATE_IP__ && (__LOGS__ ; __SEND_MAIL__ )
    fi
else
    # create log file
    echo -e "${IP}">${LOGFILE}
fi