Abysse Tech

Ma Vie Digitale

Comment créer votre propre DNS Dynamique

by

La tournée des fêtes arrivant je me précipite à faire en sorte de pouvoir accéder à certains de mes services hébergés à la maison pour pouvoir par exemple faire face à la conversation typique.

– A la maison:

Moi: « Quel film libre de droit veux tu voir? » Elle: « Je ne sais pas… »

– Endroit Random où je n’ai accès à rien du tout:

Elle: « Ce serait cool qu’on regarde ce film libre de droit »

Et forcément, moi j’oublie et je passe pour un guignol.

Du coup j’anticipe et je veux donc pouvoir à l’aube de Noel et les différentes vadrouilles pouvoir avec accès entre autres à Radarr.

 

Un DNS Dynamique est un nom de domaine qui est attaché à une IP qui change. Et comme depuis bien longtemps déjà Orange opte pour des IPs dynamiques et facture 18€ par mois le service d’une IP fixe; le DNS dynamique est incontournable.

Des solutions en ligne existent tels que no-ip.org qui va vérifier l’IP externe actuelle et l’attacher à un nom de domaine : maison.dyndns.com par exemple.

Du coup, si l’on rentre dans le navigateur maison.dyndns.com:portserveur on a pouvoir accéder depuis l’extérieur du réseau local à ce que l’on souhaite et ce en dépit d’une IP qui change tout le temps.

Oui mais sur la machine virtuelle hébergeant de multiples serveurs, j’allais donc installer le client no-ip.org et la je vois que l’host que j’avais enregistré a expiré. Je lis encore et je vois qu’il faut réactiver le domaine tous les mois ou payer.

La je me dis que c’est un peu too much pour just pour un simple refresh de l’IP du domaine.

Donc me voila parti pour une solution in-house.

 

PréRequis: 1. Avoir un nom de domaine 2. Hébergement cPanel (ici host-stage.net) 3. Un Serveur a accéder depuis l’extérieur 4. Port Forwarding sur votre routeur de votre IP locale vers l’extérieur 5. Un équipement Linux / Unix qui tourne 24/24 (NAS, Raspberry, Mac) Cela marche sur Windows aussi mais il faudra improviser pour le script bash en fin d’article qui permet d’automatiser le refresh. Cygwin est une option par exemple. Sinon la dernière Build de Windows 10 semble include le programme WGET et du coup au lieu d’un script bash, vous allez pouvoir créer un script bat.

Allez c’est parti. On plonge dans la configuration détaillé de votre propre service de DNS dynamique et entièrement gratis.

1. Dans un premier temps on va créer la zone DNS du serveur et on peut choisir ce que l’on veut:

-film.domaine.com -nimportequoi.domaine.com

Ici on peut créer autant de DNS que l’on a de serveurs, ou utiliser le même avec des ports différents. C’est comme vous souhaitez.

Dans cPanel on clique sur DNS Editor et on clique sur Add a Record:

On spécifie le sous domaine que l’on souhaite avoir en DNS dynamique, un TTL de 1800 (mise en cache DNS de 30 minutes), et une IP random pour commencer. Evitez de mettre la votre pour la phase de test.

 

2. Ensuite, on va uploader le script PHP suivant dans un répertoire de votre choix sur votre compte FTP de votre domaine.

*****Je vous invite très fortement à mettre un mot de passe pour éviter tout risque d’injection DNS et de réorienter les requêtes de votre serveur vers autre chose. (Directory Privacy dans cPanel, et pour la suite de l’article optez pour un mot de passe long mais sans caractères spéciaux. Normalement votre hébergeur bloquera toute tentative de brute force donc aucune chance de passer outre).***

Editer les valeurs dans le script ci dessous que vous allez nommer dyndns.php

