Détection de changement d'adresse IP Internet WAN

Bonjour,
Je dispose d’un routeur et de 2 accès WAN dont 1 en backup.
Je voulais détecter le basculement de l’un vers l’autre directement dans JEEDOM. Pas forcément en temps réel.
J’ai donc bricolé ce petit bout de code (je n’y connaît rien).

$outputname = "MonIPWanNow";
$req  = 'curl "http://checkip.dyndns.com"';
$scenario->setLog('Ma requete : '.$req);
$output0 = shell_exec($req);
$scenario->setLog('Mon retour : '.$output0);
$output0 = substr($output0, strpos($output0, ":")+1, strpos($output0, "</bo")-strlen($output0));
$output0 = str_replace(' ', '', $output0);
$scenario->setLog('Variable MonIPWanNow : '.$output0);
// affecte le résultat à la variable $outputname
$scenario->setData($outputname, $output0);

Je récupère donc l’@IP wan actuelle de ma connexion à internet pour agir / notifier.
Les réseaux IP entre les 2 fournisseurs n’étant pas les mêmes, je peux distinguer l’un de l’autre.
On peut aussi l’utiliser dans le cas de changement d’@ip dynamique…

1 « J'aime »

Bonjour,

Plutôt qu’un shell_exec, vous pouvez utiliser un curl_exec pour ne pas devoir lancer un process shell:

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "http://checkip.dyndns.com");
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $curlResponse = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // pour vérifier le http code de la requête
        $error = curl_error($ch); // pour vérifier les erreurs
        curl_close($ch);
        unset($ch);

ou encore plus simple un simple get content puisque c’est une simple requête get:

$output= file_get_contents("http://checkip.dyndns.com");

Merci Mips. J’ai modifié comme proposé au plus simple ! :slightly_smiling_face:

Hello,

Je me suis fait un petit scénario aussi :
Il est un peu plus complexe car il a 3 liens (le 3eme est pas dans le tableau car en ip 4G dynamique)
Et j’appelle un scénario dans le bloc code pour faire une notification Discord.
Je le lance toutes les 5 minutes.

Si ça peut donner des idées


// Author : Marc GUYARD (mguyard)
// Version : 1.1
// Date : 20201113
// Fonction : Recupère l'adresse IP et la stock dans une variable en vue de notifier

// Url de requête
$url = "http://ifconfig.io/ip";

// Addresse IPs de tout les liens principaux
$array_PublicIP = array(
  	'94.103.X.X' => array(
     	'name' => 'K-Net',
        'order' => '1'
     ),
	'82.64.X.X' => array(
 	 	'name' => 'Freebox',
        'order' => '2'
     )
);


// Stocke la précédent addresse IP
$previousPublicIP = $scenario->getData('PublicIP');

// Récupère l'adresse IP Publique actuelle
$ipCall = curl_init();
curl_setopt($ipCall, CURLOPT_URL, $url);
curl_setopt($ipCall, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ipCall, CURLOPT_TIMEOUT,        15);
curl_setopt($ipCall, CURLOPT_CONNECTTIMEOUT, 15);
$ipCallReturn = trim(curl_exec($ipCall));
$ipCallHTTPCode  = curl_getinfo($ipCall, CURLINFO_HTTP_CODE);
curl_close($ipCall);
// Si Success
if($ipCallHTTPCode == 200) {
  $scenario->setLog("Le site a validé la demande. Contenu reçu : '".$ipCallReturn."'");
  if (filter_var($ipCallReturn, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 )) {
    $scenario->setLog("Verification : C'est bien une adresse IP");
    // Si la précédente IP et la nouvelle sont différentes
    if (strcmp($previousPublicIP,$ipCallReturn) !== 0) {
      	$scenario->setLog("L'adresse IP récupérée (". $ipCallReturn .") est différente de la précédente (". $previousPublicIP .")");
      	// Stoke en variable la nouvelle IP Publique
    	$scenario->setData('PublicIP', $ipCallReturn);
        // Verification changement de lien et alerte
        if (array_key_exists($ipCallReturn, $array_PublicIP)) {
        	 $scenario->setLog("L'adresse IP récupérée correspond au lien " . $array_PublicIP[$ipCallReturn]['name']);
             if (array_key_exists($previousPublicIP, $array_PublicIP)) {
             	 if ($array_PublicIP[$ipCallReturn]['order'] > $array_PublicIP[$previousPublicIP]['order']) {
                 	sendNotification($scenario, ":warning: Bascule sur le lien " . $array_PublicIP[$ipCallReturn]['name'] . " depuis le lien " . $array_PublicIP[$previousPublicIP]['name'] . ".L'adresse IP actuelle est " . $ipCallReturn);
                 } else {
                    sendNotification($scenario, "OK : Retour sur le lien " . $array_PublicIP[$ipCallReturn]['name'] . ".L'adresse IP actuelle est " . $ipCallReturn);
                 }
             } else {
              	 sendNotification($scenario, ":warning: Bascule sur le lien " . $array_PublicIP[$ipCallReturn]['name'] . " depuis le lien 4G.L'adresse IP actuelle est " . $ipCallReturn);
             }
        } else {
         	 $scenario->setLog("L'adresse IP récupérée correspond au lien 4G");
             sendNotification($scenario, ":warning: Bascule sur la 4G. L'adresse IP actuelle est " . $ipCallReturn);
        }
    } else {
     	 $scenario->setLog("L'adresse IP récupérée (". $ipCallReturn .") est identique à la précédente");
    }
  } else {
   	 $scenario->setLog("Le Contenu reçu (".$ipCallReturn.") n'est pas une adresse IP Publique");
  }
} else {
  $scenario->setLog("/!\ ERROR : Le site a répondu '".$ipCallReturn."' avec code de retour HTTP ".$ipCallHTTPCode);
}

