0

Relais Wake on LAN (WOL)

Dans cet article, j’explique comment créer un relais Wake On LAN (WOL) à l’aide d’un microcontrôleur ESP8266, afin que vous puissiez allumer à distance les appareils connectés à votre réseau local (LAN) via Internet.

Remarque : Le réveil à distance d’un appareil via Internet est également connu sous le nom de WOW (Wake On Wide Area Network (WAN)), car Internet se trouve sur le WAN.

Dans l’article ci-dessous, je me concentre sur mes exigences « réelles » pour pouvoir alimenter à distance un serveur Synology DS2411+ Network Attached Storage (NAS) via Internet. Mon serveur NAS Synology DS2411+ est connecté à un Smart UPS APC 1500, qui est également connecté à mon réseau local. J’ai été surpris d’apprendre que cet UPS ne dispose d’aucune fonctionnalité dans son interface Web de gestion ou son serveur Telnet/SSH pour prendre en charge la diffusion du « paquet magique » WOL vers les appareils via le réseau local. Par conséquent, en cas de panne de courant, l’onduleur intelligent APC 1500 est capable de communiquer avec le serveur NAS Synology DS2411+ afin qu’il s’arrête automatiquement. Cependant, l’onduleur intelligent APC 1500 ne dispose d’aucun mécanisme pour interroger régulièrement le serveur NAS Synology DS2411+ et le rallumer avec un paquet WOL magique une fois la panne de courant résolue !

Wake-up on LAN (WOL) utilise un paquet magique diffusé sur le réseau local avec une adresse MAC (Media Access Control) spécifiée. N’importe quel appareil sur votre réseau local peut être alimenté via le paquet magique, si les critères suivants sont remplis :

  • l’appareil contient une carte d’interface réseau (NIC) qui prend en charge la fonction WOL (la plupart des cartes réseau modernes prennent en charge WOL)
  • le système d’exploitation de l’appareil a la fonction WOL activée sur la carte réseau
  • la carte réseau de l’appareil a la même adresse MAC que celle diffusée dans le paquet magique

En règle générale, il est difficile d’essayer d’utiliser WOL via Internet pour allumer à distance un périphérique de votre réseau local, car de nombreux routeurs ne prennent pas en charge la fonctionnalité de relais WOL. Certains routeurs disposent de la fonctionnalité relais WOL (comme mon routeur de Bouyages Telecom), mais celle-ci ne fonctionne pas. WOL utilise soit User Datagram Port (UDP) 9, soit UDP 7. La redirection de port UDP 9, par exemple vers un périphérique de votre réseau, présente les problèmes suivants :

  • pas fiable car la liaison de l’adresse IP de l’appareil à l’adresse MAC est perdue avec le temps
  • limité à l’adresse IP de l’appareil que vous avez spécifié dans la règle de redirection de port
  • risqué car vous ouvrez votre réseau local à Internet, permettant à quiconque d’inonder votre réseau local de plusieurs requêtes WOL

Comme l’illustre le schéma ci-dessous, l’utilisation d’un relais WOL sur un microcontrôleur ESP8266 résout les problèmes ci-dessus, car le relais WOL ajoute une couche de sécurité (à l’aide d’un code d’accès SecureON) et vous permet d’allumer à distance plusieurs appareils avec des adresses MAC différentes.

Exemple d'implémentation de relais WOL
Exemple d’implémentation de relais WOL – Réveiller à distance un serveur Synology NAS via Internet

Dans le schéma ci-dessus, nous voyons ce qui suit :

1. À l’aide d’une application mobile iOS telle que Magic Packet, nous spécifions un port UDP de choix, plutôt que les ports UDP 7 ou UDP 9 « bien connus ». Le port UDP de choix est défini sur l’ESP8266 et le port UDP spécifié dans l’application iOS doit correspondre à celui défini sur l’ESP8266. Dans notre exemple, nous utilisons UDP 50055.
Remarque : certains fournisseurs de réseaux mobiles ferment tous les ports UDP inférieurs à 1024 sur leurs réseaux mobiles 3G/4G/5G. Par conséquent, il est recommandé de configurer le relais WOL sur l’ESP8266 avec un port UDP supérieur à 1024.

2. À l’aide d’une application mobile iOS, nous pouvons définir plusieurs adresses MAC « cibles », ce qui nous permet d’allumer à distance plusieurs appareils « cibles » sur le réseau local, si nécessaire.

