Blog
Python: Identificar usuarios conectados a una red Wi-Fi
- Publicado por: Hebert
- Categoría: Blog
Las redes Wi-Fi son muy utilizadas actualmente y no es un demás decir que también debemos tener mucho cuidado de los intrusos. La mayoría de los routers permiten ver los usuarios conectados a él, pero ¿Qué pasa si tu router no muestra la lista de clientes? o ¿Qué pasa si tu router muestra la lista de clientes pero tienes clientes ocultos?. Bueno, acá en este post aprenderemos con Python a crear una identificador de usuarios en una red wi-fi.
Lo primero que debemos hacer es instalar los paquetes necesarios que vamos a usar en nuestro programa, estos son scapy y WinPcap este último si estás en windows puesto que en linux y MAC solo basta con instalar scapy.
Para instalar scapy solo debemos ejecutar en la terminal
pip install scapy
Para instalar WinPcap podemos descargarlo e instalarlo
https://www.winpcap.org/install/
Muy bien, una vez hecho todo esto podemos comenzar a escribir nuestro código, primero debemos construir una función que nos ayude a analizar la red wi-fi a la que estamos conectados, ya que previamente debemos estar conectados a la red para saber que usuarios están conectados.
La forma en como vamos a hacer esto es viendo los paquetes ARP que se envían desde otros equipos y todos ellos serán identificados gracias a scapy el cual nos dirá de que IP proviene y de que dispositivo, ¿genial no?. Algo bastante útil para monitorear redes propias.
Vamos a abrir una terminal y buscamos los parámetros de nuestra ip como yo estoy en windows voy a tipear
ipconfig # Al ejecutar el comando obtenemos algo como lo siguiente Adaptador de LAN inalámbrica Wi-Fi: Sufijo DNS específico para la conexión. . : Vínculo: dirección IPv6 local. . . : ******************** Dirección IPv4. . . . . . . . . . . . . . : ************ Máscara de subred . . . . . . . . . . . . : *********** Puerta de enlace predeterminada . . . . . : 192.168.1.1 # Note que he censurado los otros parámetros con "*", solo he dejado la puerta de enlace predeterminada ya que es la que nos interesa.
Al obtener la puerta de enlace predeterminada, entonces podremos comenzar con el código para así escanear la red y conseguir lo que queremos ya que está será la dirección ip que debemos utilizar.
# Lo primordial es importar la librería de scapy de la siguiente forma import scapy.all as scapy from time import time # Ahora vamos a construir una función que nos ayude a analizar la red wifi a la cual estamos conectados. def escanear(direccion_ip): scapy.arping(direccion_ip) escanear("192.168.1.1/24") # Para identificar a todos los usuarios dentro de esta puerta de enlace predeterminada debemos colocar /24 al final de la ip # >>> Al ejecutar el código obtuve el siguiente resultado: c0:06:c3:2c:8d:1a unknown 192.168.1.1 f6:a5:5b:2d:c1:eb unknown 192.168.1.100 a8:9c:ed:3e:b5:9d unknown 192.168.1.102 10:b1:f8:2e:eb:87 unknown 192.168.1.108
Este resultado me indica que 4 dispositivos en mi red Wi-Fi están enviando paquetes ARP, pero acá no estamos identificando todos los que están en la red ya que solo se muestran los dispositivos que enviaron información ARP al momento que se realizó el escaneo.
Ahora vamos a modificar un poco el código para ver las solicitudes ARP que están enviando solicitudes ARP a la puerta de enlace
def escanear(direccion_ip): solicitud_arp = scapy.ARP(pdst=direccion_ip) print(solicitud_arp.summary()) escanear("192.168.1.1/24") # >>> El ejecutar el código obtuve el siguiente resultado: ARP who has Net("192.168.1.1/24") says 192.168.1.106
Este resultado indica que en la NET o puerta de enlace predeterminada alguien está hablando como “192.168.1.106” esto lo que quiere decir es que la dirección de ip 192.168.1.106 está haciendo solicitudes ARP a nuestro router.
Pero para construir el programa que queremos aún faltan un par de cosas, ahora lo que debemos hacer es hacer que el broadcast de la solicitud sea visible ya que el broadcast prácticamente es la dirección mac del dispositivo que está enviando la solicitud y luego mostrar el marco ETHER que es donde podremos visualizar dichos datos, nuestra función ahora quedaría de la siguiente manera.
def escanear(direccion_ip): solicitud_arp = scapy.ARP(pdst=direccion_ip) broadcast = scapy.Ether() scapy.ls(scapy.Ether()) escanear("192.168.1.1/24") # >>> Al ejecutar el código obtuve como resultado lo siguiente: dst : DestMACField = 'ff:ff:ff:ff:ff:ff' ('None') src : SourceMACField = '00:27:11:01:d4:d1' ('None') type : XShortEnumField = 36864 ('36864')
Este resultado nos indica los parámetros que podemos utilizar para seguir construyendo nuestro programa, en este caso nos interesa el Broadcast Destination (dst) que para este caso es “ff:ff:ff:ff:ff:ff” ahora lo que debemos hacer es pasarle este dato a nuestro broadcast para que pueda centrar sus análisis en base a este.
Hasta este punto tenemos una dirección destino (dst) y una ip, ahora lo que tenemos que hacer es combinar ambas para luego escribir una instrucción que le pregunte a cada solicitud dentro del router quien tiene dicha ip, nuestra función se transformaría en lo siguiente:
def escanear(direccion_ip): solicitud_arp = scapy.ARP(pdst=direccion_ip) broadcast = scapy.Ether(dst='ff:ff:ff:ff:ff:ff') # Fusionamos solicitud_arp_broadcast = broadcast/solicitud_arp respuesta = scapy.srp(solicitud_arp_broadcast, timeout=1) # Con esta instrucción le decimos que queremos que pregunte a cada solicitud dentro del router a quién le pertenece dicha ip. escanear("192.168.1.1/24") # >>> Al ejecutar el código obtuve el siguiente resultado: Finished sending 256 packets. ...............................................................................................................................................................................................................................................................................................................................................................................................................................................*.*..*......................................... Received 478 packets, got 3 answers
Podemos observar que obtuve 478 paquetes, 3 respuestas lo que sigue en este punto es imprimir esos paquetes de los que se obtienen respuesta, vamos a hacerlo recorriendo la respuesta la cuál es una lista y le indicaremos que queremos traer únicamente los datos de la primera posición de la respuesta ya que nos interesa el psrc y el hwsrc.
def escanear(direccion_ip): solicitud_arp = scapy.ARP(pdst=direccion_ip) broadcast = scapy.Ether(dst='ff:ff:ff:ff:ff:ff') # Fusionamos solicitud_arp_broadcast = broadcast/solicitud_arp respuesta = scapy.srp(solicitud_arp_broadcast, timeout=1)[0] print("IP\t\t\tMAC Address\n-----------------------------------------") for element in respuesta: print(element[1].psrc + '\t\t' + element[1].hwsrc) escanear("192.168.1.1/24") # >>> Al ejecutar el código obtuve el siguiente resultado: Finished sending 256 packets. .............................................................................................................................................................................................................................................................................................................................................**..........*.. Received 348 packets, got 3 answers, remaining 253 packets IP MAC Address ----------------------------------------- 192.168.1.104 64:e0:03:65:f4:5d 192.168.1.108 10:b1:f8:2e:eb:87 192.168.1.111 b8:ae:ed:55:01:bc
Ahora podemos ver que restamos recibiendo la dirección de ip de cada dispositivo con su respectivo mac address, esto ya comienza a tener forma pero para que esto aún quede un poco más sólido, lo que podemos hacer es guardar los datos en una colección de diccionarios y programar una función que imprima estos resultados para que nuestro código sea más legible y esto lo podemos lograr de la siguiente manera
def escanear(direccion_ip): solicitud_arp = scapy.ARP(pdst=direccion_ip) broadcast = scapy.Ether(dst='ff:ff:ff:ff:ff:ff') # Fusionamos solicitud_arp_broadcast = broadcast/solicitud_arp respuesta = scapy.srp(solicitud_arp_broadcast, timeout=1)[0] # Con esta instrucción le decimos que queremos que pregunte a cada solicitud dentro del router a quién le pertenece dicha ip. lista_clientes = [] # Creamos el diccionario for elemento in respuesta: cliente = {"IP": elemento[1].psrc, "MAC Address": elemento[1].hwsrc} lista_clientes.append(cliente) return (lista_clientes) def imprimir_resultados(clientes): print("IP\t\t\tMAC Address\n-----------------------------------------") for cliente in clientes: print(cliente["IP"] + "\t\t" + cliente["MAC Address"]) clientes = escanear("192.168.1.1/24") imprimir_resultados(clientes) # Al ejecutar el código obtuve el siguiente resultado IP MAC Address ----------------------------------------- 192.168.1.101 08:25:25:f1:af:4e 192.168.1.110 24:da:9b:f4:84:ca
Así es como hemos creado un identificador de usuarios para una red wi-fi, los puntos importantes a considerar en este identificador es que solo funciona cuando estamos conectados a dicha red, no podrás escanear cualquier red a la cuál no puedas acceder.
Otro punto super importante es que carece de precisión puesto que solo detecta a los usuarios que estén enviando solicitudes ARP al momento en que se está realizando el escaneo, pero esto puede solucionarse fácilmente colocando nuestro código en un bucle while para que este se ejecute muchas veces y así poder monitores una red las veces que deseemos.