-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 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
- Loading branch information
1 parent
85398dc
commit 8f97bb3
Showing
1 changed file
with
106 additions
and
55 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,76 +1,127 @@ | ||
# Copyright 2023 ClarkCodes | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
''' | ||
Copyright 2023 ClarkCodes | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
''' | ||
# NetScanner.py | ||
# Descripción: Utilidad de red escrita en Python para escanear y detectar dispositivos | ||
# en un segmento de red indicado con nmap, obtener direcciones ip, direcciones mac y | ||
# sus puertos abiertos. | ||
# Author: Clark - ClarkCodes | ||
|
||
# Author: Clark - @ClarkCodes | ||
# Versión: 2.0 | ||
|
||
# Imports | ||
import nmap | ||
import typer | ||
from rich import print | ||
from rich.table import Table | ||
from rich import box | ||
from rich.progress import Progress, SpinnerColumn, TextColumn | ||
|
||
# Constantes | ||
SEPARATOR = "********************************************" | ||
|
||
# Predefined | ||
separator = "********************************************" | ||
# Global Variables | ||
dev_Scanner = nmap.PortScanner() | ||
|
||
# Functions | ||
def printFoundHosts( allHostsList : list[str] ): | ||
if len( allHostsList ) > 0: | ||
print( "\n*--- Dispositivos encontrados:\n" ) | ||
def printFoundHosts( all_hosts_list : list[str] ): | ||
if len( all_hosts_list ) > 0: | ||
print( "[yellow]*--- Dispositivos encontrados:\n" ) | ||
|
||
for i, host in enumerate( allHostsList ): | ||
print( separator ) | ||
print( f"*** Dispositivo #{ i + 1 } ***" ) | ||
print( f"Nombre: { devScanner[host].hostname() }" ) | ||
print( f"Dirección Ip: { host }" ) | ||
for i, host in enumerate( all_hosts_list ): | ||
print( SEPARATOR ) | ||
found_device_table = Table( f"[green]Parámetro", "[green]Datos", title = f"[bold][green]*** Dispositivo #{ i + 1 } ***", title_justify = "center", box = box.ROUNDED ) | ||
found_device_table.add_row( f"Nombre:", f"{dev_Scanner[host].hostname()}" ) | ||
found_device_table.add_row( f"Dirección Ip:", f"{host}" ) | ||
|
||
if 'mac' in devScanner[host]['addresses']: | ||
print( f"Dirección MAC: { devScanner[host]['addresses']['mac'] }" ) | ||
if 'mac' in dev_Scanner[host]['addresses']: | ||
found_device_table.add_row( f"Dirección MAC:", f"{dev_Scanner[host]['addresses']['mac']}" ) | ||
|
||
print( f"Estado: { devScanner[host].state() }" ) | ||
found_device_table.add_row( f"Estado:", f"{dev_Scanner[host].state()}" ) | ||
|
||
protocolsList = devScanner[host].all_protocols() | ||
print( "" ) | ||
print( found_device_table ) | ||
|
||
if len( protocolsList ) > 0: | ||
print( "\n* Protocolos *" ) | ||
protocols_list = dev_Scanner[host].all_protocols() | ||
|
||
for proto in devScanner[host].all_protocols(): | ||
print( f"\tProtocolo: { proto }" ) | ||
lport = devScanner[host][proto].keys() | ||
if len( protocols_list ) > 0: | ||
protocols_table = Table( f"[green]Parámetro", "[green]Datos", title = "[bold][green]* Protocolos *", title_justify = "center", box = box.ROUNDED ) | ||
|
||
for proto in dev_Scanner[host].all_protocols(): | ||
protocols_table.add_row( f"Protocolo:", f"{proto}" ) | ||
|
||
lport = dev_Scanner[host][proto].keys() | ||
#lport.sort() | ||
for port in lport: | ||
print ( f"\t\tPuerto: { port }\tEstado: { devScanner[host][proto][port]['state'] }" ) | ||
|
||
print( separator ) | ||
else: | ||
print( "\nNo se encontraron dispositivos en el segmento de red indicado." ) | ||
|
||
protocols_table.add_row( f"Puerto:", f"{port}" ) | ||
protocols_table.add_row( f"Estado:", f"{dev_Scanner[host][proto][port]['state']}" ) | ||
|
||
### Script Body Code | ||
print( "\n*** Clark's Network Devices Scanner ***\n" ) | ||
print( "" ) | ||
print( protocols_table ) | ||
|
||
devScanner = nmap.PortScanner() | ||
|
||
ip = input( "Ingrese el Rango Ip: " ) | ||
|
||
print( "\nBuscando dispositivos presentes en la red del rango Ip indicado: ", ip ) | ||
print( "Un momento por favor, en breve se mostrará el resultado.\nDetectando..." ) | ||
|
||
devScanner.scan( ip ) | ||
|
||
printFoundHosts( devScanner.all_hosts() ) | ||
|
||
# Fin del Script - Mensaje de Despedida | ||
print( "\nGracias por usar este Script, es todo por ahora, hasta pronto, bye. :)" ) | ||
print( "@ClarkCodes(en todas las redes sociales).\n\n" ) | ||
print( f"[yellow]{SEPARATOR}" ) | ||
else: | ||
print( "[bright_black]\nNo se encontraron dispositivos en el segmento de red indicado." ) | ||
|
||
def is_ip_range_valid( ip_range : str ): | ||
dots_counter = ip_range.count( '.' ) | ||
|
||
if( dots_counter != 3 ): | ||
return False | ||
|
||
segments_list = ip_range.split( '.' ) | ||
|
||
for index, segment in enumerate( segments_list ): | ||
if( ( index < 3 or ( index == 3 and segment.find( '/' ) == -1 ) ) ): | ||
number = int( segment ) | ||
|
||
if( number < 0 or number > 255 ): | ||
return False | ||
|
||
return True | ||
|
||
# Función Principal | ||
def main(): | ||
print( "[bold green]\n*** Clark's Network Devices Scanner ***" ) | ||
|
||
while True: # Bucle para Repetir el Menú hasta que el usuario decida salir. | ||
print( "\n[bright_cyan]* Lobby de Opciones *[/bright_cyan]\nIngrese un rango ip para escanear la red o ingrese 'q' para salir." ) | ||
|
||
user_input = input( "\nIngrese el Rango Ip: " ) | ||
|
||
if( user_input == 'q' or user_input == 'Q' ): # Condición de Salida | ||
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." ) | ||
break | ||
|
||
try: | ||
if( not is_ip_range_valid( user_input ) ): | ||
raise ValueError | ||
|
||
print( "" ) | ||
with Progress( SpinnerColumn(), TextColumn( "[yellow][progress.description]{task.description}" ), transient = True ) as progress: | ||
progress.add_task( description="[light_sky_blue1]Buscando dispositivos presentes en la red dentro del rango Ip indicado... Un momento por favor...", total = None ) | ||
|
||
dev_Scanner.scan( user_input ) | ||
printFoundHosts( dev_Scanner.all_hosts() ) | ||
|
||
except ValueError: | ||
print( "\n❌ La estructura del rango ip no es válida, verifique nuevamente." ) | ||
except Exception as ex: | ||
print( "\n❌ Oops... algo no ha salido bien, revise nuevamente por favor." ) | ||
print( "Message Error: ", ex ) | ||
|
||
# Llamada a la Función Principal usando typer | ||
if __name__ == "__main__": | ||
typer.run( main ) |