3. À l’aide d’une application mobile iOS, il est nécessaire de spécifier un code d’accès SecureON pour que le paquet magique WOL soit diffusé sur le réseau local. Ce code d’accès SecureON est défini sur l’ESP8266 sous forme de valeurs entières, et celui spécifié dans l’application iOS doit correspondre à celui défini sur l’ESP8266, généralement exprimé en hexadécimal. Dans notre exemple, nous définissons 654321 comme valeur entière du code d’accès SecureON sur l’ESP8266, ce qui correspond à 36:35:34:33:32:31 (ou 36-35-34-33-32-31) dans l’application iOS.
Remarque 1 : Toutes les applications iOS ne prennent pas en charge la fonctionnalité SecureON. Les deux applications iOS suivantes prennent en charge la fonctionnalité SecureON : Magic Packet et WakeUP – The Wake on LAN Tool.
Remarque 2 : Le format du code d’accès SecureON peut varier selon les différentes applications iOS. L’application Magic Packet iOS utilise les tirets (-) entre les valeurs HEX, alors que d’autres applications iOS peuvent utiliser des deux-points (:).
Remarque 3 : Au lieu d’utiliser une application iOS, vous pouvez utiliser le site Web suivant pour lancer WOL sur Internet : https://www.depicus.com/wake-on-lan/woli. Ce site Web prend également en charge l’utilisation du mot de passe SecureON.

Dans le schéma ci-dessus, nous voyons que l’application mobile iOS envoie le paquet magique à robert wisbey.net, qui est résolu en l’adresse IP WAN de mon routeur à l’aide du service DNS dynamique noip.com. Vous pouvez également spécifier l’adresse IP WAN de votre routeur Internet. Cependant, si l’adresse IP WAN de votre routeur change régulièrement, vous ne pouvez pas garantir que vous pourrez accéder à distance à votre routeur ou à votre réseau local. Je recommande d’utiliser le service DNS dynamique de noip.com, qui associe l’adresse IP WAN actuelle de votre routeur à un nom de domaine fixe de votre choix. Le service DNS dynamique de noip.com propose une version gratuite et une version payante. Si vous choisissez d’utiliser l’un de leurs services payants, n’hésitez pas à utiliser mes liens de parrainage dans ce paragraphe ainsi que le code promo REFER20 pour obtenir une réduction de 20 %.

Le code C++ suivant peut être utilisé pour créer le relais WOL sur l’ESP8266 :

#include <ESP8266WiFi.h>                  
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>

////////////////////////////////////////////////
// Class to Send/Receive UDP's:
////////////////////////////////////////////////
class BroadCastDeamon: public WiFiUDP {
  public:
  void PostUDP( const char *Packet, IPAddress ip, unsigned int destPort) {
     PostUDP(Packet, strlen(Packet), ip, destPort);
  }
  void PostUDP( const char *Packet, int len, IPAddress ip, unsigned int destPort) {
    WiFiUDP::beginPacket( ip, destPort);
    WiFiUDP::write(Packet, len);
    WiFiUDP::endPacket();
  }
  void BroadcastUDP( const char *Packet, unsigned int destPort) {
     BroadcastUDP(Packet, strlen(Packet), destPort);
  }
  void BroadcastUDP( const char *Packet, int len, unsigned int destPort ) {
    IPAddress broadcastIP = (uint32_t)WiFi.localIP() | (~(uint32_t)WiFi.subnetMask());
    PostUDP(Packet, len, broadcastIP, destPort);
  }  
  
  bool CheckReceived() {
    // if there's data available, read a packet and return length
    packetSize = parsePacket();
    if (packetSize)
    {
      //Serial.print("Received UDP packet from [");
      //Serial.print(broadcastUdp.remoteIP());
      //Serial.print("] : ");
      // read the packet into packetBufffer
      int len = read(packetBuffer, 255);
      packetBuffer[len] = 0;
      //Serial.println(packetBuffer);
      return true;
    }
    return false;
  }
  char *GetPacketData() {
    return packetBuffer;
  }
  int GetPacketSize() {
     return packetSize;
  }
  private:
   char packetBuffer[256]; //buffer to hold last packet retreived
   int  packetSize;
};

BroadCastDeamon WOLDeamon;

////////////////////////////////
// the configuration Part of the code:

// SecureOn for WOL has to be 6 hex bytes; Advice change the default.
byte SecureOn[7] = "654321"; // In most WOL apps that support SecureOn you have to enter the bytes in HEX format like this: "36:35:34:33:32:31" for "654321"
// Receiver Port for WOL packets forwarded by the router
unsigned int WOLPort=50055; // just some random choice in the free range. But make sure you forward UDP packets to this port in your router