< ?php // Based on the hard work of Mitchel Haan // https://haanenterprises.com/2013/04/host-your-own-dynamic-dns-using-php-and-cpanel-apis/ // // usage: // http://username:password@website.com/dyndns.php?hostname=remote&myip=192.168.1.1 // // per the settings below, the above will update the IP remote.example.com to 192.168.1.1 // myip is not required, will default to the remote IP calling the script // // most dyndns clients will work with a custom url setting. you will likely need to only // provide the subdomain and not the full address. // (ie: with this script, hostname=remote instead of hostname=remote.example.com /***** Variables *****/ #The username and password used by the updater to send the request. #HTTP Basic authentication $php_auth_user='username'; $php_auth_pw='password'; #The url of the cpanel server $dyndnsCpanel = 'https://example.com:2083'; #username and password used to login to cpanel $dyndnsCpanelUser = 'username'; $dyndnsCpanelPass = 'password'; #the main domain name of the account on cpanel $dyndnsDomain = 'example.com'; // Plain text output header('Content-type: text/plain'); if (!isset($_SERVER['PHP_AUTH_USER'])) { header('WWW-Authenticate: Basic realm="CPanel DynDyns"'); header('HTTP/1.0 401 Unauthorized'); die("badauth\n"); } if(!($_SERVER['PHP_AUTH_USER']==$php_auth_user && $_SERVER['PHP_AUTH_PW']==$php_auth_pw)) { sleep(10); die("badauth\n"); } // Make sure a host was specified if (empty($_GET['hostname'])) die("notfqdn\n"); // Use server value for IP if none was specified $ip = $_GET['myip']; if (empty($ip)) $ip = $_SERVER['REMOTE_ADDR']; // Validate IP address if (!filter_var($ip, FILTER_VALIDATE_IP)) die('Invalid IP address'); // Get and validate ttl $ttl = $_GET['ttl']; if (!is_numeric($ttl) || $ttl < 60) $ttl = 300; // Create class object $dyn = new DynDnsUpdater(); // Connection information $dyn->setCpanelHost($dyndnsCpanel); $dyn->setDomain($dyndnsDomain); // Set username $dyn->setCpanelUsername($dyndnsCpanelUser); // Set password $dyn->setCpanelPassword($dyndnsCpanelPass); $dyn->updateHost($_GET['hostname'], $ip); // End of processing exit; /**********************************/ /*** Function definitions below ***/ /**********************************/ class DynDnsUpdater { private $curl; private $cpanelHost; private $cpanelUsername; private $cpanelPassword; private $domain; /***** Constructor / Destructor *****/ function __construct() { // Create curl object $this->curl = curl_init(); $curlDefaults = array( CURLOPT_SSL_VERIFYPEER => false, // Allow self-signed certs CURLOPT_SSL_VERIFYHOST => false, // Allow certs that do not match the hostname CURLOPT_RETURNTRANSFER => true, // Return contents ); curl_setopt_array($this->curl, $curlDefaults); } function __destruct() { // Release curl object curl_close($this->curl); } /***** Setters *****/ function setCpanelHost($host) { $this->cpanelHost = $host; } function setCpanelUsername($username) { $this->cpanelUsername = $username; } function setCpanelPassword($password) { $this->cpanelPassword = $password; } function setDomain($domain) { $this->domain = $domain; } /***** Public Functions *****/ public function updateHost($host, $ip) { $hosts = $this->getHost($host); if ($hosts === false) return false; foreach ($hosts as $hostInfo) { if ($hostInfo['address'] == $ip) { echo "nochg $ip\n"; return true; } $updateParams = array( 'cpanel_jsonapi_module' => 'ZoneEdit', 'cpanel_jsonapi_func' => 'edit_zone_record', 'domain' => $this->domain, 'Line' => $hostInfo['Line'], 'type' => $hostInfo['type'], 'address' => $ip ); $result = $this->cpanelRequest($updateParams); if ($result) echo "good $ip\n"; else echo "Update failed: {$hostInfo['name']}\n"; } } /***** Private Functions *****/ private function getHost($host) { $fetchzoneParams = array( 'cpanel_jsonapi_module' => 'ZoneEdit', 'cpanel_jsonapi_func' => 'fetchzone_records', 'domain' => $this->domain, 'customonly' => 1 ); $result = $this->cpanelRequest($fetchzoneParams); if (empty($result['data'])) return false; // Get the payload $zoneFile = $result['data']; $hosts = array(); foreach ($zoneFile as $line) { if ( ($line['type'] == 'A') && ($host == DYNDNS_ALLHOSTS || (strcasecmp($line['name'], $host.'.') === 0)) ) { $hosts[] = $line; } } if (!empty($hosts)) return $hosts; else echo "nohost\n"; return false; } private function cpanelRequest($params) { if (empty($this->curl) || empty($params)) return false; curl_setopt($this->curl, CURLOPT_URL, $this->cpanelHost.'/json-api/cpanel?'.http_build_query($params)); curl_setopt($this->curl, CURLOPT_HTTPHEADER, array( 'Authorization: Basic ' . base64_encode($this->cpanelUsername.':'.$this->cpanelPassword)) ); $result = curl_exec($this->curl); $error = false; // Check for valid result if ($result === false) { echo curl_error($this->curl)."\n"; // If curl didn't return anything, there's nothing else to check return false; } // Check for error code if (curl_getinfo($this->curl, CURLINFO_HTTP_CODE) != '200') { $err = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); echo "Error $err\n"; $error = true; } // Attempt to process result $jsonResult = json_decode($result, true); if (empty($jsonResult)) { echo "Invalid JSON: \n".$result."\n"; return false; } // Check for cpanelresult object if (isset($jsonResult['cpanelresult'])) { $jsonResult = $jsonResult['cpanelresult']; } else { $error = true; } // Check for cpanel error if (isset($jsonResult['error'])) { echo $jsonResult['error']."\n"; $error = true; } if ($error) { // No sense going past here... no more information to get return false; } return $jsonResult; } } ?>

