Tabla de Contenidos
Obtener las máquinas activas de un segmento de red
Módulo perteneciente al curso Python avanzado para proyectos de seguridad
ICMP se trata de un protocolo muy útil para diagnóstico de errores en la capa de red y que se utiliza en herramientas tales como TRACEROUTE para el análisis del tráfico de un paquete por los diferentes routers por los que pasa.
El protocolo ICMP es un protocolo de mensajes que permite saber si una máquina determinada está disponible o no. Para ello define una lista de mensajes de control para diferentes propósitos, en el caso del comando PING se utilizan los mensajes Echo Request y Echo Reply.
Ejecutar comando ping en Python
El comando ping utiliza un mensaje ICMP del tipo ECHO_REQUEST para consultar si una máquina se encuentra activa y en el caso de que dicha máquina conteste con un ICMP_ECHO_REPLY dentro del tiempo fijado antes de que se obtenga un timeout, se entiende que la máquina está activa.
Si se obtiene un timeout durante la petición de ping se entiende que la máquina está caída o bien existe algún mecanismo de protección como un proxy que esté filtrando este tipo de mensajes. En este caso utilizamos el módulo subprocess que permite ejecutar el comando ping propio del sistema operativo.
El siguiente código lo podemos encontrar en el fichero comando_ping.py:
#!/usr/bin/env python3 from subprocess import Popen, PIPE import sys import argparse parser = argparse.ArgumentParser(description='Ping Scan Network') # argumentos principales parser.add_argument("--host", dest="host", help="Host o direccion ip", required=True) parsed_args = parser.parse_args() direccion_ip = parsed_args.host print("Scanning %s " %(direccion_ip)) if sys.platform.startswith('linux'): # Linux subprocess = Popen(['/bin/ping', '-c 1 ', direccion_ip], stdin=PIPE, stdout=PIPE, stderr=PIPE) elif sys.platform.startswith('win'): # Win subprocess = Popen(['ping', direccion_ip], stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout, stderr= subprocess.communicate(input=None) print(stdout) if b"Destination Host Unreachable" in stdout or b"100% packet loss" in stdout or b"100% perdidos" in stdout or stdout==b"": print("La dirección IP %s no está activa!" %(direccion_ip)) else: print("La dirección IP %s está activa!" %(direccion_ip))
Ejecución script comando ping
Para ejecutar el anterior script necesitamos pasarle por parámetro el host o dirección ip utilizando el argumento --host:
$ python3 comando_ping.py usage: comando_ping.py [-h] --host HOST comando_ping.py: error: the following arguments are required: --host
Ejemplo de ejecución:
$ python3 comando_ping.py --host 8.8.8.8 Scanning 8.8.8.8 b'PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.\n64 bytes from 8.8.8.8: icmp_seq=1 ttl=119 time=9.74 ms\n\n--- 8.8.8.8 ping statistics ---\n1 packets transmitted, 1 received, 0% packet loss, time 0ms\nrtt min/avg/max/mdev = 9.743/9.743/9.743/0.000 ms\n' La dirección IP 8.8.8.8 está activa!
La idea ahora en el ejercicio que se plantea es ejecutar el comando ping para cada posible máquina que nos encontremos en el segmento de red a analizar con el objetivo de determinar qué maquinas están activas.
Time To Live (TTL): El tiempo de vida de un paquete es un concepto usado en redes de computadores para indicar por cuántos nodos puede pasar un paquete antes de ser descartado por la red o devuelto a su origen.
Actividad práctica: Utilizar el comando ping para determinar las máquinas activas en un segmento de red
Completa el siguiente script que utiliza el módulo subprocess para realizar un ping a cada una de las direcciones ip de nuestra red y nos devuelve para cada dirección ip si está activa utilizando la salida que devuelve el comando ping. Sustituir las xxx por variables o clases definidas en el script.
#!/usr/bin/env python3 from subprocess import Popen, PIPE import sys import argparse parser = argparse.ArgumentParser(description='Ping Scan Network') # argumentos principales parser.add_argument("-network", dest="network", help="NetWork segment[For example 192.168.1]", required=True) parser.add_argument("-machines", dest="machines", help="Machines number",type=int, required=True) parsed_args = parser.parse_args() for ip in xxx(0,parsed_args.machines): direccion_ip = parsed_args.xxx +'.' + str(xxx) print("Scanning %s " %(xxx)) if sys.platform.xxx('linux'): # Linux subprocess = xxx(['/bin/ping', '-c 1 ', xxx], stdin=xxx, stdout=xxx, stderr=xxx) elif sys.platform.xxx('win'): # Windows subprocess = xxx(['ping', xxx], stdin=xxx, stdout=xxx, stderr=xxx) stdout, stderr= subprocess.xxx(input=None) print(stdout) if b"Destination Host Unreachable" in xxx or stdout==b"": print("La dirección IP %s no está activa!" %(xxx)) else: print("La dirección IP %s está activa!" %(xxx))
El objetivo del script es pasar por argumentos al scriot la red a escanear junto con el número de máquinas
usage: PingScanNetWork.py [-h] -network NETWORK -machines MACHINES PingScanNetWork.py: error: the following arguments are required: -network, -machines
Ejemplo de ejecución con máquinas inactivas:
$ python3 PingScanNetWork.py -network 192.168.1 -machines 3 Scanning 192.168.1.0 b'PING 192.168.1.0 (192.168.1.0) 56(84) bytes of data.\n\n--- 192.168.1.0 ping statistics ---\n1 packets transmitted, 0 received, 100% packet loss, time 0ms\n\n' La dirección IP 192.168.1.0 no está activa! Scanning 192.168.1.1 b'PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.\n\n--- 192.168.1.1 ping statistics ---\n1 packets transmitted, 0 received, 100% packet loss, time 0ms\n\n' La dirección IP 192.168.1.1 no está activa! Scanning 192.168.1.2 b'PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.\n\n--- 192.168.1.2 ping statistics ---\n1 packets transmitted, 0 received, 100% packet loss, time 0ms\n\n' La dirección IP 192.168.1.2 no está activa!
Ejemplo de ejecución con máquinas activas
$ python3 PingScanNetWork.py -network 192.168.18 -machines 3 Scanning 192.168.18.0 b'' La dirección IP 192.168.18.0 no está activa! Scanning 192.168.18.1 b'PING 192.168.18.1 (192.168.18.1) 56(84) bytes of data.\n64 bytes from 192.168.18.1: icmp_seq=1 ttl=64 time=3.34 ms\n\n--- 192.168.18.1 ping statistics ---\n1 packets transmitted, 1 received, 0% packet loss, time 0ms\nrtt min/avg/max/mdev = 3.345/3.345/3.345/0.000 ms\n' La dirección IP 192.168.18.1 está activa! Scanning 192.168.18.2 b'PING 192.168.18.2 (192.168.18.2) 56(84) bytes of data.\nFrom 192.168.18.21 icmp_seq=1 Destination Host Unreachable\n\n--- 192.168.18.2 ping statistics ---\n1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms\n\n' La dirección IP 192.168.18.2 no está activa!
Solución
#!/usr/bin/env python3 from subprocess import Popen, PIPE import sys import argparse parser = argparse.ArgumentParser(description='Ping Scan Network') # argumentos principales parser.add_argument("-network", dest="network", help="NetWork segment[For example 192.168.1]", required=True) parser.add_argument("-machines", dest="machines", help="Machines number",type=int, required=True) parsed_args = parser.parse_args() for ip in range(0,parsed_args.machines): direccion_ip = parsed_args.network +'.' + str(ip) print("Scanning %s " %(direccion_ip)) if sys.platform.startswith('linux'): # Linux subprocess = Popen(['/bin/ping', '-c 1 ', direccion_ip], stdin=PIPE, stdout=PIPE, stderr=PIPE) elif sys.platform.startswith('win'): # Windows subprocess = Popen(['ping', direccion_ip], stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout, stderr= subprocess.communicate(input=None) print(stdout) if b"Destination Host Unreachable" in stdout or stdout==b"": print("La dirección IP %s no está activa!" %(direccion_ip)) else: print("La dirección IP %s está activa!" %(direccion_ip))
FAQ
¿Para qué sirve nmap?
Nmap es una herramienta para la exploración de la red y la auditoría de seguridad. Permite realizar escaneados con ping (determinando que máquinas están activas), muchas técnicas de escaneado de puertos, detección de versiones (determinando los protocolos de los servicios y las versiones de las aplicaciones que están escuchando en los puertos), e identificación mediante TCP/IP (identificando el sistema operativo de la máquina o el dispositivo)
