Skip to content

Commit

Permalink
✨ feat(log): gestion des logs
Browse files Browse the repository at this point in the history
La fonction writeToLog() a été optimisée pour réduire la répétition des informations temporelles (date/heure) dans les logs et permettre un format uniforme.

Implémentation d'une fonction writeToLog() pour gérer la journalisation des messages d'erreur et d'information.

Arrêt du script en cas d'erreur fatale détectée dans les messages.

✨ feat(gobal):

Ajout d'une variable pour Interval Loop, LOOP_INTERVAL

🐞 fix: global variable

Utilisation de getenv() pour récupérer les variables d'environnement nécessaires à l'exécution du script (TOKEN, DOMAINS, SUBDOMAINS, TYPES, LOG_FILE_PATH).
Définition de valeurs par défaut pour les variables lorsque nécessaire.
  • Loading branch information
vincentberry committed Oct 25, 2024
1 parent de213f1 commit 5a232f9
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 61 deletions.
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

## Objectif

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.
Le script vise à automatiser la mise à jour des enregistrements DNS pour un sous-domaine spécifié chez le fournisseur de services en ligne 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.
1. **Compatibilité Fournisseur:** Le script est conçu pour fonctionner avec les API de Online.net

2. **Utilisation de cURL:** Le script utilise cURL pour effectuer des requêtes HTTP pour connaitre la ip du dns.

Expand Down Expand Up @@ -57,6 +57,7 @@ services:
- SUBDOMAINS=@,*
- TYPES=A
- CHECK_PUBLIC_IPv4=true #optional
- LOG_LEVEL=INFO #optional
restart: unless-stopped
````
Les logs sont stocké dans le docker `/usr/src/app/log`
Expand All @@ -76,6 +77,7 @@ services:
- TYPES=A
- CHECK_PUBLIC_IPv4=true #optional
- CHECK_PUBLIC_IP6=true #optional
- LOG_LEVEL=INFO #optional
dns:
-8.8.8.8
-2001:4860:4860::8888
Expand Down Expand Up @@ -103,6 +105,7 @@ services:
- TYPES=A
- CHECK_PUBLIC_IPv4=true #optional
- CHECK_PUBLIC_IP6=true #optional
- LOG_LEVEL=INFO #optional
dns:
-8.8.8.8
-2001:4860:4860::8888
Expand All @@ -123,5 +126,19 @@ php ddns_update.php
| `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`). |
| `LOG_LEVEL` | `string` | **Optionnel** Définit le niveau de log pour l'application. Les valeurs possibles sont : `DEBUG`, `INFO`, `ERROR`, `FATAL`. La valeur par défaut est `DEBUG`. |
| `LOOP_INTERVAL` | `int` | **Optionnel** La durée (en secondes) entre chaque itération de la boucle principale. Cela définit combien de temps le script attend avant de répéter ses vérifications. La valeur par défaut est `300` secondes (5 minutes). |

### Niveaux de log

Les niveaux de log disponibles dans l'application sont les suivants :

| Niveau | Description |
|----------|------------------------------------------------------------|
| `DEBUG` | Informations détaillées pour le débogage. |
| `INFO` | Informations générales sur l'exécution du programme. |
| `ERROR` | Messages d'erreur signalant des problèmes à résoudre. |
| `FATAL` | Erreurs critiques entraînant l'arrêt de l'application. |


Ce README a été créé avec le soutien d'une intelligence artificielle pour fournir des informations claires et utiles.
135 changes: 76 additions & 59 deletions ddns_update.php
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
<?php

// Récupération des clés d'API et d'autres paramètres depuis les variables d'environnement
$Online_Token = getenv('ONLINE_TOKEN');
$domains = explode(',', getenv('DOMAINS')) ?: [''];
$subdomains = explode(',', getenv('SUBDOMAINS')) ?: ['@', '*'];
$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)
// Fonction centralisée pour récupérer les variables d'environnement avec valeur par défaut
function getEnvVar($key, $default) {
return getenv($key) ?: $default;
}

// Récupération des paramètres depuis les variables d'environnement
$Online_Token = getEnvVar('ONLINE_TOKEN', '');
$domains = explode(',', getEnvVar('DOMAINS', ''));
$subdomains = explode(',', getEnvVar('SUBDOMAINS', '@'));
$types = explode(',', getEnvVar('TYPES', 'A,AAAA'));
$checkPublicIPv4 = filter_var(getEnvVar('CHECK_PUBLIC_IPv4', 'true'), FILTER_VALIDATE_BOOLEAN);
$checkPublicIPv6 = filter_var(getEnvVar('CHECK_PUBLIC_IPv6', 'true'), FILTER_VALIDATE_BOOLEAN);
$logFilePath = getEnvVar('LOG_FILE_PATH', "/usr/src/app/log/log.log");
$loopInterval = intval(getEnvVar('LOOP_INTERVAL', 300));
$logLevel = getEnvVar('LOG_LEVEL', "DEBUG");