// Enter your own WLAN credentials
char wlanSSID[]="Your Wifi LAN SSID";
char wlanPWD[]="Your Wifi LAN Password";


void setup() {
  delay(1000);
  Serial.begin(115200);
  delay(1000);
  Serial.println("Starting the WOL Gateway "); 
  while (!ConnectToNetwork(wlanSSID, wlanPWD)) {
    delay(2000);
  }
  WOLDeamon.begin(WOLPort);
}



void loop() {
    HandleWOLReceived(SecureOn);
    delay(10);
}

bool ConnectToNetwork(char *wlanSSID, char *wlanPWD )  {
  int timeout=0;
  bool succes=false;
  WiFi.mode(WIFI_STA);
  Serial.print("Connecting SSID: ");
  Serial.println(wlanSSID);
  WiFi.begin(wlanSSID, wlanPWD);
  while (WiFi.status() != WL_CONNECTED && timeout < 10)
  {
      delay(1000);
      timeout++;
  }
  if (WiFi.status() == WL_CONNECTED) {
     Serial.println();
     Serial.print("Connected, IP address: ");
     Serial.println(WiFi.localIP());
     succes=true;
  }
  else {
    Serial.println("Connecting to SSID Failed ");
  }
  // printWifiMode();
  return succes;
}



#define WOL_SECURE_PACKET_SIZE 108
bool HandleWOLReceived (byte *pwd) {
  if (WOLDeamon.CheckReceived() && WOLDeamon.GetPacketSize() == WOL_SECURE_PACKET_SIZE) {
     byte *pPrefix = (byte *)WOLDeamon.GetPacketData();
     byte *pPWD = pPrefix + 102; // start position of the SecureOn
     // check if it is has both a valid WOL prefix (6 times FF) and that it contains the defined SecureOn password
     for (int i=0; i<6; i++) {
       if (pPrefix[i] != 255 || pPWD[i] != pwd[i]) {
         Serial.println("INVALID WOL packet received");
         return false;
       }
     }
     // Broadcast WOL packet on local LAN
     Serial.println("Valid WOL packet received");
     WOLDeamon.BroadcastUDP(WOLDeamon.GetPacketData(), WOL_SECURE_PACKET_SIZE, 7); // accidently used for WOL (official for echo)
     WOLDeamon.BroadcastUDP(WOLDeamon.GetPacketData(), WOL_SECURE_PACKET_SIZE, 9); // (un)official WOL port
  }
  return true;
}

Reamrque : dans le code C++ ci-dessus, les informations d’identification WiFi sont génériques, 654321 a été utilisé pour le code SecureON et 50055 a été utilisé pour le port d’écoute UDP. Modifiez ces quatre paramètres de configuration selon vos besoins.

Une fois le code C++ écrit sur l’ESP8266 et connecté à votre réseau local, vous pouvez surveiller le port série via Arduino pour voir l’adresse IP qu’il a initialement obtenue de votre routeur.

Exemple de sortie série Arduino lorsqu'elle est connectée au microcontrôleur ESP8266 exécutant le code C++ du relais WOL
Exemple de sortie série Arduino lorsqu’elle est connectée au microcontrôleur ESP8266 exécutant le code C++ du relais WOL

Sur votre routeur, vous pouvez identifier l’ESP8266 qui fonctionne comme relais WOL et déterminer son adresse MAC. Sur le serveur DHCP de votre routeur, vous devez attribuer à l’adresse MAC de l’ESP8266 fonctionnant comme relais WOL une adresse IP statique (par exemple 192.168.1.5).

Paramètres d'adresse IP statique du serveur DHCP
Paramètres d’adresse IP statique du serveur DHCP

Une fois l’adresse IP statique définie pour l’ESP8266 fonctionnant comme relais WOL dans la table DHCP de votre routeur, vous devez rediriger le port UDP que vous aviez défini sur l’ESP8266 (par exemple 50055) vers cette adresse IP statique.

Redirection de port vers le relais WOL ESP8266
Redirection de port vers le relais WOL ESP8266

La vidéo suivante illustre le fonctionnement du relais WOL comme prévu, alimentant (réveilleant) à distance un serveur Synology NAS via Internet. J’espère que cet article a été utile à tous ceux qui ont eu besoin d’allumer (réveiller) à distance des appareils du réseau local via Internet.