Le gros problème lorsque l’on veut des solutions d’auto-hébergement avec un nom de domaine vient souvent de notre adresse IP attribuée dynamiquement par notre fournisseur. Il y a bien les solutions des DNS dynamique comme synology.me ou internet-box.ch mais difficile de mettre en place un serveur mail ou web avec un sous-domaine. CloudFlare permet de mettre en place une solution viable, stable et performante. Voici en détail les étapes pour y parvenir.
Nom de domaine
Avant toute chose, il vous faut un nom de domaine. Il vous suffit d’en acheter un chez un registar. Il en existe des milliers. A vous de comparer les prix. Personnellement, ayant des domaines en .ch je me suis tourné vers Infomaniak qui sont très compétitifs. Il existe aussi OVH et Gandi qui ont de très bons retours.
CloudFlare
Votre nom de domaine acquis, il faut maintenant lui attribuer des serveurs DNS qui se chargerons de faire le lien entre votre IP et le nom. CloudFlare en possède plusieurs, pour savoir lesquels utiliser, il faut désormais inscrire votre domaine chez eux.
Inscription
Une fois cette étape passée, il faut maintenant inscrire notre nom de domaine
Ajout du domaine
Ajoutons notre domaine. Différents tests se font lors de l’ajout, laissez le site faire son check et cliquez sur dès que tout est terminé.
Continuez à la prochaine étape
C’est ici que nous allons donc définir les entrées “A” de notre domaine, elles sont au nombre de 3 minimum.
- *
- votredomaine
- www
Ces 3 entrées sont à saisir avec votre adresse IP actuelle
On sélectionne le plan gratuit
Et voici les deux DNS à entrer du côté de notre registar.
Serveur Mail
Sous-domaines
Ces deux chapitres seront décrits en détail dans un autre post, à venir dans le futur.
Mise à jour automatique
A partir de maintenant, vous avez un domaine qui est valide et redirige vers votre adresse IP (enfin, laissez 24h, le temps de répliquer les données sur les serveurs du monde entier 🙂 ) Mais, le jour où votre IP change, il faudra retourner modifier vos entrées. Et ça, c’est pas très pratique ni réactif !
Script PHP
Pour palier à ça, j’ai écrit un script PHP qu’il faudra exécuter automatiquement afin de détecter un changement d’adresse IP et de mettre à jour les entrées chez CloudFlare le cas échéant.
<?php header('Content-Type: text/plain'); $timestart=microtime(true); /** * @author Stéphane Rochat <contact@stephanerochat.ch> * @version 2.1 * @license http://creativecommons.org/licenses/by-nc/4.0/ */ /******* Documentations ******* API CloudFlare : https://api.cloudflare.com/ Clickatell : https://www.clickatell.com/apis-scripts/apis/http-s/ */ // User defined var /************* CloudFlare **********************/ // $CFtoken = 'TOKEN'; // This is the API key made available on your Account page. // $CFemail = 'EMAIL'; // The e-mail address associated with the API key // $CFdomain = 'DOMAIN.TLD'; // The target domain /**************** Mail *************************/ // $mailTo = 'EMAIL'; // Receiver of the mail // $mailFrom = 'EMAIL'; // From mail /************* Clickatell **********************/ // $CATusername = 'USERNAME'; // Clickatell username // $CATpwd = 'PASSWORD'; // Clickatell password // $CATapi = 'API'; // Clickatell API key // $CATTo ='PHONENUM'; // Receiver number phone // End of User defined var // Global var $userAgent = 'curl'; $curl_headers = array( 'X-Auth-Email: '.$CFemail, 'X-Auth-Key: '.$CFtoken, 'Content-Type: application/json'); // End of Global var // Get actual IP $contents = file_get_contents('http://api.ipify.org/?format=json'); $ipifyJson = json_decode($contents, true); unset($contents); if(!filter_var($ipifyJson['ip'], FILTER_VALIDATE_IP)) { exit('IP not valid !'); } // Get zone info (we need the ID) $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'https://api.cloudflare.com/client/v4/zones?name='.$CFdomain); curl_setopt($curl, CURLOPT_COOKIESESSION, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HTTPHEADER, $curl_headers); curl_setopt($curl, CURLOPT_USERAGENT, 'curl'); $CFZones = json_decode(curl_exec($curl), true); curl_close($curl); if($CFZones['success'] != 1) { echo $CFZones['errors'][0]['error_chain'][0]['message']."\n"; exit('Error getting zone from CloudFlare'); } // We have the ID, let's get "A" Records of the domain $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'https://api.cloudflare.com/client/v4/zones/'.$CFZones['result']['0']['id'].'/dns_records?type=A&?name='.$CFdomain); curl_setopt($curl, CURLOPT_COOKIESESSION, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HTTPHEADER, $curl_headers); curl_setopt($curl, CURLOPT_USERAGENT, 'curl'); $CFDNSRecords = json_decode(curl_exec($curl), true); curl_close($curl); $qtyRecords = $CFDNSRecords['result_info']['total_count']; $errCloudFlare = FALSE; $ipUpdated = FALSE; for ($i = 0; $i < $qtyRecords; $i++) { if($CFDNSRecords['result'][$i]['content'] <> $ipifyJson['ip']) { // Recreate values $data = array( 'type' => $CFDNSRecords['result'][$i]['type'], 'name' => $CFDNSRecords['result'][$i]['name'], 'content' => $ipifyJson['ip'] ); // Update it $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, 'https://api.cloudflare.com/client/v4/zones/'.$CFZones['result']['0']['id'].'/dns_records/'.$CFDNSRecords['result'][$i]['id']); curl_setopt($curl, CURLOPT_COOKIESESSION, true); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HTTPHEADER, $curl_headers); curl_setopt($curl, CURLOPT_USERAGENT, 'curl'); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($curl, CURLOPT_POSTFIELDS,json_encode($data)); $CFUpdateRecord = json_decode(curl_exec($curl), true); curl_close($curl); // Error handling if($CFUpdateRecord['success'] == '1') { $ipUpdated[] = $CFDNSRecords['result'][$i]['name']; } else { $errCloudFlare[] = array('name' => $CFDNSRecords['result'][$i]['name'], 'error' => $CFUpdateRecord['errors'][0]['error_chain'][0]['message']); } } } // Errors or IP updated ? Send a mail & SMS if($errCloudFlare || $ipUpdated) { // Gen text for errors if(is_array($errCloudFlare)) { $subject = 'IP Different - Error with CloudFlare'; $messageSMS = 'IP+changed,+new+is+:+'.$ipifyJson['ip'].'+-+Error+with+CloudFlare'; $messageMail = 'Errors :'."\n"; foreach ($errCloudFlare as &$value) { $messageMail .= 'Name : '. $value['name'] . ' / Error : '.$value['error']."\n"; } } // Gen text for success elseif(is_array($ipUpdated)) { $subject = 'IP Different'; $messageSMS = 'IP+changed,+new+is+:+'.$ipifyJson['ip']; $messageMail = 'Updated with new IP ('.$ipifyJson['ip'].') :'."\n"; foreach ($ipUpdated as &$value) { $messageMail .= $value."\n"; } } // Send Mail $headers = 'From: '.$mailFrom."\n"; $headers .= 'Content-type: text/plain'."\n"; $headers .= "X-Priority: 1 (Highest)\n"; $headers .= "X-MSMail-Priority: High\n"; $headers .= "Importance: High\n"; $page_load_time = microtime(true)-$timestart; $timeToExecute = "Script executed in " . $page_load_time . " sec"; $mailer = mail($mailTo, utf8_decode(stripslashes($subject)), utf8_decode(stripslashes($messageMail.$timeToExecute)), $headers); // Send SMS file_get_contents('http://api.clickatell.com/http/sendmsg?user='.$CATusername.'&password='.$CATpwd.'&api_id='.$CATapi.'&to='.$CATTo.'&text='.$messageSMS); exit('Executed, see mail or SMS for details'); } else { exit('No Change'); } ?>
Ce script nécessite un certain nombre de paramètres. Ils sont à remplir en début du fichier. Les voici en détail :
CloudFlare
$CFToken: Vous trouverez la clé API depuis votre compte (voir images ci-dessous)
$CFemail : L’email de votre compte chez CloudFlare
$CFdomain : Le nom de domaine que vous avez ajouté dans CloudFlare à l’étape précédente
$mailTo : Le destinataire du mail en cas de mise à jour
$mailFrom : L’expéditeur du mail
SMS (compte clickatell nécessaire)
$CATusername : Votre compte utilisateur
$CATpwd : Votre mot de passe
$CATapi : L’api HTTP
$CATTo : Le numéro de téléphone qui recevra le SMS
Exécution automatique du script
Il faut maintenant configurer votre DSM pour qu’il exécute le script toutes les 5min (j’ai volontairement choisi ce délai pour soulager les requêtes API)
- Placez le script à la racine de votre serveur web synology
- Ouvrez le planificateur de tâches
- Créez une nouvelle tâche (script défini par l’utilisateur)
- Utilisateur : root
- Script : curl -s http://127.0.0.1/test_IPAdress.php 2>&1 >> /dev/null
- Programmer : Quotidiennement / Première heure : 00:00 / Toutes les 5 min / Dernière heure : 23:55
- Et voilà !
N’hésitez pas à faire part de vos remarques, suggestions et problèmes dans les commentaires 🙂
Sources pour la rédaction de ce post :
Votre tuto et script sont juste magnifiques,
J’ai pu grâce a vous d’avoir un serveur accessible en tout moment par un nom de domaine professionnelle avec mon adresse ip dynamique.
Juste une question, est ce que les statistiques fourni par CloudFlare se réinitialisent a chaque changement d’ip sur ma zone dns ?
Bonjour,
Merci de votre commentaire et feedback 🙂
J’étais sûr d’y avoir répondu quelques jours après :/
Je n’utilise pas ce service, malheureusement je ne peux pas donner de réponse pour les stats. La logique voudrait que non.
Ping : Nouvelle version de l’API cloudflare = mise à jour du script de self hosting | Stéphane Rochat
Ping : Script CloudFlare mis à jour | Stéphane Rochat
Bonjour, nous sommes en 2019 est que cette config est toujours fonctionnelle?
Chez moi ça ne fonctionne pas, pouvez vous m’aider? merci d’avance
C’est toujours fonctionnel chez moi. Quel est le problème ?
Bsr, je vais tenter de le faire demain, et je vous tiendrai au courant.merci pour votre réponse.
Bonsoir Stephane, tu serai bien aimable de m’envoyer un script simple sans CLICKATELL et envois de mail. Merci d’avance
Il suffit de commenter les lignes 150 et 153 😉