// Définition des niveaux de log
$logLevels = [
"DEBUG" => 0,
"INFO" => 1,
"ERROR" => 2,
"FATAL" => 3,
];

function writeToLog($type, $message)
{
global $logFilePath;
// file_put_contents($logFilePath, date('Y-m-d H:i:s') . " - $message\n", FILE_APPEND);
print_r($message . " \n");
global $logLevel;
global $logLevels;

// Vérifie si le niveau du message est égal ou supérieur au niveau actuel
if ($logLevels[$type] >= $logLevels[$logLevel]) {
print_r("[$type] $message\n");
}

file_put_contents($logFilePath, date('Y-m-d H:i:s') . " [$type] - $message\n", FILE_APPEND);

// Si le message contient "Fatal", arrêter l'exécution du script
if (stripos($message, 'Fatal') !== false) {
if (stripos($type, 'FATAL') !== false) {
die("⛔ Script arrêté\n");
}
}
Expand Down Expand Up @@ -47,7 +69,7 @@ function OnlineApi($URL, $POSTFIELDS = "", $method = 'GET')
ApiErrorOnline($result['code']);
return null;
} else {
writeToLog("❌ Erreur cURL $httpCode : $error");
writeToLog("ERROR", "❌ Erreur cURL $httpCode : $error");
return null;
}
}
Expand Down Expand Up @@ -75,9 +97,9 @@ function ApiErrorOnline($httpCode)
];

if (isset($errorCodes[$httpCode])) {
writeToLog("❌ Erreur API Online.net : " . $errorCodes[$httpCode] . "\n");
writeToLog("ERROR", "❌ Erreur API Online.net : " . $errorCodes[$httpCode] . "\n");
} else {
writeToLog("❌ Erreur API Online.net : Code d'erreur inconnu ($httpCode)\n");
writeToLog("ERROR", "❌ Erreur API Online.net : Code d'erreur inconnu ($httpCode)\n");
}
}

Expand All @@ -87,10 +109,10 @@ function checkInternetConnection()
$connected = @fsockopen("www.google.com", 80);
if ($connected) {
fclose($connected);
writeToLog("✅ Connexion Internet valide");
writeToLog("DEBUG", "✅ Connexion Internet valide");
return true;
}
writeToLog("❌ Erreur : Pas de connexion Internet.");
writeToLog("ERROR", "❌ Erreur : Pas de connexion Internet.");
return false;
}

Expand All @@ -111,11 +133,11 @@ function isPublicIPv4($IPv4, $checkPublicIPv4)
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");
writeToLog("ERROR", "❌ 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");
writeToLog("DEBUG", "✅ L'adresse IP récupérée est une adresse IPv4 publique");
}
return true;
}
Expand Down Expand Up @@ -152,11 +174,11 @@ function isPublicIPv6($IPv6, $checkPublicIPv6)
// 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");
writeToLog("DEBUG", "✅ 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");
writeToLog("ERROR", "❌ L'adresse IP récupérée n'est pas une adresse IPv6 publique : $IPv6");
return false;
}
return true;
Expand All @@ -165,57 +187,57 @@ function isPublicIPv6($IPv6, $checkPublicIPv6)
// 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");
writeToLog("DEBUG", "📊 IP$IP publique actuelle : $addressIP");
writeToLog("DEBUG", "📌 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");
writeToLog("ERROR","⏰ Échec de l'envoi de la mise à jour DNS pour le sous-domaine $sub du domaine $domain.");
} else {
writeToLog("✅ IP$IP publique à mise à jour avec succès pour $sub.$domain\n");
writeToLog("INFO", "✅ Mise à jour réussie : La nouvelle IP publique a été appliquée pour le sous-domaine $sub du domaine $domain.");
}
} else {
writeToLog("🔄 IP$IP inchangée pour $sub.$domain !\n");
writeToLog("DEBUG", "🔄 IP $IP inchangée pour le sous-domaine $sub du domaine $domain.");
}
}

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("INFO", "\n---------------------------------");
writeToLog("INFO", "🚩 Script Start");
writeToLog("INFO", "💲ONLINE_TOKEN: " . $Online_Token);
writeToLog("INFO", "💲domains: " . json_encode($domains));
writeToLog("INFO", "💲subdomains: " . json_encode($subdomains));
writeToLog("INFO", "💲type: " . json_encode($types));
if (in_array('A', $types)) {
writeToLog("💲checkPublicIPv4: " . $checkPublicIPv4);
writeToLog("INFO", "💲checkPublicIPv4: " . $checkPublicIPv4);
}
if (in_array('AAAA', $types)) {
writeToLog("💲checkPublicIPv6: " . $checkPublicIPv6);
writeToLog("INFO", "💲checkPublicIPv6: " . $checkPublicIPv6);
}
writeToLog("💲logFilePath: " . $logFilePath);
writeToLog("INFO", "💲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.");
writeToLog("FATAL", " Veuillez fournir des valeurs valides pour les variables d'environnement.");
} else {
writeToLog("✅ Variables d'environnement valide");
writeToLog("INFO", "✅ Variables d'environnement valide");
}

