Scanner automatique pour trouver des hôtes actifs avec Python

Souhaitez-vous voir quelles IP sont actives sur un réseau ? Vous aimeriez savoir comment se déroule un programme de ce style ? Eh bien aujourd'hui je vous montre comment faire un programme en python 3 qui va scanner le réseau dans une plage d'adresses IP que l'utilisateur fournit.

Pour cette tâche, nous allons automatiser le ping du système d'exploitation.

Option 1 - Scanner simple


J'ai mis cette première option, car elle est plus facile à comprendre et à réaliser, avant d'entrer dans quelque chose de plus compliqué.

Le programme complet est le suivant :

 import os import sys import platform from datetime import datetime ip = input ("Entrez l'IP:") ip divisé = ip.split ('.') essayez: rouge = ip divisé [0] + '.' + ip divisé [1 ] + ' . ' + ipDivided [2] +'. ' start = int (entrée ("Entrez le numéro de départ du sous-réseau :")) end = int (entrée ("Entrez le numéro où vous voulez terminer le balayage :")) sauf : print ("[!] Erreur" ) sys.exit (1) if (platform.system () == "Windows") : ping = "ping -n 1" else : ping = "ping -c 1" starttime = datetime.now () print ("[ * ] L'analyse est effectuée à partir de ", rouge + str (début), " à ", rouge + str (fin)) pour le sous-réseau dans la plage (début, fin + 1) : adresse = rouge + str (sous-réseau) réponse = os .popen (ping + "" + adresse) pour la ligne dans response.readlines (): if ("ttl" in line.lower ()): print (adresse, "est actif") break endtime = datetime.now () time = endTime - startTime print ("[*] Le scan a duré% s"% time) 
