Skip to content

Commit

Permalink
Merge pull request #3 from vincentberry/Not_internet
Browse files Browse the repository at this point in the history
  • Loading branch information
vincentberry authored Jul 6, 2024
2 parents b15c8ff + 2a66584 commit 8f098bc
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 78 deletions.
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

⚠️ 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

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.
Expand Down Expand Up @@ -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`
Expand All @@ -71,8 +74,11 @@ services:
- DOMAINS=exemple.fr,exemple-2.fr
- 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
````

Expand All @@ -95,8 +101,11 @@ services:
- DOMAINS=exemple.fr,exemple-2.fr
- 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
````
Expand All @@ -105,12 +114,14 @@ 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 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.
253 changes: 182 additions & 71 deletions ddns_update.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
$Online_Token = getenv('ONLINE_TOKEN');
$domains = explode(',', getenv('DOMAINS')) ?: [''];
$subdomains = explode(',', getenv('SUBDOMAINS')) ?: ['@', '*'];
$types = getenv('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", 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
Expand All @@ -28,25 +35,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',
Expand Down Expand Up @@ -76,106 +84,209 @@ 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;
}

// 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: " . json_encode($types));
writeToLog("💲checkPublicIPv4: " . $checkPublicIPv4);
writeToLog("💲checkPublicIPv6: " . $checkPublicIPv6);
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");
} 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");
// Récupération de l'IPv4 du client appelant la page.
$IPv4ApiResponse = @file_get_contents("https://api.ipify.org?format=json");
if ($IPv4ApiResponse !== false && in_array('A', $types)) {
$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 {
$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("🔍 Vérification de l'IP pour $sub.$domain...\n");
if (checkInternetConnection()) {
writeToLog("❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify.");
}
writeToLog("\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.
}
// 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");

writeToLog("📊 IP actuelle : $address\n");
writeToLog("📌 IP enregistrée : $ipyet\n");
if (isPublicIPv4($addressIPv6, $checkPublicIPv6)) {
writeToLog("");

if ($ipyet !== $address) { // Comparaison de la nouvelle IP et de celle en service.
$ch = curl_init();
foreach ($domains as $domain) {
foreach ($subdomains as $sub) {

$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");
writeToLog("🔍 Vérification de l'IPv6 pour $sub.$domain...");

if ($result === null) {
writeToLog("⏰ Erreur ENVOI pour $sub.$domain" . "\n");
} else {
writeToLog("✅ IP mise à jour avec succès pour $sub.$domain\n\n");
$IPv6_domain = "";
compareAndUpdate("v6", $IPv6_domain, $addressIPv6, $domain, $sub, "AAAA");
}

} else {
writeToLog("🔄 IP inchangée pour $sub.$domain !\n\n");
}
}
} else {
$error = error_get_last();
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...\n---------------------------------\n");
writeToLog("⏳ Attente de 5 minutes...");
writeToLog("---------------------------------");

// Pause de 5 minutes
sleep(300);
}

writeToLog("⛔ Done !\n");
die("⛔ Done !\n");
?>
writeToLog("⛔ Done !");
die("⛔ Done !\n");

0 comments on commit 8f098bc

Please sign in to comment.