//vérification de la connection internet
if (!checkInternetConnection()) {
writeToLog("⛔ Fatal : Veuillez vérifier votre connexion Internet pour l'initialisation.");
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é.");
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");
writeToLog("INFO", "✅ API Online.net valide de " . $userInfo['last_name'] . " " . $userInfo['first_name'] . " \n");
}

while (true) {
Expand All @@ -227,15 +249,14 @@ function compareAndUpdate($IP, $IP_domain, $addressIP, $domain, $sub, $types)
if ($IPv4ApiResponse !== false) {
$IPv4Data = json_decode($IPv4ApiResponse, true);
$addressIPv4 = $IPv4Data['ip'];
writeToLog("🌐 Adresse IPv4 publique actuelle : $addressIPv4");
writeToLog("DEBUG", "🌐 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...");
writeToLog("DEBUG", "🔍 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.
Expand All @@ -250,12 +271,11 @@ function compareAndUpdate($IP, $IP_domain, $addressIP, $domain, $sub, $types)
}
} else {
$error = error_get_last();
writeToLog("❌ Impossible de récupérer l'adresse IPv4. Erreur : " . $error['message']);
writeToLog("ERROR", "❌ Impossible de récupérer l'adresse IPv4. Erreur : " . $error['message']);

if (checkInternetConnection()) {
writeToLog("❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify.");
writeToLog("ERROR", "❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify.");
}
writeToLog("\n");
}
}

Expand All @@ -264,17 +284,16 @@ function compareAndUpdate($IP, $IP_domain, $addressIP, $domain, $sub, $types)
// Récupération de l'IPv6 du client appelant la page.
$IPv6ApiResponse = @file_get_contents("https://api6.ipify.org?format=json");
if ($IPv6ApiResponse !== false) {
$IPv4Data = json_decode($IPv4ApiResponse, true);
$IPv6Data = json_decode($IPv6ApiResponse, true);
$addressIPv6 = $IPv6Data['ip'];
writeToLog("🌐 Adresse IPv4 publique actuelle : $addressIPv6");
writeToLog("DEBUG", "🌐 Adresse IPv4 publique actuelle : $addressIPv6");

if (isPublicIPv4($addressIPv6, $checkPublicIPv6)) {
writeToLog("");

foreach ($domains as $domain) {
foreach ($subdomains as $sub) {

writeToLog("🔍 Vérification de l'IPv6 pour $sub.$domain...");
writeToLog("DEBUG", "🔍 Vérification de l'IPv6 pour $sub.$domain...");

$IPv6_domain = "";
compareAndUpdate("v6", $IPv6_domain, $addressIPv6, $domain, $sub, "AAAA");
Expand All @@ -283,21 +302,19 @@ function compareAndUpdate($IP, $IP_domain, $addressIP, $domain, $sub, $types)
}
} else {
$error = error_get_last();
writeToLog("❌ Impossible de récupérer l'adresse IPv6. Erreur : " . $error['message']);
writeToLog("ERROR", "❌ 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("ERROR", "❌ Erreur : La connexion Internet fonctionne, mais une erreur est survenue avec l'API ipify.");
}
writeToLog("");
}
}

writeToLog("⏳ Attente de 5 minutes...");
writeToLog("---------------------------------");
writeToLog("DEBUG", "⏳ Attente de 5 minutes...");

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

writeToLog("⛔ Done !");
die("Done !\n");
writeToLog("FATAL", "⛔ Script terminé !");
die("Fin de l'exécution.\n");

0 comments on commit 5a232f9

Please sign in to comment.