Le langage python permet facilement de créer des connexions réseaux et de communiquer entre ordinateurs. Et grace à ChatGPT qui peut jouer le rôle de professeur particulier, l'essentiel des notions et des capacités du langage de programmation python3 peut être dévoilé, expliqué, et mis en oeuvre directement.
Invite envoyé à chatGPTP : « Programme en python. Un serveur qui ouvre un port en écoute, et qui affiche les messages textes qui y sont envoyés. Et programme un client qui envoie à l'adresse IP du serveur sur le bon port des messages textes.»
On crée un programme server.py qui va écouter sur le port 12345 :
server.py import socket # Définition du port d'écoute
PORT = 12345 # Remplacez par le numéro de port désiré# Création du socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("0.0.0.0", PORT)) # Écoute sur toutes les interfaces réseau
server_socket.listen(5)print(f"Serveur en écoute sur le port {PORT}...")
while True:
client_socket, client_address = server_socket.accept()
print(f"Connexion reçue de {client_address}")# Lecture du message envoyé par le client
message = client_socket.recv(1024).decode("utf-8")
print(f"Message reçu : {message}")client_socket.close() # Fermer la connexion avec le client
On crée un programme client.py qui va émettre à destination du socket (serveur et port) : 192.168.1.10:12345
client.py import socket # Définition du serveur et du port
SERVER_IP = "192.128.1.10" # Remplacez par l'IP du serveur
PORT = 12345 # Doit correspondre au port du serveur# Création du socket client
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((SERVER_IP, PORT))# Saisie du message à envoyer
message = input("Entrez votre message : ")
client_socket.sendall(message.encode("utf-8"))print("Message envoyé !")
client_socket.close()
Pour démarrer le serveur, exécutez dans le shell bash « python3 server.py ». Le serveur sera en attente de connexion et affichera tous les messages qui lui seront envoyés. Pour envoyer un message au serveur, exécuter dans le shell bash « python3 client.py » et saisissez un message et validez, le message sera envoyé.
Le non-expert étant vite noyé quant il y a plus de 36 lignes de codes, on recourt à une élèvation de protocole. On se débarrasse d'une partie technique qui est traité une fois pour toute dans une couche logiciel en-dessous et qui correspond à un niveau de protocole plus bas. Et on programme des fonctions plus avancées formant un nouveau langage, une nouvelle couche logiciel, qui gère un niveau de protocole plus élevé.
On crée la fonction servidor(p) qui démarre le serveur d'écoute sur le port p, et la fonction cliente(ip,p,s) qui envoie le message s au serveur d'adresse ip et de port p.
reseau1.py import socket
def servidor(PORT):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(("0.0.0.0", PORT)) # Écoute sur toutes les interfaces réseau
server_socket.listen(5)
print(f"Serveur en écoute sur le port {PORT}...")
while True:
client_socket, client_address = server_socket.accept()
print(f"Connexion reçue de {client_address}")
message = client_socket.recv(1024).decode("utf-8")
print(f"Message reçu : {message}")
client_socket.close() # Fermer la connexion avec le client
def cliente(IP, PORT, message):
try:
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((IP, PORT))
client_socket.sendall(message.encode("utf-8"))
print("? Message envoyé avec succès !")
client_socket.close()
except ConnectionRefusedError:
print("? Erreur : Impossible de se connecter au serveur. Vérifiez qu'il est bien démarré.")
except socket.timeout:
print("? Erreur : La connexion a expiré.")
except Exception as e:
print(f"?? Erreur inattendue : {e}")
On lance l'interpréteur en ligne python3 et on exécute :
from reseau1 import *
// Importe le paquet socket et les deux fonctions servidor(.) et cliente(.,.,.)servidor(9110)
// Démarre le serveur d'écoute du port 9110
On lance un second interpréteur en ligne python3 et on exécute :
cliente("192.168.1.26", 9110, "Bonjour !")
// Envoie le message "Bonjour !" au serveur d'adresse IP 192.168.1.26 et de port d'écoute 9110cliente("192.168.1.132", 9110, "Bonjour !")
// Envoie le message "Bonjour !" au serveur d'adresse IP 192.168.1.132 et de port d'écoute 9110
L'évolution des performances des ordinateurs suit plus ou moins la loi de Moore. Même s'il y a un ralentissement ou une accélération pour certains, on reste dans une évolution de nature exponentielle ce qui signifie toujours une révolution, et donc potentiellement un changement de mode du système au niveau macroscopique. Ce changement à venir donnera l'avantage aux systèmes décentralisés, car chaque noeuds d'un réseau a actuellement des capacitées de calcul et de mémoire qui surpasse de façon dantesque sa simple nécessité, et il en est de même pour les débits Internet entre noeuds. Cette révolution des systèmes informatiques en réseau entrainera de part égale une révolution sociale. Voyons à quoi peut ressembler un tel système décentralisé en en créant un, pouvant servire de base à d'autres...
On veut mettre en oeuvre un système de communication entre un nombre quelconque d'ordinateurs sur l'Internet. Le système est décentralisé, cela signifie que chaque membre doit être un serveur à part entière qui contribue en partie à l'intégrité du système de communication. Pour entrer en contact en utilisant ce système de communication avec d'autres membres, il faut d'abord connaitre au moins un serveur qui pourra alors transmettre des adresses d'autres serveurs. Le serveur doit donc gérer une liste de contacts. Un contact se compose d'un enchufe (socket en anglais) c'est à dire l'adresse IP d'un serveur et son numéro de port d'écoute, que l'on mémorise généralement sous forme d'une chaine de caractères telle que par exemple "80.25.123.5:9110", et il comprend une donnée informationnelle sur le serveur en question, une donnée arbitraire créée par le serveur possédant l'annuaire. La modification de cette donnée n'est pas considérée comme une modification de l'annuaire. Si l'on souhaite accéder à une donnée informationelle concernant directement le serveur référencé, on s'adresse directement au serveur référencé, qui aura donc un champ particulier servant de réponse à cette demande.
Une adresse IP désigne une interface réseaux localisée qui est généralement un ordinateur. Et cet ordinateur peut héberger plusieurs serveurs utilisant à chaque fois un port d'écoute différent. C'est pourquoi on parlera d'hôtes identifiés par leur adresse IP, et on parlera de serveurs identifiés par leur enchufe. Chaque sommet du système de communication est un serveur identifié par son enchufe. Pour de multiple raisons un serveur peut être amené à changer d'adresse IP et de port d'écoute. C'est pourquoi on l'élève en abstraction pour lui permettre de changer d'adrese IP et de port d'écoute sans changer son identité, et cette nouvelle entitée est appelée membre ou utilisateur. L'utilisateur n'est donc pas une personnes physique ni morale. L'utilisateur est un serveur qui peut changer d'adresse et de port d'écoute.
Le défaut actuelle des concepteurs est sans doute de vouloir d'abord axer leur développement sur la sécurité. Cela s'explique par des raisons sociologiques, par le fait que les possédants financent de façon importante le développement et ont intérêt à protéger leur situation de possédant. Notre démarche est inverse. Au départ, tout est publique et n'importe qui peut se faire passer pour n'importe qui. Viendra par la suite les champs privés que l'utilisateur veut garder secret et qui peut inclure des clefs de cryptage et d'identification, etc.. ainsi que des blockchaines.
Le système étant décentralisé, il faut donc pour pouvoir se connecter, connaitre l'adresse d'un serveur, et il y aura plusieurs serveurs connus publiquement et qui devront être gérés par des associations à but non-lucratif. Ces serveurs n'auront aucune différence vis-à-vis des autres serveurs. C'est l'exigence d'une totale décentralisation. En particulier, le système de communication n'exige pour aucun serveur d'être en marche en permanence. Ces serveurs publiques n'ont comme seule différence, celle d'être connu du grand publique avec comme caution l'association qui les gère.
La plus part des utilisateurs ont une adresse IP qui n'est pas permanente, renouvelée 1 fois par mois, ou 1 fois par ans, et ils n'ont pas de nom de domaine. L'aspect décentralisé du système que nous voulons mettre en oeuvre, rend faisable un travail similaire à ce que font les serveurs de noms pour identifier les serveurs, à part que nous n'allons pas utiliser de nom mais une clé. Pour identifier l'utilsateur qui peut changer d'adresse IP et qui peut changer de port d'écoute, le plus simple est de générer une clef d'identification aléatoire et suffisament grande pour s'assurer qu'il n'y a pas de doublon. Posons la question à ChatGPT o1 :
Quel est la probabilité qu'il y ait au moins un doublon dans 7 milliards de tirages de clés au hasard de 1024 bits ? ChatGPT o1 : Raisonnement terminé pendant 7 secondes
En pratique, l’espace de clés 1024 bits (de taille `2^1024`) est si vaste qu’avec « seulement » `7` milliards de tirages, la probabilité d’avoir un doublon est extraordinairement faible. On peut l’estimer via la formule approchée du « paradoxe des anniversaires » :
`P("collisions")≈1−e^(−(n(n−1))/(2N))`
où
`n=7×10^9` est le nombre de tirages.
`N=2^1024` est le nombre total de clés possibles.Calculez d’abord `(n(n−1))/(2N)`.
`(n(n−1))/2≈7×109×(7×109−1)2≈2.45×10^19`
`2^1024 ≈ 1.79×10^308`
Donc : ` (n(n−1))/(2N)≈(2,45×10^19)/(1.79×10^308)≈1.36×10^(-289)`
Ensuite,
`P("collisions")≈1−e^(−1.36×10^(−289))`
Pour un nombre `x` très petit, `e^(−x)≈1−x`. Ainsi,.
`P("collisions")≈1.36×10^−289`
En d’autres termes, la probabilité qu’il existe au moins un doublon parmi `7` milliards de clés `1024` bits choisies aléatoirement est de l’ordre de `1.36×10^(−289)` : un nombre absolument négligeable. Pour toute application pratique, on peut le considérer comme nul.
Si on prend une clé sur seulement `128` bits, la probabilité d'avoir au moins un doublon sur `7` milliards de tirages est de `7"×"10^(-20)`, un nombre absolument négligeable. Pour toute application pratique, on peut le considérer comme nul.
Il est commode de représenter la clé en hexadécimal. Un digit en héxadécimal représente 4 bits, la clé tient donc sur 32 digits héxadécimaux. Elle représente votre identifiant unique. Si vous voulez vous faire passer pour quelqu'un d'autre, il faudra modifier le programme pour remplacer votre clé par celle d'un autre utilisateur.
L'utilisateur est un serveur et n'a qu'une seule adresse et qu'un seul port d'écoute. C'est le choix d'un système de communication entre serveurs. Pour définir des utilisateurs regroupant plusieurs serveurs, ce sera une application d'un niveau de protocole plus élevé, une couche logiciel au dessus de ce système de communication décentralisé, qu'il faudra développer.
On ajoute donc aux contacts un troisième champ, qu'est cette clé d'identification de 32 caractères héxadécimaux, et qui identifie le serveur.
Le numéro de port pour émettre ne peut pas être le même que le numéro de port pour recevoir. Le numéro de port pour émettre et choisie aléatoirement par l'ordinateur, seul le numéro de port d'écoute et important, c'est pourquoi il sera systématiquement communiqué dans tous messages, pour permettre de répondre sans avoir besoin de consulter l'annuaire.
Si un serveur reçoit un message d'une adresse IP et d'un port d'écoute qu'il n'a pas dans son annuaire, alors il va demander la clé d'identification et ajouter le nouveau contact dans son annuaire, et efface l'éventuel autre contact ayant la même clé d'identification. Car la clé d'identification identifie un seul serveur.
Dans cette première étape de développement du système, celui-ci propose une copie de l'annuaire pour chaque serveur. On doit donc établir un algorithme de synchronisation des annuaires.
Le serveur transmet la modifications de son annuaire à tous ses contactes qu'il possède dans son annuaire. Si le contact n'est pas en marche l'information ne peut pas être immédiatement transmise. Si le contact ne connaissait pas déjà cette information, il modifit à son tour son annuaire et retransmet à tous ses contacts.
Mais il peut y avoir des échos tardifs d'anciennes modifications qui vont remodifier les dernières modifications. Pour éviter ce cafouillage, il faut ajouter un horodatage, la date du premier message à l'origine de la modification de l'annuaire. On ajoute donc aux contacts un quatrième champ contenant cet horodatage. Cela permet au serveur qui a une information plus récente de répondre, et ainsi de corriger le demandeur en l'informant que sa demande est obsolète et en lui transmettant la bonne demande de mise-à-jour.
Mais les serveurs ne sont pas à l'écoute en permanence, c'est pourquoi lors de l'envoi d'une mise à jour, il faut un accusé de réception. On ajoute donc aux contacts un cinquième champ qu'est la date de l'accusé de réception. Tant que la date de réception est plus petite que la plus récente date de mise à jour, le seveur sait qu'il faudra qu'il informe ce contact des mise-à-jours de l'annuaire qui se sont faite après cet date.
La complexité est alors en `n^2` où `n` est le nombre de noeuds. Pour réduire cette complexité, l'algorithme doit être plus subtile. Posons la question à ChatGPT o1 :
Étant donné `n` serveurs communiquant entre-eux, chacun contenant une donnée datée. Connaissez-vous des algorithmes permettant à ces `n` serveurs de synchroniser leur donnée sur celle la plus récente, et qui économise le nombre de communication ? Raisonné sur la synchronisation de serveurs pendant 29 secondes :
L'utilisateur souhaite synchroniser les données parmi les serveurs pour converger vers la version la plus récente, tout en minimisant les communications.
Je suis en train de voir les approches de diffusion des données, comme l'épidémie et l'arbre couvrant, tout en minimisant les communications tout en assurant la robustesse. Hm, je me demande si c'est efficace.
Je suis en train de noter l'approche de l'arbre couvrant ou du vecteur de version pour diffuser les données avec une convergence rapide et peu de communications, tout en identifiant efficacement les nœuds avec les informations les plus récentes.
Je suis en train de voir les approches comme "Rassemblement Maximum et Diffusion", "Arbre Couvrant", et "Répétition". Progressivement, on découvre "Convergecast" et "Succès-succès".
Pour synchroniser `n` serveurs de sorte qu’ils convergent tous vers la donnée la plus récente (selon un critère de date/horodatage) tout en minimisant les échanges, on utilise classiquement des schémas de convergence de type “gather & broadcast” ou bien des approches “épidémiques” (gossip). Selon le contexte (fiabilité, rapidité, topologie), certaines méthodes sont plus adaptées que d’autres. Ci-dessous un aperçu des principaux algorithmes ou familles d’algorithmes :
-----------------------------------------------------------------------------------------------------------------------------------------------
1. Schémas de convergence en arbre (“gather & broadcast”)
L’idée est de construire (ou d’utiliser) une arborescence logique (un spanning tree) couvrant tous les nœuds du réseau :
- Convergence (gather) : chaque nœud envoie son horodatage (et éventuellement sa donnée) vers le “racine” de l’arbre.
- En montant dans l’arborescence, on peut agréger l’information : on compare l’horodatage reçu avec celui conservé localement et on ne remonte que la donnée la plus récente.
- Au terme de cette phase, le nœud racine connaît la donnée la plus récente de tout le réseau.
- Diffusion (broadcast) : le nœud racine réémet la valeur la plus récente à ses enfants dans l’arborescence, qui la réémettent à leurs propres enfants, etc., jusqu’à couvrir tout le réseau.
Complexité en communications
- Avec un arbre couvrant de `n−1` arêtes, on a typiquement `(n−1)` envois pour la phase de convergence et `(n−1)` pour la phase de diffusion.
- Au total, `2(n−1)` messages suffisent.
- C’est optimal pour une structure en arbre (dans un réseau totalement interconnecté, on peut faire d’autres optimisations — par exemple un schéma en anneau – mais on retombe sur une ordre de grandeur similaire).
Avantages / Inconvénients
- Avantage : Nombre d’échanges réduit et contrôlé (lignes directrices : on sait à tout moment quels nœuds sont déjà informés).
- Inconvénient : Besoin de maintenir (ou de construire) un arbre couvrant correct. Si l’arbre se brise ou qu’un nœud tombe, il faut prévoir un mécanisme de résilience (reconstruction, multipath, etc.).
-----------------------------------------------------------------------------------------------------------------------------------------------
2. Approches épidémiques (gossip)
Les algorithmes gossip ou « anti-entropy » mettent en œuvre une diffusion aléatoire :
- Périodiquement, chaque nœud choisit un pair au hasard dans l’ensemble des nœuds (ou parmi une liste de voisins).
- Les deux échangent leurs données (ou, plus précisément, les métadonnées : horodatages, version, etc.) :
- Le nœud qui constate que l’autre possède une version plus récente se met à jour.
- Cette version plus récente se propage ainsi de proche en proche.
Complexité en communications
- Les algorithmes gossip se distinguent par leur rapidité de convergence statistique (typiquement en `O(log n)` tours “de communication” pour que la majorité des nœuds aient l’information), mais le nombre total de messages peut être plus élevé que dans un schéma hiérarchique si on n’y prend pas garde (car la diffusion est plus “redondante”).
- L’intérêt réside dans le fait qu’ils sont simples à implémenter, robustes aux pannes et aux changements dynamiques dans le réseau.
Avantages / Inconvénients
- Avantages : Extrêmement tolérant aux pannes, facile à mettre en place dans un réseau pair-à-pair dynamique, forte probabilité d’atteindre tous les nœuds même avec des liens instables.
- Inconvénients : Potentiellement plus de messages (car échanges redondants) et, sans réglage fin, on ne garantit pas un nombre minimal de communications.
-----------------------------------------------------------------------------------------------------------------------------------------------
3. Utilisation de primitives de “All-Reduce” (HPC)
Dans le domaine du calcul parallèle haute performance (HPC), on retrouve des collectives (MPI, etc.) comme “all-reduce” qui permettent de calculer une fonction globale (somme, maximum, etc.) et de redistribuer le résultat à tout le monde.
- Ici, le “maximum” des horodatages est précisément l’opération que l’on cherche : “all-reduce(max(…))”.
- Sous le capot, ces primitives sont souvent implémentées via des approches arborescentes, en anneau, ou en hypercube, pour minimiser la latence et/ou le volume de données (donc proches de l’approche “gather & broadcast”).
-----------------------------------------------------------------------------------------------------------------------------------------------
En résumé
- Schéma arborescent (gather & broadcast) : assure la récupération du max d’horodatage en `2(n−1)` communications (dans un arbre couvrant). Très économe si on peut s’appuyer sur une structure de graphe fiable.
- Gossip / anti-entropy : très robuste et simple à gérer sur des réseaux dynamiques, mais plus coûteux en messages (au sens strict) si on cherche un strict minimum de communications.
- Primitives “all-reduce” : implémentent souvent un maximum (ou d’autres opérations) de manière optimale via des topologies arborescentes ou en anneau. Très utilisées en HPC, on peut les transposer pour un cluster ou un ensemble de serveurs.
Pour la synchronisation sur la donnée la plus récente avec un minimum de trafic, on recommande en général un schéma de type convergecast+diffusion (donc en arbre ou en anneau). Les algorithmes épidémiques sont, eux, idéaux pour des contextes plus massifs ou peu fiables, où l’on accepte des redondances de communication pour gagner en résilience et en simplicité.
On établit un protocole, un ensemble de messages déclenchant des actions spécifiques.
Le système doit se protéger contre la création de contacts éphémères en grand nombre qui écroulerai la gestion de l'annuaire. C'est pourquoi le contact doit être évalué. La date du dernier message ou silbido reçu (ping en anglais) ou envoyé avec succès est mémorisée dans le contact mais n'est pas considéré comme une modification de l'annuaire. Lorsque l'annuaire commence à être gros, il teste avec des ping ses contacts de façons aléatoire avec une plus grande intensité pour obtenir le plus de dernières dates de présence. Puis, lorsque l'annuaire devient vraiment trop gros, il supprime les contactes les plus anciens et transmet cette mise-à-jour de l'annuaire à tous ces contacts.
On peut alors créer un protocole d'un niveau plus élevé pour pouvoir envoyer un message à un serveur identifié par sa clé.
Il comprend un démon qui récupère le flux de messages reçut et le retransmet en interne dans une file, et une fonction qui envoi un message.
La fonction d'envoi est simple, exemple: cliente("192.168.1.26", 9110, "Bonjour !"), et on la complète afin qu'elle envoit systématiquement en plus le numéro de port du serveur d'écoute de l'expéditeur, l'adresse IP du serveur de l'expéditeur étant déjà envoyé par les protocoles plus bas, il n'est pas utile de l'ajouter.
Le serveur retransmet ce qu'il recoit dans un flux asynchrone de messages internes. C'est une file qui accumulent les messages non-traités. Et un autre démon traite chaque message, dans l'ordre de leur arrivé. Ainsi deux processus traitent une donnée partagée qu'est la file de messages.
Demandons à ChatGPT de faire le travail. On demande à "Python GPT"
Crée deux processus p1 et p2 qui vont partager une même file de String. Le processus p1 ajoute "Bonjour" dans la file toute les secondes, le processus p2 retire un string de la file toute des secondes. Python GPT :
Voici un script Python utilisant le module multiprocessing et une Queue pour partager une file entre les deux processus.
Le processus p1 ajoute "Bonjour" dans la file toutes les secondes, et le processus p2 retire un élément de la file toutes les secondes.
import multiprocessing
import timedef producer(queue):
while True:
queue.put("Bonjour")
print("[P1] Ajouté: Bonjour")
time.sleep(1)"""Ajoute 'Bonjour' dans la file chaque seconde.""" def consumer(queue):
while True:
if not queue.empty():
message = queue.get()
print(f"[P2] Retiré: {message}")
time.sleep(1)
"""Retire un élément de la file chaque seconde.""" if __name__ == "__main__":
queue = multiprocessing.Queue()p1 = multiprocessing.Process(target=producer, args=(queue,))
p2 = multiprocessing.Process(target=consumer, args=(queue,))# Création des processus p1.start()
p2.start()# Démarrage des processus time.sleep(10) # Arrêt après 10 secondes p1.terminate()
p2.terminate()# Terminer proprement les processus p1.join()
p2.join()# Attendre la fin des processus print("Fin du programme")
Il comprend la fonction qui envoi un message à un serveur identifié par sa clé. On envoit ce message à n'importe quel serveurs du réseau. Celui-ci trouve la clé dans son annuaire et transmet le message, ou bien il ne la trouve pas et répond "clé de serveur inconnue".
Puis si l'annuaire devient vraiment trop grand, environ 100_000 clés, la duplication de l'annuaire sur chaque serveur devient trop gourmande en temps en flux et en places. L'annuaire devra être dispatché, chaque serveur possèdera qu'une portion de l'annuaire. Et des algorithmes plus savants devront maintenir cette annuaire et permettre à toutes demandes d'une clé arrivant sur un serveur quelconque de pouvoir intérroger l'essentiel de l'annuaire.
...
Se pose alors la question suivante : « Est-il possible de concevoir un réseau social aussi interactif que X ou Facebook, sans qu'il n'y ait de serveur dédié permanent ? et sans qu'il n'y ait de serveurs spécifiques se différenciant des autres, dans une sorte de communisme informatique ». Il n'empêche que si le réseau social doit prendre des décisions, celles-ci semblent ne pouvoir être conçues et appliquées que par une sorte de polit-bureau s'appuyant sur un cercle plus restreint de serveurs...
C'est alors, l'utilisateur au sens classique où on l'entend, qui est identifié par une clé, et auquel va correspondre une liste de serveurs identifiés par leur enchufe (leur adresse IP et leur port d'écoute).
Mais la plus-part des utilisateurs n'ont pas de serveur directement raccordé à l'Internet. Ils ont une Livebox qui joue le rôle de routeur et qui les relit à l'Internet, et pour accéder à un réseau social, ils utilisent le navigateur Internet et se connecter sur un site web distant. Pour faire directement sans utiliser un serveur web distant, il faut ouvrir un port sur la Livebox et cela nécessite des connaissances informatiques. Mais grace à l'UPnP, il est possible d'ouvrir automatiquement des ports sur un routeur. Posons la question à ChatGPT :
Connaissez-vous l'Universal Plug and Play (UPnP). Cette fonction permet aux applications d'ouvrir des ports automatiquement ? ChatGPT :
Oui, je connais bien l'Universal Plug and Play (UPnP). C'est un ensemble de protocoles réseau qui permet aux appareils d’un réseau local de se découvrir mutuellement et d’établir des connexions sans configuration manuelle.
L’une de ses fonctionnalités clés est l’ouverture automatique des ports sur un routeur via le protocole UPnP IGD (Internet Gateway Device). Cela permet à des applications comme les jeux en ligne, les logiciels de visioconférence ou les serveurs domestiques d’ouvrir des ports dynamiquement, sans intervention de l’utilisateur.
Avantages du UPnP :
- Facilité d’utilisation : Pas besoin de configurer manuellement les règles de redirection de ports.
- Pratique pour les applications nécessitant des connexions entrantes (ex. : jeux en ligne, serveurs multimédias).
- Compatible avec la plupart des routeurs modernes.
Inconvénients et risques de sécurité :
- Sécurité laxiste : Tout appareil sur le réseau peut ouvrir des ports, ce qui peut être une porte d’entrée pour des logiciels malveillants.
- Exploitation possible : Certains malwares peuvent utiliser UPnP pour exposer un appareil vulnérable à Internet.
- Difficile à contrôler : Contrairement à une configuration manuelle, il est plus difficile de suivre quels ports sont ouverts.
Bonnes pratiques :
- Désactiver UPnP sur le routeur si vous n’en avez pas besoin.
- Utiliser des règles de port manuelles pour un meilleur contrôle.
- Vérifier les appareils connectés au réseau pour s’assurer qu’aucun ne l’exploite de manière abusive.
- Mettre à jour le firmware du routeur pour corriger d’éventuelles vulnérabilités.
Si vous utilisez UPnP, c’est surtout pratique pour éviter les configurations compliquées, mais il faut garder en tête les risques et surveiller l’activité réseau. Vous envisagez de l’activer sur un routeur ?
Est-il possible d'utiliser l'UPnP en python3 ? ChatGPT :
Oui, il est tout à fait possible d’utiliser UPnP en Python 3 pour ouvrir et gérer des ports sur un routeur compatible avec UPnP IGD (Internet Gateway Device).
◉ Bibliothèques utiles :
- miniupnpc – Une bibliothèque Python qui permet de découvrir les routeurs UPnP, d’ouvrir/fermer des ports et de récupérer l’IP publique.
- ssdp – Une autre approche en utilisant directement le protocole de découverte des services UPnP.
◉ Exemple d'utilisation avec miniupnpc
Lancez l'installation de la bibliothèque si ce n'est pas fait :
pip install miniupnpc
Puis, voici un script pour ouvrir un port sur un routeur via UPnP :
import miniupnpc
# Initialisation de l'UPnP client
upnp = miniupnpc.UPnP()
upnp.discoverdelay = 200 # Délai en ms pour la découverte
upnp.discover() # Recherche des périphériques UPnP sur le réseau# Connexion au routeur
upnp.selectigd()# Vérification de l'IP publique
external_ip = upnp.externalipaddress()
print(f"IP Publique : {external_ip}")# Configuration des ports
internal_port = 5000 # Port de l'appareil local
external_port = 5000 # Port visible sur Internet
protocol = 'TCP' # Peut être 'UDP' selon le besoin# Ajout d'une redirection de port
upnp.addportmapping(external_port, protocol, upnp.lanaddr, internal_port, "Test UPnP Mapping","")print(f"Port {external_port} redirigé vers {upnp.lanaddr}:{internal_port}")
# Liste des ports actuellement mappés
for i in range(10): # On regarde les 10 premières entrées
mapping = upnp.getspecificportmapping(i, protocol)
if mapping:
print(f"Port {i} : {mapping}")# Suppression de la redirection (facultatif)
upnp.deleteportmapping(external_port, protocol)
print(f"Port {external_port} fermé.")◉ Explication du script :
- Découverte du routeur via UPnP.
- Récupération de l’IP publique du routeur.
- Ouverture d’un port en associant un port externe à un port interne.
- Vérification des redirections actives.
- Optionnel : Fermeture du port avec deleteportmapping().
◉ Cas d'usage :
- Héberger un serveur de jeu ou web chez soi.
- Ouvrir un port temporairement pour un logiciel.
- Automatiser la gestion des ports sur un réseau local.
◉ Attention aux risques de sécurité ! Activez UPnP uniquement si nécessaire et assurez-vous que votre réseau est bien protégé.
Vous voulez tester ça sur un projet particulier ?
Dés lors, le serveur peut lui-même changer de port, et à l'aide d'un serveur installé sur un autre ordinateur qui possède un droit d'exécution, se copier et s'installer sur cet autre ordinateur.
---- 18 mars 2025 ----