Mise à jour d'un enregistrement DNS avec une adresse IP dynamique

Le principe du script est simple, aller périodiquement interoger une page internet (dans mon cas ifconfig.me/ip) pour obtenir l'adresse IP de la machine qui fait tourner le script, mémoriser cette adresse. Si l'adresse a changé, alors il faut mettre à jour l'enregistrement DNS, et envoyer un mail.

Voici les grandes parties du script:

Récupérer l'ancienne adresse IP:

open(my $h, '>>', $ip_file) or die "cannot create file $!\n";
open(my $h, '<', $ip_file) or die "cannot read file: $!";
$old_ip = <$h>;
chomp $old_ip;
close ($h);

On notera le premier open, qui crée le fichier si celui-ci n'existe pas. Utile si, comme moi, vous stockez cette valeur dans `/tmp` qui est vidé à chaque redémarrage...
Le second appel à open appelle implicitement le `close` sur `$h`.

Obtenir l'adresse IP via la fonction `get()` fournie par le package LWP::Simple.

$new_ip = get($check_url);

Si ces deux valeurs sont différentes, utiliser l'API ovh pour mettre à jour le domaine.

Initialisation de la "session":

my $soap = SOAP::Lite
-> uri('https://soapi.ovh.com/manager')
-> proxy('https://www.ovh.com:1664');
#login
my $result = $soap->call( 'login' => ('<<OVH HANDLE>>', '<<OVH PASSWORD>>', 'fr', 0) );
print "login successfull\n";
my $session = $result->result();

Il faut préalablement avoir créé un champs de type `A` (qui fait correspondre un nom symbolique -le sous domaine- à une adresse IP), via le manager.
Pour mettre à jour une valeur, l'API requiert la valeur précédente contenue dans ce champs. C'est un peu pénible, mais je suppose que c'est pour éviter les erreurs.

Heuresement, l'API nous fournit une methode permettant de lister les entrées pour une zone DNS (`zoneEntryList`); il ne reste plus qu'à les parcourir à la recherche de celle qui nous intéresse.

my $result = $soap->call( 'zoneEntryList' => ($session, 'fser.info') );
print "zoneEntryList successfull\n";
my $return = $result->result();
my $oldvalue = '';
# search the previous value for << SOUS DOMAINE >>
foreach (@{$return}) {
        if ($_->{subdomain} eq '<< SOUS DOMAINE >>') {
                $oldvalue = $_->{target};
                next;
        }
}
print "Ancienne valeur DNS : $oldvalue\n";

On peut maintenant modifier l'entrée qui nous intéresse:

#zoneEntryModify
$soap->call( 'zoneEntryModify' => ($session, 'fser.info', 'box', 'A', $oldvalue, $new_ip) );
print "zoneEntryModify successfull\n";

Et se déconnecter:

#logout
$soap->call( 'logout' => ( $session ) );
print "logout successfull\n";

Enfin, on envoie un mail, le plus simplement du monde (ou presque, les options `-oi` et `-t` de sendmail -qui n'est pas sendmail, voir un autre poste ici même- m'ont sauvé la vie)

open(my $mail, '| /usr/sbin/sendmail -oi -t') or die "sendmail: $!";
print $mail join("\r\n", @headers);
print $mail "Was $old_ip; is now $new_ip\n";
close ($mail);

On oublie pas de mettre à jour le fichier témoin de l'ancienne adresse, pour éviter l'auto spam:

open (my $h, '>', $ip_file) or die "myfile: $!";
print $h $new_ip;
close($h);

Ne reste plus qu'à installer une cron pour ce script, par exemple toutes les 5 minutes:

$ crontab -e
# m h  dom mon dow   command
*/5 * * * * perl /path/to/script/dynip.pl

Et on peut utiliser dig pour vérifier le résultat, en utilisant le dns d'ovh utilisé par votre domaine, pour éviter un faux négatif (c'est à dire que vous croyez que votre domaine n'est pas mis à jour, alors qu'il l'est)

$ dig +short @ns10.ovh.net mondomaine
mon.ip.a.moi
$

Yata!

attachment: 

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.