From cd1de231f7ee86262542aabccc31504d7532ab79 Mon Sep 17 00:00:00 2001 From: Vincent Berry <37981730+vincentberry@users.noreply.github.com> Date: Fri, 5 Jul 2024 22:08:03 +0200 Subject: [PATCH 1/3] Refactor: Moved IP address and DNS update logic - Moved the block responsible for retrieving and comparing IP addresses for each subdomain and ipApiResponse is true. --- ddns_update.php | 59 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/ddns_update.php b/ddns_update.php index c5ba36d..ca3270f 100644 --- a/ddns_update.php +++ b/ddns_update.php @@ -129,6 +129,35 @@ function checkInternetConnection() $address = $ipData['ip']; writeToLog("🌐 Adresse IP actuelle : $address\n"); + writeToLog("🔍 VĂ©rification de l'IP pour $sub.$domain...\n"); + + if ($sub === "@") { + $ipyet = gethostbyname($domain); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. + } elseif ($sub === "*") { + $ipyet = gethostbyname("testdnsall." . $domain); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. + } else { + $ipyet = gethostbyname("$sub.$domain"); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. + } + + writeToLog("📊 IP actuelle : $address\n"); + writeToLog("📌 IP enregistrĂ©e : $ipyet\n"); + + if ($ipyet !== $address) { // Comparaison de la nouvelle IP et de celle en service. + $ch = curl_init(); + + $URL = "domain/" . $domain . "/version/active"; + $POSTFIELDS = "[{\"name\": \"$sub\",\"type\": \"$types\",\"changeType\": \"REPLACE\",\"records\": [{\"name\": \"$sub\",\"type\": \"$types\",\"priority\": 0,\"ttl\": 3600,\"data\": \"$address\"}]}]"; + $result = OnlineApi($URL, $POSTFIELDS, "PATCH"); + + if ($result === null) { + writeToLog("⏰ Erreur ENVOI pour $sub.$domain" . "\n"); + } else { + writeToLog("✅ IP mise Ă  jour avec succĂšs pour $sub.$domain\n\n"); + } + + } else { + writeToLog("🔄 IP inchangĂ©e pour $sub.$domain !\n\n"); + } } else { $error = error_get_last(); writeToLog("❌ Impossible de rĂ©cupĂ©rer l'adresse IP. Erreur : " . $error['message'] . "\n"); @@ -137,36 +166,6 @@ function checkInternetConnection() writeToLog("❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify.\n"); } } - - writeToLog("🔍 VĂ©rification de l'IP pour $sub.$domain...\n"); - - if ($sub === "@") { - $ipyet = gethostbyname($domain); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. - } elseif ($sub === "*") { - $ipyet = gethostbyname("testdnsall." . $domain); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. - } else { - $ipyet = gethostbyname("$sub.$domain"); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. - } - - writeToLog("📊 IP actuelle : $address\n"); - writeToLog("📌 IP enregistrĂ©e : $ipyet\n"); - - if ($ipyet !== $address) { // Comparaison de la nouvelle IP et de celle en service. - $ch = curl_init(); - - $URL = "domain/" . $domain . "/version/active"; - $POSTFIELDS = "[{\"name\": \"$sub\",\"type\": \"$types\",\"changeType\": \"REPLACE\",\"records\": [{\"name\": \"$sub\",\"type\": \"$types\",\"priority\": 0,\"ttl\": 3600,\"data\": \"$address\"}]}]"; - $result = OnlineApi($URL, $POSTFIELDS, "PATCH"); - - if ($result === null) { - writeToLog("⏰ Erreur ENVOI pour $sub.$domain" . "\n"); - } else { - writeToLog("✅ IP mise Ă  jour avec succĂšs pour $sub.$domain\n\n"); - } - - } else { - writeToLog("🔄 IP inchangĂ©e pour $sub.$domain !\n\n"); - } } } From 7789e85c34df040da2782d409daa3dc04fd6a29d Mon Sep 17 00:00:00 2001 From: Vincent Berry <37981730+vincentberry@users.noreply.github.com> Date: Sat, 6 Jul 2024 17:06:43 +0200 Subject: [PATCH 2/3] =?UTF-8?q?-Mis=20=C3=A0=20jour=20writeToLog=20pour=20?= =?UTF-8?q?arr=C3=AAter=20l'ex=C3=A9cution=20du=20script=20si=20le=20messa?= =?UTF-8?q?ge=20de=20journal=20contient=20'Fatal'.=20-Ajout=20d'une=20fonc?= =?UTF-8?q?tion=20pour=20v=C3=A9rifier=20si=20l'adresse=20IP=20r=C3=A9cup?= =?UTF-8?q?=C3=A9r=C3=A9e=20est=20publique.=20-Mis=20=C3=A0=20jour=20le=20?= =?UTF-8?q?script=20pour=20journaliser=20un=20message=20d'erreur=20si=20l'?= =?UTF-8?q?adresse=20IP=20n'est=20pas=20publique.=20-Ajout=20de=20la=20lim?= =?UTF-8?q?itation=20IPv4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 20 ++++-- ddns_update.php | 187 ++++++++++++++++++++++++++++-------------------- 2 files changed, 124 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index aacd2f5..1dfc086 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Le script vise Ă  automatiser la mise Ă  jour des enregistrements DNS A pour un sous-domaine spĂ©cifiĂ© chez les fournisseurs de services en ligne tels que Online.net. Cela est particuliĂšrement utile dans les scĂ©narios oĂč l'adresse IP de l'hĂŽte change rĂ©guliĂšrement. +⚠ Veuillez noter que ce script est actuellement limitĂ© Ă  la gestion des adresses IPv4 uniquement. Les adresses IPv6 ne sont pas prises en charge pour le moment. Assurez-vous que vos configurations et attentes sont alignĂ©es avec cette limitation. ⚠ + ## FonctionnalitĂ©s 1. **CompatibilitĂ© Multi-Fournisseurs:** Le script est conçu pour fonctionner avec les API de plusieurs fournisseurs de services, en se concentrant sur Online.net. @@ -54,6 +56,7 @@ services: - DOMAINS=exemple.fr,exemple-2.fr - SUBDOMAINS=@,* - TYPES=A + - CHECK_PUBLIC_IPv4=true #optional restart: unless-stopped ```` Les logs sont stockĂ© dans le docker `/usr/src/app/log` @@ -71,6 +74,7 @@ services: - DOMAINS=exemple.fr,exemple-2.fr - SUBDOMAINS=@,* - TYPES=A + - CHECK_PUBLIC_IPv4=true #optional dns: -8.8.8.8 restart: unless-stopped @@ -95,6 +99,7 @@ services: - DOMAINS=exemple.fr,exemple-2.fr - SUBDOMAINS=@,* - TYPES=A + - CHECK_PUBLIC_IPv4=true #optional dns: -8.8.8.8 command: ["php", "/usr/src/app/ddns_update.php"] @@ -105,12 +110,13 @@ services: php ddns_update.php ``` -| Variable | Description | -| --------------- | -------------------------------------------------------------------------------------------------------------- | -| `ONLINE_TOKEN` | Remplacez "MonTokenOniline.Net" par votre clĂ© API Online.net. Obtenez cette clĂ© depuis [la console Online.net](https://console.online.net/fr/api/access). | -| `DOMAINS` | Indiquez la liste de vos domaines sĂ©parĂ©s par des virgules. Par exemple, `exemple.fr,exemple-2.fr`. | -| `SUBDOMAINS` | SpĂ©cifiez les sous-domaines sĂ©parĂ©s par des virgules que vous souhaitez mettre Ă  jour. Utilisez `@` pour le domaine principal et `*` pour tous les sous-domaines (par exemple, `@,*`). | -| `TYPES` | Indiquez le type d'enregistrement DNS Ă  mettre Ă  jour. Par exemple, `A` pour un enregistrement de type Adresse IPv4. | -| `LOG_PATH` | (Optionnel) Le chemin du rĂ©pertoire pour les logs. Si vous souhaitez les stocker dans un volume, spĂ©cifiez le chemin ici (par exemple, `/log`). | +| Variable | Type | Description | +| --------------------- | :------- | -------------------------------------------------------------------------------------------------------------- | +| `ONLINE_TOKEN` | `string` | Remplacez "MonTokenOniline.Net" par votre clĂ© API Online.net. Obtenez cette clĂ© depuis [la console Online.net](https://console.online.net/fr/api/access). | +| `DOMAINS` | `string` | Indiquez la liste de vos domaines sĂ©parĂ©s par des virgules. Par exemple, `exemple.fr,exemple-2.fr`. | +| `SUBDOMAINS` | `string` | SpĂ©cifiez les sous-domaines sĂ©parĂ©s par des virgules que vous souhaitez mettre Ă  jour. Utilisez `@` pour le domaine principal et `*` pour tous les sous-domaines (par exemple, `@,*`). | +| `TYPES` | `A` or `AAAA` or `A,AAAA` | Indiquez le type d'enregistrement DNS Ă  mettre Ă  jour. Par exemple, `A` (par dĂ©faut) pour un enregistrement de type Adresse IPv4. | +| `CHECK_PUBLIC_IPv4` | `boolean` | (Optionnel) Si dĂ©fini Ă  true (par dĂ©faut), vĂ©rifie que l'adresse IP rĂ©cupĂ©rĂ©e est une adresse publique. Sinon, cette vĂ©rification est ignorĂ©e. | +| `LOG_PATH` | `string` | (Optionnel) Le chemin du rĂ©pertoire pour les logs. Si vous souhaitez les stocker dans un volume, spĂ©cifiez le chemin ici (par exemple, `/log`). | Ce README a Ă©tĂ© crĂ©Ă© avec le soutien d'une intelligence artificielle pour fournir des informations claires et utiles. diff --git a/ddns_update.php b/ddns_update.php index ca3270f..64c7cbe 100644 --- a/ddns_update.php +++ b/ddns_update.php @@ -4,14 +4,20 @@ $Online_Token = getenv('ONLINE_TOKEN'); $domains = explode(',', getenv('DOMAINS')) ?: ['']; $subdomains = explode(',', getenv('SUBDOMAINS')) ?: ['@', '*']; -$types = getenv('TYPES') ?: 'A'; +$types = 'A'; +$checkPublicIPv4 = getenv('CHECK_PUBLIC_IPv4') ?: 'true'; $logFilePath = getenv('LOG_FILE_PATH') ?: "/usr/src/app/log/log.log"; function writeToLog($message) { global $logFilePath; - file_put_contents($logFilePath, date('Y-m-d H:i:s') . " - $message", FILE_APPEND); - print_r($message); + file_put_contents($logFilePath, date('Y-m-d H:i:s') . " - $message\n", FILE_APPEND); + print_r($message . " \n"); + + // Si le message contient "Fatal", arrĂȘter l'exĂ©cution du script + if (stripos($message, 'Fatal') !== false) { + die("⛔ Script arrĂȘtĂ©\n"); + } } // Fonction pour vĂ©rifier l'API Online.net @@ -28,25 +34,26 @@ function OnlineApi($URL, $POSTFIELDS = "", $method = 'GET') $headers[] = 'Authorization: Bearer ' . $Online_Token; $headers[] = 'Content-Type: application/json'; // Correction du type de contenu curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - + $result = json_decode(curl_exec($ch), true); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $error = curl_error($ch); curl_close($ch); if ($httpCode == 200 || $httpCode == 201 || $httpCode == 202 || $httpCode == 203 || $httpCode == 204) { - return $result ?: "ok"; - }elseif ($httpCode == 401 && isset($result['code'])){ + return $result ?: "ok"; + } elseif ($httpCode == 401 && isset($result['code'])) { ApiErrorOnline($result['code']); return null; - }else{ - writeToLog("❌ Erreur cURL $httpCode : $error\n"); + } else { + writeToLog("❌ Erreur cURL $httpCode : $error"); return null; } } // Fonction pour gĂ©rer les erreurs spĂ©cifiques Ă  l'API Online.net -function ApiErrorOnline($httpCode) { +function ApiErrorOnline($httpCode) +{ $errorCodes = [ -1 => 'Erreur interne', 1 => 'ParamĂštre manquant', @@ -76,105 +83,133 @@ function ApiErrorOnline($httpCode) { // Fonction pour vĂ©rifier la connexion Internet function checkInternetConnection() { - $connected = @fsockopen("www.google.com", 80); + $connected = @fsockopen("www.google.com", 80); if ($connected) { fclose($connected); - writeToLog("✅ Connexion Internet valide\n"); + writeToLog("✅ Connexion Internet valide"); return true; } - writeToLog("❌ Erreur : Pas de connexion Internet.\n"); + writeToLog("❌ Erreur : Pas de connexion Internet."); return false; } -writeToLog("\n---------------------------------\n"); -writeToLog("đŸš© Script Start\n"); -writeToLog("đŸ’ČONLINE_TOKEN: " . $Online_Token . "\n"); -writeToLog("đŸ’Čdomains: " . json_encode($domains) . "\n"); -writeToLog("đŸ’Čsubdomains: " . json_encode($subdomains) . "\n"); -writeToLog("đŸ’Čtype: " . $types . "\n"); -writeToLog("đŸ’ČlogFilePath: " . $logFilePath . "\n"); +// Fonction pour vĂ©rifier si c'est bien une IPv4 Public +function isPublicIPv4($IPv4, $checkPublicIPv4) +{ + if ($checkPublicIPv4) { + // Plages d'adresses IP privĂ©es + $privateRanges = [ + '10.0.0.0|10.255.255.255', // 10.0.0.0 - 10.255.255.255 + '172.16.0.0|172.31.255.255', // 172.16.0.0 - 172.31.255.255 + '192.168.0.0|192.168.255.255' // 192.168.0.0 - 192.168.255.255 + ]; + + // Convertit l'adresse IP en entier pour la comparaison + $IPv4Long = ip2long($IPv4); + + foreach ($privateRanges as $range) { + list($start, $end) = explode('|', $range); + if ($IPv4Long >= ip2long($start) && $IPv4Long <= ip2long($end)) { + writeToLog("❌ L'adresse IP rĂ©cupĂ©rĂ©e n'est pas une adresse IPv4 publique : $IPv4"); + return false; + } + } + writeToLog("✅ L'adresse IP rĂ©cupĂ©rĂ©e est une adresse IPv4 publique"); + } + return true; +} + +writeToLog("\n---------------------------------"); +writeToLog("đŸš© Script Start"); +writeToLog("đŸ’ČONLINE_TOKEN: " . $Online_Token); +writeToLog("đŸ’Čdomains: " . json_encode($domains)); +writeToLog("đŸ’Čsubdomains: " . json_encode($subdomains)); +writeToLog("đŸ’Čtype: " . $types); +writeToLog("đŸ’ČcheckPublicIPv4: " . $checkPublicIPv4); +writeToLog("đŸ’ČlogFilePath: " . $logFilePath); // VĂ©rification des valeurs des variables d'environnement if (empty($Online_Token) || empty($domains) || empty($subdomains) || empty($types) || empty($logFilePath)) { - writeToLog("⛔ Fatal : Veuillez fournir des valeurs valides pour les variables d'environnement.\n"); - die("⛔ Done !"); -}else{ - writeToLog("✅ Variables d'environnement valide\n"); + writeToLog("⛔ Fatal : Veuillez fournir des valeurs valides pour les variables d'environnement."); +} else { + writeToLog("✅ Variables d'environnement valide"); } //vĂ©rification de la connection internet if (!checkInternetConnection()) { - writeToLog("❌ Fatal : Veuillez vĂ©rifier votre connexion Internet pour l'initialisation.\n"); - die("⛔ Done !"); + writeToLog("⛔ Fatal : Veuillez vĂ©rifier votre connexion Internet pour l'initialisation."); } // VĂ©rification de l'API Online.net $userInfo = OnlineApi("user", ""); if ($userInfo === null) { - writeToLog("⛔ Fatal : VĂ©rification de l'API Online.net a Ă©chouĂ©.\n"); - die("⛔ Done !\n"); -}else{ - writeToLog("✅ API Online.net valide de ".$userInfo['last_name'] . " " . $userInfo['first_name']." \n\n"); + writeToLog("⛔ Fatal : VĂ©rification de l'API Online.net a Ă©chouĂ©."); +} else { + writeToLog("✅ API Online.net valide de " . $userInfo['last_name'] . " " . $userInfo['first_name'] . " \n"); } while (true) { - foreach ($domains as $domain) { - foreach ($subdomains as $sub) { - // RĂ©cupĂ©ration de l'IP du client appelant la page. - $ipApiResponse = @file_get_contents("https://api64.ipify.org?format=json"); - - if ($ipApiResponse !== false) { - $ipData = json_decode($ipApiResponse, true); - $address = $ipData['ip']; - - writeToLog("🌐 Adresse IP actuelle : $address\n"); - writeToLog("🔍 VĂ©rification de l'IP pour $sub.$domain...\n"); - - if ($sub === "@") { - $ipyet = gethostbyname($domain); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. - } elseif ($sub === "*") { - $ipyet = gethostbyname("testdnsall." . $domain); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. - } else { - $ipyet = gethostbyname("$sub.$domain"); // RĂ©cupĂ©ration de l'IP en service sur l'enregistrement DNS. - } - - writeToLog("📊 IP actuelle : $address\n"); - writeToLog("📌 IP enregistrĂ©e : $ipyet\n"); - - if ($ipyet !== $address) { // Comparaison de la nouvelle IP et de celle en service. - $ch = curl_init(); - - $URL = "domain/" . $domain . "/version/active"; - $POSTFIELDS = "[{\"name\": \"$sub\",\"type\": \"$types\",\"changeType\": \"REPLACE\",\"records\": [{\"name\": \"$sub\",\"type\": \"$types\",\"priority\": 0,\"ttl\": 3600,\"data\": \"$address\"}]}]"; - $result = OnlineApi($URL, $POSTFIELDS, "PATCH"); - - if ($result === null) { - writeToLog("⏰ Erreur ENVOI pour $sub.$domain" . "\n"); + // RĂ©cupĂ©ration de l'IPv4 du client appelant la page. + $IPv4ApiResponse = @file_get_contents("https://api.ipify.org?format=json"); + $IPv6ApiResponse = @file_get_contents("https://api6.ipify.org?format=json"); + + if ($IPv4ApiResponse !== false) { + $IPv4Data = json_decode($IPv4ApiResponse, true); + $addressIPv4 = $IPv4Data['ip']; + writeToLog("🌐 Adresse IPv4 publique actuelle : $addressIPv4"); + + if (isPublicIPv4($addressIPv4, $checkPublicIPv4)) { + writeToLog("\n"); + + foreach ($domains as $domain) { + foreach ($subdomains as $sub) { + + writeToLog("🔍 VĂ©rification de l'IPv4 pour $sub.$domain..."); + + if ($sub === "@") { + $IPv4_domain = gethostbyname($domain); // RĂ©cupĂ©ration de l'IPv4 en service sur l'enregistrement DNS. + } elseif ($sub === "*") { + $IPv4_domain = gethostbyname("testdnsall." . $domain); // RĂ©cupĂ©ration de l'IPv4 en service sur l'enregistrement DNS. } else { - writeToLog("✅ IP mise Ă  jour avec succĂšs pour $sub.$domain\n\n"); + $IPv4_domain = gethostbyname("$sub.$domain"); // RĂ©cupĂ©ration de l'IPv4 en service sur l'enregistrement DNS. } - - } else { - writeToLog("🔄 IP inchangĂ©e pour $sub.$domain !\n\n"); - } - } else { - $error = error_get_last(); - writeToLog("❌ Impossible de rĂ©cupĂ©rer l'adresse IP. Erreur : " . $error['message'] . "\n"); - if (checkInternetConnection()) { - writeToLog("❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify.\n"); + writeToLog("📊 IPv4 publique actuelle : $addressIPv4"); + writeToLog("📌 IPv4 publique enregistrĂ©e : $IPv4_domain"); + + if ($IPv4_domain !== $addressIPv4) { // Comparaison de la nouvelle IPv4 et de celle en service. + $ch = curl_init(); + + $URL = "domain/" . $domain . "/version/active"; + $POSTFIELDS = "[{\"name\": \"$sub\",\"type\": \"$types\",\"changeType\": \"REPLACE\",\"records\": [{\"name\": \"$sub\",\"type\": \"$types\",\"priority\": 0,\"ttl\": 3600,\"data\": \"$addressIPv4\"}]}]"; + $result = OnlineApi($URL, $POSTFIELDS, "PATCH"); + + if ($result === null) { + writeToLog("⏰ Erreur ENVOI pour $sub.$domain"); + } else { + writeToLog("✅ IPv4 publique Ă  mise Ă  jour avec succĂšs pour $sub.$domain\n"); + } + } else { + writeToLog("🔄 IPv4 inchangĂ©e pour $sub.$domain !\n"); + } } } } - } + } else { + $error = error_get_last(); + writeToLog("❌ Impossible de rĂ©cupĂ©rer l'adresse IPv4. Erreur : " . $error['message']); - writeToLog("⏳ Attente de 5 minutes...\n---------------------------------\n"); + if (checkInternetConnection()) { + writeToLog("❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify."); + } + } + writeToLog("⏳ Attente de 5 minutes..."); + writeToLog("---------------------------------"); // Pause de 5 minutes sleep(300); } -writeToLog("⛔ Done !\n"); -die("⛔ Done !\n"); -?> +writeToLog("⛔ Done !"); +die("⛔ Done !\n"); \ No newline at end of file From 2a665847bedbc8fe82dbf45ee4924b8a814ee9c7 Mon Sep 17 00:00:00 2001 From: Vincent Berry <37981730+vincentberry@users.noreply.github.com> Date: Sat, 6 Jul 2024 18:42:35 +0200 Subject: [PATCH 3/3] =?UTF-8?q?-=20Int=C3=A9gration=20de=20la=20logique=20?= =?UTF-8?q?pour=20r=C3=A9cup=C3=A9rer=20et=20comparer=20les=20adresses=20I?= =?UTF-8?q?Pv6=20lorsque=20'AAAA'=20est=20sp=C3=A9cifi=C3=A9=20dans=20le?= =?UTF-8?q?=20tableau=20des=20types.=20-=20Adaptation=20de=20la=20boucle?= =?UTF-8?q?=20principale=20pour=20g=C3=A9rer=20les=20mises=20=C3=A0=20jour?= =?UTF-8?q?=20d'IPv4=20et=20d'IPv6=20en=20fonction=20des=20types=20sp?= =?UTF-8?q?=C3=A9cifi=C3=A9s.=20-=20Mise=20=C3=A0=20jour=20de=20la=20gesti?= =?UTF-8?q?on=20des=20erreurs=20et=20des=20logs=20pour=20prendre=20en=20co?= =?UTF-8?q?mpte=20les=20=C3=A9ventuels=20probl=C3=A8mes=20avec=20la=20r?= =?UTF-8?q?=C3=A9cup=C3=A9ration=20d'IPv6.=20-=20Refonte=20des=20fonctions?= =?UTF-8?q?=20existantes=20pour=20assurer=20la=20compatibilit=C3=A9=20avec?= =?UTF-8?q?=20la=20comparaison=20des=20adresses=20IPv4=20et=20IPv6.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 15 ++++-- ddns_update.php | 121 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 109 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 1dfc086..01de810 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Le script vise Ă  automatiser la mise Ă  jour des enregistrements DNS A pour un sous-domaine spĂ©cifiĂ© chez les fournisseurs de services en ligne tels que Online.net. Cela est particuliĂšrement utile dans les scĂ©narios oĂč l'adresse IP de l'hĂŽte change rĂ©guliĂšrement. -⚠ Veuillez noter que ce script est actuellement limitĂ© Ă  la gestion des adresses IPv4 uniquement. Les adresses IPv6 ne sont pas prises en charge pour le moment. Assurez-vous que vos configurations et attentes sont alignĂ©es avec cette limitation. ⚠ +⚠ Les adresses IPv6 ne sont pas encore entiĂšrement prises en charge. Assurez-vous que vos configurations et attentes sont alignĂ©es avec cette limitation. ⚠ ## FonctionnalitĂ©s @@ -75,8 +75,10 @@ services: - SUBDOMAINS=@,* - TYPES=A - CHECK_PUBLIC_IPv4=true #optional + - CHECK_PUBLIC_IP6=true #optional dns: -8.8.8.8 + -2001:4860:4860::8888 restart: unless-stopped ```` @@ -100,8 +102,10 @@ services: - SUBDOMAINS=@,* - TYPES=A - CHECK_PUBLIC_IPv4=true #optional + - CHECK_PUBLIC_IP6=true #optional dns: -8.8.8.8 + -2001:4860:4860::8888 command: ["php", "/usr/src/app/ddns_update.php"] restart: unless-stopped ```` @@ -114,9 +118,10 @@ php ddns_update.php | --------------------- | :------- | -------------------------------------------------------------------------------------------------------------- | | `ONLINE_TOKEN` | `string` | Remplacez "MonTokenOniline.Net" par votre clĂ© API Online.net. Obtenez cette clĂ© depuis [la console Online.net](https://console.online.net/fr/api/access). | | `DOMAINS` | `string` | Indiquez la liste de vos domaines sĂ©parĂ©s par des virgules. Par exemple, `exemple.fr,exemple-2.fr`. | -| `SUBDOMAINS` | `string` | SpĂ©cifiez les sous-domaines sĂ©parĂ©s par des virgules que vous souhaitez mettre Ă  jour. Utilisez `@` pour le domaine principal et `*` pour tous les sous-domaines (par exemple, `@,*`). | -| `TYPES` | `A` or `AAAA` or `A,AAAA` | Indiquez le type d'enregistrement DNS Ă  mettre Ă  jour. Par exemple, `A` (par dĂ©faut) pour un enregistrement de type Adresse IPv4. | -| `CHECK_PUBLIC_IPv4` | `boolean` | (Optionnel) Si dĂ©fini Ă  true (par dĂ©faut), vĂ©rifie que l'adresse IP rĂ©cupĂ©rĂ©e est une adresse publique. Sinon, cette vĂ©rification est ignorĂ©e. | -| `LOG_PATH` | `string` | (Optionnel) Le chemin du rĂ©pertoire pour les logs. Si vous souhaitez les stocker dans un volume, spĂ©cifiez le chemin ici (par exemple, `/log`). | +| `SUBDOMAINS` | `string` | SpĂ©cifiez les sous-domaines sĂ©parĂ©s par des virgules que vous souhaitez mettre Ă  jour. Utilisez `@` pour le domaine principal et `*` pour tous les sous-domaines. *Par default: `*,@`* | +| `TYPES` | `A` or `AAAA` or `A,AAAA` | Indiquez le type d'enregistrement DNS Ă  mettre Ă  jour. Par exemple, `A` (par dĂ©faut) pour un enregistrement de type Adresse IPv4. *Par default: `A,AAAA`* | +| `CHECK_PUBLIC_IPv4` | `boolean` | **Optionnel** Si dĂ©fini Ă  `true`, vĂ©rifie que l'adresse IP rĂ©cupĂ©rĂ©e est une adresse publique. Sinon, cette vĂ©rification est ignorĂ©e. *Par default: `true`* | +| `CHECK_PUBLIC_IPv6` | `boolean` | **Optionnel** Si dĂ©fini Ă  `true`, vĂ©rifie que l'adresse IP rĂ©cupĂ©rĂ©e est une adresse publique. Sinon, cette vĂ©rification est ignorĂ©e. *Par default: `true`* | +| `LOG_PATH` | `string` | **Optionnel** Le chemin du rĂ©pertoire pour les logs. Si vous souhaitez les stocker dans un volume, spĂ©cifiez le chemin ici (par exemple, `/log`). | Ce README a Ă©tĂ© crĂ©Ă© avec le soutien d'une intelligence artificielle pour fournir des informations claires et utiles. diff --git a/ddns_update.php b/ddns_update.php index 64c7cbe..e51aa7e 100644 --- a/ddns_update.php +++ b/ddns_update.php @@ -4,14 +4,15 @@ $Online_Token = getenv('ONLINE_TOKEN'); $domains = explode(',', getenv('DOMAINS')) ?: ['']; $subdomains = explode(',', getenv('SUBDOMAINS')) ?: ['@', '*']; -$types = 'A'; +$types = explode(',', getenv('TYPES')) ?: ['A', 'AAAA']; $checkPublicIPv4 = getenv('CHECK_PUBLIC_IPv4') ?: 'true'; +$checkPublicIPv6 = getenv('CHECK_PUBLIC_IPv6') ?: 'true'; $logFilePath = getenv('LOG_FILE_PATH') ?: "/usr/src/app/log/log.log"; function writeToLog($message) { global $logFilePath; - file_put_contents($logFilePath, date('Y-m-d H:i:s') . " - $message\n", FILE_APPEND); + // file_put_contents($logFilePath, date('Y-m-d H:i:s') . " - $message\n", FILE_APPEND); print_r($message . " \n"); // Si le message contient "Fatal", arrĂȘter l'exĂ©cution du script @@ -119,13 +120,77 @@ function isPublicIPv4($IPv4, $checkPublicIPv4) return true; } +// Fonction pour vĂ©rifier si c'est bien une IPv6 Publique +function isPublicIPv6($IPv6, $checkPublicIPv6) +{ + if ($checkPublicIPv6) { + // DĂ©tection simplifiĂ©e de l'adresse IPv6 publique (non exhaustif) + // VĂ©rification si l'adresse IPv6 commence par les prĂ©fixes typiques des adresses publiques + $publicPrefixes = [ + '2', // Global Unicast (ULA) + '3', // Global Unicast (ULA) + '4', // Global Unicast (ULA) + '5', // Global Unicast (ULA) + '6', // Global Unicast (ULA) + '7', // Global Unicast (ULA) + '8', // Global Unicast (ULA) + '9', // Global Unicast (ULA) + 'a', // Global Unicast + 'A', // Global Unicast + 'b', // Global Unicast + 'B', // Global Unicast + 'c', // Global Unicast + 'C', // Global Unicast + 'd', // Global Unicast + 'D', // Global Unicast + 'e', // Global Unicast + 'E', // Global Unicast + 'f', // Global Unicast + 'F' // Global Unicast + ]; + + // VĂ©rification du prĂ©fixe + $firstChar = substr($IPv6, 0, 1); + if (in_array($firstChar, $publicPrefixes)) { + writeToLog("✅ L'adresse IP rĂ©cupĂ©rĂ©e est une adresse IPv6 publique : $IPv6"); + return true; + } + + writeToLog("❌ L'adresse IP rĂ©cupĂ©rĂ©e n'est pas une adresse IPv6 publique : $IPv6"); + return false; + } + return true; +} + +// Fonction pour comparer et mettre Ă  jour les adresses IP enregistrĂ©es +function compareAndUpdate($IP, $IP_domain, $addressIP, $domain, $sub, $types) +{ + writeToLog("📊 IP$IP publique actuelle : $addressIP"); + writeToLog("📌 IP$IP publique enregistrĂ©e : $IP_domain"); + + if ($IP_domain !== $addressIP) { // Comparaison de la nouvelle IPv4 et de celle en service. + $URL = "domain/" . $domain . "/version/active"; + $POSTFIELDS = "[{\"name\": \"$sub\",\"type\": \"$types\",\"changeType\": \"REPLACE\",\"records\": [{\"name\": \"$sub\",\"type\": \"$types\",\"priority\": 0,\"ttl\": 3600,\"data\": \"$addressIP\"}]}]"; + $result = OnlineApi($URL, $POSTFIELDS, "PATCH"); + + if ($result === null) { + writeToLog("⏰ Erreur ENVOI pour $sub.$domain"); + } else { + writeToLog("✅ IP$IP publique Ă  mise Ă  jour avec succĂšs pour $sub.$domain\n"); + } + } else { + writeToLog("🔄 IP$IP inchangĂ©e pour $sub.$domain !\n"); + } +} + writeToLog("\n---------------------------------"); writeToLog("đŸš© Script Start"); writeToLog("đŸ’ČONLINE_TOKEN: " . $Online_Token); writeToLog("đŸ’Čdomains: " . json_encode($domains)); writeToLog("đŸ’Čsubdomains: " . json_encode($subdomains)); -writeToLog("đŸ’Čtype: " . $types); +writeToLog("đŸ’Čtype: " . json_encode($types)); writeToLog("đŸ’ČcheckPublicIPv4: " . $checkPublicIPv4); +writeToLog("đŸ’ČcheckPublicIPv6: " . $checkPublicIPv6); writeToLog("đŸ’ČlogFilePath: " . $logFilePath); // VĂ©rification des valeurs des variables d'environnement @@ -152,9 +217,7 @@ function isPublicIPv4($IPv4, $checkPublicIPv4) while (true) { // RĂ©cupĂ©ration de l'IPv4 du client appelant la page. $IPv4ApiResponse = @file_get_contents("https://api.ipify.org?format=json"); - $IPv6ApiResponse = @file_get_contents("https://api6.ipify.org?format=json"); - - if ($IPv4ApiResponse !== false) { + if ($IPv4ApiResponse !== false && in_array('A', $types)) { $IPv4Data = json_decode($IPv4ApiResponse, true); $addressIPv4 = $IPv4Data['ip']; writeToLog("🌐 Adresse IPv4 publique actuelle : $addressIPv4"); @@ -174,36 +237,50 @@ function isPublicIPv4($IPv4, $checkPublicIPv4) } else { $IPv4_domain = gethostbyname("$sub.$domain"); // RĂ©cupĂ©ration de l'IPv4 en service sur l'enregistrement DNS. } + compareAndUpdate("v4", $IPv4_domain, $addressIPv4, $domain, $sub, "A"); + } + } + } + } else { + $error = error_get_last(); + writeToLog("❌ Impossible de rĂ©cupĂ©rer l'adresse IPv4. Erreur : " . $error['message']); - writeToLog("📊 IPv4 publique actuelle : $addressIPv4"); - writeToLog("📌 IPv4 publique enregistrĂ©e : $IPv4_domain"); + if (checkInternetConnection()) { + writeToLog("❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify."); + } + writeToLog("\n"); + } - if ($IPv4_domain !== $addressIPv4) { // Comparaison de la nouvelle IPv4 et de celle en service. - $ch = curl_init(); + // RĂ©cupĂ©ration de l'IPv6 du client appelant la page. + $IPv6ApiResponse = @file_get_contents("https://api6.ipify.org?format=json"); + if ($IPv6ApiResponse !== false && in_array('AAAA', $types)) { + $IPv4Data = json_decode($IPv4ApiResponse, true); + $addressIPv6 = $IPv6Data['ip']; + writeToLog("🌐 Adresse IPv4 publique actuelle : $addressIPv6"); - $URL = "domain/" . $domain . "/version/active"; - $POSTFIELDS = "[{\"name\": \"$sub\",\"type\": \"$types\",\"changeType\": \"REPLACE\",\"records\": [{\"name\": \"$sub\",\"type\": \"$types\",\"priority\": 0,\"ttl\": 3600,\"data\": \"$addressIPv4\"}]}]"; - $result = OnlineApi($URL, $POSTFIELDS, "PATCH"); + if (isPublicIPv4($addressIPv6, $checkPublicIPv6)) { + writeToLog(""); - if ($result === null) { - writeToLog("⏰ Erreur ENVOI pour $sub.$domain"); - } else { - writeToLog("✅ IPv4 publique Ă  mise Ă  jour avec succĂšs pour $sub.$domain\n"); - } - } else { - writeToLog("🔄 IPv4 inchangĂ©e pour $sub.$domain !\n"); - } + foreach ($domains as $domain) { + foreach ($subdomains as $sub) { + + writeToLog("🔍 VĂ©rification de l'IPv6 pour $sub.$domain..."); + + $IPv6_domain = ""; + compareAndUpdate("v6", $IPv6_domain, $addressIPv6, $domain, $sub, "AAAA"); } } } } else { $error = error_get_last(); - writeToLog("❌ Impossible de rĂ©cupĂ©rer l'adresse IPv4. Erreur : " . $error['message']); + writeToLog("❌ Impossible de rĂ©cupĂ©rer l'adresse IPv6. Erreur : " . $error['message']); if (checkInternetConnection()) { writeToLog("❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify."); } + writeToLog(""); } + writeToLog("⏳ Attente de 5 minutes..."); writeToLog("---------------------------------");