Skip to content

Commit 8f97bb3

Browse files
committed
Upgrade to version 2.0
- Upgrade the user interface - Use the typer library for a great look - Add a method for validation - Restructure the code organization - Add Code Refactorings and improvements
1 parent 85398dc commit 8f97bb3

File tree

1 file changed

+106
-55
lines changed

1 file changed

+106
-55
lines changed

Utilities/NetScanner.py

Lines changed: 106 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,127 @@
1-
# Copyright 2023 ClarkCodes
2-
#
3-
# Licensed under the Apache License, Version 2.0 (the "License");
4-
# you may not use this file except in compliance with the License.
5-
# You may obtain a copy of the License at
6-
#
7-
# http://www.apache.org/licenses/LICENSE-2.0
8-
#
9-
# Unless required by applicable law or agreed to in writing, software
10-
# distributed under the License is distributed on an "AS IS" BASIS,
11-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12-
# See the License for the specific language governing permissions and
13-
# limitations under the License.
1+
'''
2+
Copyright 2023 ClarkCodes
143
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
'''
1516
# NetScanner.py
1617
# Descripción: Utilidad de red escrita en Python para escanear y detectar dispositivos
1718
# en un segmento de red indicado con nmap, obtener direcciones ip, direcciones mac y
1819
# sus puertos abiertos.
19-
# Author: Clark - ClarkCodes
20+
21+
# Author: Clark - @ClarkCodes
22+
# Versión: 2.0
2023

2124
# Imports
2225
import nmap
26+
import typer
27+
from rich import print
28+
from rich.table import Table
29+
from rich import box
30+
from rich.progress import Progress, SpinnerColumn, TextColumn
31+
32+
# Constantes
33+
SEPARATOR = "********************************************"
2334

24-
# Predefined
25-
separator = "********************************************"
35+
# Global Variables
36+
dev_Scanner = nmap.PortScanner()
2637

2738
# Functions
28-
def printFoundHosts( allHostsList : list[str] ):
29-
if len( allHostsList ) > 0:
30-
print( "\n*--- Dispositivos encontrados:\n" )
39+
def printFoundHosts( all_hosts_list : list[str] ):
40+
if len( all_hosts_list ) > 0:
41+
print( "[yellow]*--- Dispositivos encontrados:\n" )
3142

32-
for i, host in enumerate( allHostsList ):
33-
print( separator )
34-
print( f"*** Dispositivo #{ i + 1 } ***" )
35-
print( f"Nombre: { devScanner[host].hostname() }" )
36-
print( f"Dirección Ip: { host }" )
43+
for i, host in enumerate( all_hosts_list ):
44+
print( SEPARATOR )
45+
found_device_table = Table( f"[green]Parámetro", "[green]Datos", title = f"[bold][green]*** Dispositivo #{ i + 1 } ***", title_justify = "center", box = box.ROUNDED )
46+
found_device_table.add_row( f"Nombre:", f"{dev_Scanner[host].hostname()}" )
47+
found_device_table.add_row( f"Dirección Ip:", f"{host}" )
3748

38-
if 'mac' in devScanner[host]['addresses']:
39-
print( f"Dirección MAC: { devScanner[host]['addresses']['mac'] }" )
49+
if 'mac' in dev_Scanner[host]['addresses']:
50+
found_device_table.add_row( f"Dirección MAC:", f"{dev_Scanner[host]['addresses']['mac']}" )
4051

41-
print( f"Estado: { devScanner[host].state() }" )
52+
found_device_table.add_row( f"Estado:", f"{dev_Scanner[host].state()}" )
4253

43-
protocolsList = devScanner[host].all_protocols()
54+
print( "" )
55+
print( found_device_table )
4456

45-
if len( protocolsList ) > 0:
46-
print( "\n* Protocolos *" )
57+
protocols_list = dev_Scanner[host].all_protocols()
4758