Il vous faudra donc remplacer les variables suivantes en début de script:

$php_auth_user='username'; //Utilisateur Apache que vous avez créé
$php_auth_pw='password'; //Mot de Passe Apache que vous avez créé
$dyndnsCpanel = 'https://example.com:2083'; //URL d'accès à cPanel
$dyndnsCpanelUser = 'username';//Utilisateur cPanel
$dyndnsCpanelPass = 'password';//Mot de passe cPanel
$dyndnsDomain = 'example.com';//Le nom de domaine racine pour lequel vous voulez créer une zone DNS.

3. Une fois votre script édité et uploadé vous allez pouvoir tester le changement d’IP de votre zone.

Essayez donc d’accéder au lien suivant:

http://utilisateur:password@domaine.com/repertoire/dyndns.php?hostname=serveur.domaine.com

Vous devriez avoir un message de confirmation avec votre adresse IP:

good 85.45.45.44

Vous allez pouvoir vérifier l’IP dans les entrées DNS directement dans cPanel.

 

Si vous avez une erreur vous pouvez changer la ligne

'customonly' => 1

en

'customonly' => 0

Bon, c’est bien beau, mais il faut automatiser le refresh. Cette partie sera propre à votre environment et de l’équipement qui tourne 24/24. Ici, je vais utiliser un NAS Synology mais un raspberry fonctionnera tout aussi bien.

4.  On va créer un petit script en bash que l’on va appeler toutes les 10 minutes pour refresh l’IP et dès que l’IP de votre box changera, vos entrées DNS seront à jour.

Je vais donc utiliser WGET avec un user agent car sans user agent, je n’arrivais pas à m’authentifier à Apache et j’obtenais une erreur 403.

Créer avec votre éditeur de texte le fichier dyndns.sh et remplacez les valeurs souhaitez

#!/bin/bash

wget -q -U 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20070802 SeaMonkey/1.1.4' --user=utilisateur --password=motdepasse http://www.domaine.com/repertoire/dyndns.php?hostname=serveur.domaine.com &> /dev/null

Vous pouvez bien sur copier la ligne wget -q pour autant de host que vous avez créés à la première étape.

5. Une fois votre script bash créé uploadez le où vous souhaitez. Si vous optez pour un NAS synology alors vous pouvez utiliser le planificateur de tâche inclus dans le DSM et du coup cela devra ressembler à ça:

 

 

Tout le crédit du script PHP vient de ce Github: https://github.com/ethanpil/dyndns-cpanel

Leave A Comment

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.