[couleur = #a9a9a9] Code complet [/couleur]

Étape 1
Nous devons importer des bibliothèques, pour notre programme :

 importer os importer sys plate-forme d'importation à partir de datetime importer datetime
[color = # a9a9a9] Bibliothèques [/ color]

Explication des bibliothèques

  • toi: Nous en avons besoin pour faire un ping via le système d'exploitation.
  • système: Je l'utilise pour terminer le programme en raison d'une erreur dans la saisie de l'utilisateur.
  • Plate-forme: Il nous permet de connaître le système d'exploitation sur lequel nous exécutons le programme, son utilisation nous rend indépendant de la plate-forme.
  • dateheure: Je l'utilise pour connaître le temps qu'il faut pour effectuer le scan, si vous ne voulez pas le savoir vous pouvez le sauvegarder.

Étape 2
Dans le morceau de code suivant, nous demandons à l'utilisateur les données nécessaires, telles que l'hôte et la plage de sous-réseau. También tenemos un bloque try, catch que lo uso básicamente para terminar el programa de una manera controlada, si la IP que inserta el usuario no es correcta la primera instrucción del bloque dará error, y si al pedirle el comienzo y fin no inserta números saltará un erreur.

 ip = input ("Entrez l'IP:") ip divisé = ip.split ('.') essayez: network = ip divisé [0] + '.' + ip divisé [1] + '.' + ip divisé [2 ] + '.' start = int (entrée ("Entrez le numéro de départ du sous-réseau :")) end = int (entrée ("Entrez le numéro où vous voulez terminer le balayage :")) sauf : print ("[!] Erreur" ) sys.exit (1)
J'utilise la première instruction du bloc try pour créer un préfixe réseau, qui sera utile plus tard.

Par exemple, dans l'image suivante, avec les données que j'insère, nous numériserions pour voir si les adresses de 192.168.0.190 à 192.168.0.199 sont actives.

Étape 3
Dans la partie suivante du code, la seule chose que je vérifie est quel système d'exploitation est utilisé via la fonction platform.system ().

 if (platform.system () == "Windows") : ping = "ping -n 1" else : ping = "ping -c 1"
Ceci est nécessaire car nous voulons envoyer un seul paquet, et sous Windows l'instruction se fait avec -n et sous unix avec -c.

Étape 4
Ensuite, je vais analyser l'extrait de code suivant :

 starttime = datetime.now () print ("[*] L'analyse est effectuée à partir de", rouge + str (début), "à", rouge + str (fin)) pour le sous-réseau dans la plage (début, fin + 1) : adresse = réseau + str (sous-réseau) réponse = os.popen (ping + "" + adresse) pour la ligne dans response.readlines (): if ("ttl" in line.lower ()): print (address, " is active ") break endtime = datetime.now () time = endtime - starttime print (" [*] Le scan a duré% s "% time)
Cette étape est l'endroit où nous effectuons la véritable fonctionnalité, donc avant de commencer, j'obtiens le temps correspondant :
 starttime = datetime.now ()
Et nous peignons une ligne par écran pour que l'utilisateur sache que le scan est en cours (et la plage) :
 print ("[*] Le scan est fait à partir de", rouge + str (début), "à", rouge + str (fin))
Ensuite, nous voyons un for, qui parcourra la plage d'adresses IP souhaitées, sa première instruction concatène les numéros manquants au préfixe réseau, c'est-à-dire si nous avons 192.168.0. puis si la boucle for passe de 190 à 199, la première fois que vous entrez l'adresse, ce sera 192.168.0.190 et au fur et à mesure que cela progresse, le 190 sera modifié, le reste que nous gardons. Ensuite, nous obtenons la réponse ping, qui est effectuée par l'instruction :
 os.popen (ping + "" + adresse)
Pour savoir si l'IP est active nous allons vérifier si la réponse que nous avons contient le mot ttl, J'utilise ligne.inférieure () car il semble que sous Linux, il sort en minuscules et sous Windows en majuscules, nous n'avons donc aucun problème.

Dans la partie finale, tout ce que je fais c'est récupérer le temps, et je repose ce nouveau temps avec le précédent pour peindre le temps qu'il a fallu pour mon programme.

Ensuite je montre une image de l'exécution du programme, comme on peut le voir c'est un peu lent (52 secondes pour 19 adresses) ça dépend aussi de la puissance du PC, mais ce temps peut être amélioré si on utilise des threads, donc maintenant Je vais faire le programme en utilisant les " threads Python ".

Option 2 - Scanner Python fileté


Maintenant, nous allons démarrer un programme similaire, mais quelque chose de plus complexe, car maintenant le travail sera divisé entre plusieurs threads et non seulement une charge restera, à la fin nous verrons que le temps est considérablement réduit, nous pouvons donc dire qui est une version plus optimale.

Le programme est le suivant :

 import os import sys import plate-forme import threading, sous-processus de datetime import datetime IPXHILOS = 4 ip = input ("Entrez l'IP:") ip divisé = ip.split ('.') essayez: rouge = ip divisé [0] + ' .' + IP divisé [1] + '.' + IP divisé [2] + '.' start = int (entrée ("Entrez le numéro de départ du sous-réseau :")) end = int (entrée ("Entrez le numéro où vous voulez terminer le balayage :")) sauf : print ("[!] Erreur" ) sys.exit (1) if (platform.system () == "Windows"): ping = "ping -n 1" else: ping = "ping -c 1" class Thread (threading.Thread): def __init __ ( self, start, end): threading.Thread .__ init __ (self) self.start = start self.fin = end def run (self): pour le sous-réseau dans la plage (self.start, self.fin): address = network + str (sous-réseau) réponse = os.popen (ping + "" + adresse) pour la ligne dans response.readlines (): if ("ttl" in line.lower ()): print (adresse, "est actif") break startTime = datetime .now () print ("[*] L'analyse est effectuée à partir de", network + str (début), "to", réseau + str (fin)) NumberIPs = end-begining numberThreads = int ((NumberIPs / IPXHILOS) ) threads = [] try: for i in range (numberThreads): endAux = begin + IPXTHREADS if (endAux> end): endAux = end thread = Thread (beginning, endAux) thread.start () threads.append ( thread) début = finAux sauf Exceptio n donc e: print ("[!] Erreur lors de la création des threads :", e) sys.exit (2) pour le thread dans les threads : thread.join () endtime = datetime.now () time = endtime - starttime print ("[ *] L'analyse a pris % s " % de temps) 
[couleur = #a9a9a9] Programme complet [/couleur]

Ici je vais vous parler des instructions qui changent et s'ajoutent (je vais ignorer les parties égales au programme précédent) :

Les importations que nous utilisons dans le programme précédent sont valables pour nous, il nous suffit d'ajouter les suivantes, qui seront utilisées pour les threads Python.

 thread d'importation, sous-processus
J'utilise une variable pour le nombre d'adresses IP que je veux que chaque thread vérifie, elle est donc ajoutée au début du programme :
 IPXTHREADS = 4
La demande de données de l'utilisateur et la vérification du système d'exploitation restent intactes. Dans ce spectacle Je crée une classe appelée Thread qui s'étend de threading.Thread, cette classe reçoit en paramètres le début et la fin des adresses avec lesquelles chaque thread devra travailler, alors j'ai une fonction run, qui est nécessaire et doit être appelée comme ça, elle s'occupera de faire le travail quand on démarrer le fil plus tard, le for ne change pas :
 class Thread (threading.Thread): def __init __ (self, start, end): threading.Thread .__ init __ (self) self.start = start self.fin = end def run (self): pour le sous-réseau dans la plage ( self.start , self.fin): address = network + str (subnet) response = os.popen (ping + "" + address) pour la ligne dans response.readlines (): if ("ttl" in line.lower () ): print ( adresse, "est actif") break
Maintenant, nous allons expliquer la partie que j'ai en dehors de la classe Fil.

J'utilise l'instruction suivante pour connaître le nombre d'IP que j'ai au total, selon le début et la fin que l'utilisateur me donne :

 NumberIPs = fin-début
Maintenant, une fois que nous savons cela, nous pouvons calculer le nombre de threads dont j'aurai besoin pour travailler :
 nombreThreads = int ((NumberIPs / IPXTHREADS))
J'aurai besoin d'une liste où stocker chaque thread, afin que plus tard je puisse faire attendre le thread principal pour que le travail se termine :
 fils = []
Le fragment de code suivant va créer les threads et leur passer leur section de travail, pour cela nous devons « jouer » avec le début et la fin de chaque thread, c'est pourquoi j'ai créé la variable finAux. Une fois le fil créé, il commence par début () et est ajouté à la liste des discussions.
 try: for i in range (numberThreads): endAux = begin + IPXTHREADS if (endAux> end): endAux = end thread = Thread (beginning, endAux) thread.start () threads.append (thread) begin = endAux sauf Exception as e: print ("[!] Erreur lors de la création des threads :", e) sys.exit (2)
Ensuite, je crée une boucle dont le but est d'attendre que les threads se terminent
 pour le fil dans les fils : thread.join () 
Et enfin, le temps est pris, il serait soustrait de celui que j'ai pris avant de commencer et il s'affiche à l'écran, tout comme le programme précédent.

Si on fait le même test qu'avant avec ce programme on voit qu'il faut 6 secondes pour faire le même travail, quelle différence.

NoterLe temps peut varier en fonction de la puissance de votre PC et de la variable IPXHILOS, je lui attribue un 4, si vous attribuez plus de travail à chaque thread cela prendra plus de temps, s'il a moins de travail ce sera plus rapide, mais faites attention qu'il y est une limite sur le nombre de threads que nous pouvons créer.

Pouvons-nous avoir confiance que ce programme nous donne 100% des hôtes actifs ?La réponse est non, puisque vous pouvez bloquer le ping sur un hôte en bloquant les requêtes et/ou les réponses ICMP, ce dont vous pouvez être sûr, c'est que s'il vous dit qu'il est actif, il l'est. Il existe d'autres types de scanners, tels que TCP que vous pouvez utiliser avec les ports qu'un système d'exploitation laisse normalement ouverts, et la combinaison des scanners TCP et ping sera plus fiable.

Je vous laisse un zip avec les 2 codes :

codigos_ping_python.zip 1,38K 270 téléchargements

Avez-vous aimé et aidé ce tutoriel ?Vous pouvez récompenser l'auteur en appuyant sur ce bouton pour lui donner un point positif
wave wave wave wave wave