48-
for proto in devScanner[host].all_protocols():
49-
print( f"\tProtocolo: { proto }" )
50-
lport = devScanner[host][proto].keys()
59+
if len( protocols_list ) > 0:
60+
protocols_table = Table( f"[green]Parámetro", "[green]Datos", title = "[bold][green]* Protocolos *", title_justify = "center", box = box.ROUNDED )
61+
62+
for proto in dev_Scanner[host].all_protocols():
63+
protocols_table.add_row( f"Protocolo:", f"{proto}" )
64+
65+
lport = dev_Scanner[host][proto].keys()
5166
#lport.sort()
5267
for port in lport:
53-
print ( f"\t\tPuerto: { port }\tEstado: { devScanner[host][proto][port]['state'] }" )
54-
55-
print( separator )
56-
else:
57-
print( "\nNo se encontraron dispositivos en el segmento de red indicado." )
58-
68+
protocols_table.add_row( f"Puerto:", f"{port}" )
69+
protocols_table.add_row( f"Estado:", f"{dev_Scanner[host][proto][port]['state']}" )
5970

60-
### Script Body Code
61-
print( "\n*** Clark's Network Devices Scanner ***\n" )
71+
print( "" )
72+
print( protocols_table )
6273

63-
devScanner = nmap.PortScanner()
64-
65-
ip = input( "Ingrese el Rango Ip: " )
66-
67-
print( "\nBuscando dispositivos presentes en la red del rango Ip indicado: ", ip )
68-
print( "Un momento por favor, en breve se mostrará el resultado.\nDetectando..." )
69-
70-
devScanner.scan( ip )
71-
72-
printFoundHosts( devScanner.all_hosts() )
73-
74-
# Fin del Script - Mensaje de Despedida
75-
print( "\nGracias por usar este Script, es todo por ahora, hasta pronto, bye. :)" )
76-
print( "@ClarkCodes(en todas las redes sociales).\n\n" )
74+
print( f"[yellow]{SEPARATOR}" )
75+
else:
76+
print( "[bright_black]\nNo se encontraron dispositivos en el segmento de red indicado." )
77+
78+
def is_ip_range_valid( ip_range : str ):
79+
dots_counter = ip_range.count( '.' )
80+
81+
if( dots_counter != 3 ):
82+
return False
83+
84+
segments_list = ip_range.split( '.' )
85+
86+
for index, segment in enumerate( segments_list ):
87+
if( ( index < 3 or ( index == 3 and segment.find( '/' ) == -1 ) ) ):
88+
number = int( segment )
89+
90+
if( number < 0 or number > 255 ):
91+
return False
92+
93+
return True
94+
95+
# Función Principal
96+
def main():
97+
print( "[bold green]\n*** Clark's Network Devices Scanner ***" )
98+
99+
while True: # Bucle para Repetir el Menú hasta que el usuario decida salir.
100+
print( "\n[bright_cyan]* Lobby de Opciones *[/bright_cyan]\nIngrese un rango ip para escanear la red o ingrese 'q' para salir." )
101+
102+
user_input = input( "\nIngrese el Rango Ip: " )
103+
104+
if( user_input == 'q' or user_input == 'Q' ): # Condición de Salida
105+
print( "[green]\n✅ Esto ha sido todo por hoy.\n❤ Muchas gracias por ejecutar este Script, hasta la próxima...💻 Happy Coding!,👋🏼 bye :D\n😎 Clark." )
106+
break
107+
108+
try:
109+
if( not is_ip_range_valid( user_input ) ):
110+
raise ValueError
111+
112+
print( "" )
113+
with Progress( SpinnerColumn(), TextColumn( "[yellow][progress.description]{task.description}" ), transient = True ) as progress:
114+
progress.add_task( description="[light_sky_blue1]Buscando dispositivos presentes en la red dentro del rango Ip indicado... Un momento por favor...", total = None )
115+
116+
dev_Scanner.scan( user_input )
117+
printFoundHosts( dev_Scanner.all_hosts() )
118+
119+
except ValueError:
120+
print( "\n❌ La estructura del rango ip no es válida, verifique nuevamente." )
121+
except Exception as ex:
122+
print( "\n❌ Oops... algo no ha salido bien, revise nuevamente por favor." )
123+
print( "Message Error: ", ex )
124+
125+
# Llamada a la Función Principal usando typer
126+
if __name__ == "__main__":
127+
typer.run( main )

0 commit comments

Comments
 (0)