// Fonction d'envoi de notification par le Scenario de Notification
function sendNotification($scenario, $message) {
  $notificationScenarioName = scenario::fromHumanReadable('#[Notification][Notifications][SendNotification]#');
  $scenario->setLog("Convertion du scénario en ID :" . $notificationScenarioName);
  preg_match('/#scenario(\d+)#/', $notificationScenarioName, $notificationScenarioId);
  $scenario->setLog("ID du scénario :" . $notificationScenarioId[1]);
  $notificationScenario = scenario::byId($notificationScenarioId[1]);
  if(is_object($notificationScenario)) {
    // Definition des tags du scénario appellé
    $tags['#N_TYPE#'] = "message";
    $tags['#N_TITLE#'] = "Bascule d'accès INTERNET";
    $tags['#N_MESSAGE#'] = $message;
    $tags['#N_COLOR#'] = "#FF0000";
    $tags['#N_TRIGGERNAME#'] = $scenario->getHumanName();
    $tags['#N_TRIGGERID#'] = $scenario->getId();
    $notificationScenario->setTags($tags);
    $notificationScenario->launch();
    $scenario->setLog("Envoi de la notification...");
  } else {
	$scenario->setLog("Le scénario de notification n'a pas pu être récupéré !"); 
  }
}

2 « J'aime »

C’est stable http://ifconfig.io/ip ?
moi j’en utilisais 2, 3 parce que de temps en temps ces sites ne répondent pas ou en erreur, notamment celui-ci "https://myexternalip.com/raw

Chez moi, ne retourne que l’ip v6.

Retourne bien l’ip v4.

ca retourne l’ip avec laquelle ton routeur se connecte, le site n’y est pour rien.
L’autre retourne l’ipv4 car c’est probablement la seul qu’il supporte et donc tout routeur est forcé de basculer sur ipv4

1 « J'aime »

Je l’utilise depuis des années sans problèmes.

Bonjour,

Avec curl, il faut ajouter l’option -4 pour avoir l’ipv4.

curl -4 http://ifconfig.io/ip
1 « J'aime »

Avec curl_exec c’est cette option :

curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
2 « J'aime »

Merci. Effectivement c’est autre chose. Assez léché !
http://checkip.dyndns.com n’est pas fiable. Aussi je test maintenant avec d’autres sites pour être sûr comme le disait Mips.

Bonjour,

’ai bien pu créer le scénario avec un bloc « code », j’ai adapté les IPs et enlevé la partie 4G. J’ai une double connexion Fibre et VDSL, via une gateway Ubiquity qui fait du fail over.

Par contre je ne comprends pas comment faire la notification, soit via « mobile notification » soit via télégram. Je me sers des 2.

Merci de vos conseils.

Bonjour
je ne vais pas répondre directement, mais en voyant votre interrogation, je pense qu’il n’y a pas besoin de bloc code.
Vous prenez le plugin « Speedtest by ookla »
https://spine34.github.io/jeedom-plugin-speedtestByOokla/fr_FR/?theme=dark

Vous créer un scénario de notification avec :

  • En trigger l’information de l’ip externe
  • en message le trigger value

ça devrait faire le job (à vue de nez = jamais fait)

A bientôt pour avoir le résultat ! :slight_smile:

Merci Henri, c’est une bonne idée, je vais essayer cela ce soir.

rémy