Introducción
Scapy es un potente programa y biblioteca interactiva de manipulación de paquetes escrita en Python. Te permite forjar o decodificar paquetes de una amplia gama de protocolos, enviarlos a través de la red, capturarlos y hacer coincidir solicitudes con respuestas.
Lo que hace especial a Scapy es que te permite trabajar en la capa de construcción de paquetes en lugar de limitarte a la capa de socket o de aplicación. Esto significa que puedes controlar explícitamente encabezados, flags, campos y combinaciones de protocolos de una manera que las bibliotecas de cliente convencionales suelen ocultar.
En este laboratorio, aprenderás los fundamentos de la creación de paquetes utilizando Scapy. Comenzarás importando los módulos necesarios, luego pasarás a forjar paquetes ICMP (ping) y TCP capa por capa. Finalmente, enviarás estos paquetes personalizados y analizarás las respuestas de la red. Esta experiencia práctica te brindará una comprensión más profunda de cómo funcionan los protocolos de red internamente y cómo los profesionales de la seguridad prueban las defensas de una red.
Importar módulos de Scapy
En este paso, configurarás tu entorno de Python e importarás los módulos necesarios de Scapy. Aunque Scapy puede utilizarse como una consola interactiva, escribir scripts te permite guardar, modificar y reutilizar tu lógica de creación de paquetes fácilmente.
Este es un cambio de paradigma: pasas de usar protocolos a construirlos. En lugar de pedirle a una aplicación existente que envíe tráfico por ti, tú mismo defines cómo debe ser ese tráfico.
Primero, asegúrate de estar en tu directorio de trabajo predeterminado. Puedes usar el comando pwd para verificarlo, pero ya deberías estar en ~/project.
Crea un nuevo archivo de Python llamado packet_crafter.py usando el editor de texto nano.
nano packet_crafter.py
Dentro de este archivo, necesitas importar la biblioteca Scapy. La forma estándar de usar Scapy en scripts es importar todas las funciones del módulo scapy.all. Añade las siguientes líneas a tu script:
from scapy.all import *
print("Módulos de Scapy importados correctamente.")
Guarda el archivo con Ctrl+O y Enter. Si deseas seguir construyendo el script antes de probarlo, puedes permanecer en nano. Usa Ctrl+X cuando estés listo para volver a la terminal.
Ahora, ejecuta tu script usando Python para asegurarte de que no haya errores de sintaxis y que la biblioteca Scapy se cargue correctamente. Debido a que la creación de paquetes de red en bruto requiere privilegios elevados, debes ejecutar el script con sudo.
sudo python3 packet_crafter.py
Deberías ver una salida similar a la siguiente, lo que indica éxito:
Módulos de Scapy importados correctamente.
En algunos entornos de laboratorio, Scapy puede imprimir una advertencia adicional de paquetes opcionales de Python, como matplotlib, antes del mensaje de éxito. Si aún ves Módulos de Scapy importados correctamente., puedes continuar con el siguiente paso.
Forjar una solicitud de eco ICMP
En este paso, forjarás un paquete de solicitud de eco ICMP (ICMP Echo Request), comúnmente conocido como "ping". Los paquetes de red se construyen en capas, siguiendo el modelo OSI. En Scapy, puedes apilar estas capas usando el operador /.
La estratificación es uno de los conceptos más importantes que debes asimilar aquí. Cada capa añade sus propios campos y responsabilidades. Scapy refleja ese modelo directamente, razón por la cual su sintaxis facilita la comprensión de la estructura de los paquetes.
Un ping ICMP requiere una capa IP (capa de red) para especificar las direcciones de origen y destino, y una capa ICMP para definir el tipo de mensaje.
Si packet_crafter.py sigue abierto en nano, continúa editándolo. De lo contrario, ábrelo de nuevo:
nano packet_crafter.py
Añade el siguiente código al final de tu script. Este código crea un objeto IP dirigido al servidor DNS público de Google (8.8.8.8), crea un objeto ICMP y los apila juntos. El método show() imprimirá un desglose detallado de la estructura del paquete.
## Crear una capa IP dirigida al DNS de Google
ip_layer = IP(dst="8.8.8.8")
## Crear una capa ICMP (Echo Request)
icmp_layer = ICMP()
## Apilar las capas para formar el paquete final
icmp_packet = ip_layer / icmp_layer
print("\n--- Estructura del paquete ICMP ---")
icmp_packet.show()
Guarda el archivo con Ctrl+O y Enter. Puedes permanecer en nano y continuar con el siguiente paso si deseas completar más partes del script antes de ejecutarlo.
Ejecuta tu script actualizado para ver la estructura del paquete que acabas de forjar.
sudo python3 packet_crafter.py
Verás una salida detallada que muestra los valores predeterminados que Scapy completó automáticamente por ti, como la versión del protocolo, el TTL (Time To Live) y el tipo de ICMP.
--- Estructura del paquete ICMP ---
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = icmp
chksum = None
src = 10.0.2.15
dst = 8.8.8.8
\options \
###[ ICMP ]###
type = echo-request
code = 0
chksum = None
id = 0x0
seq = 0x0
unused = ''
Crear un paquete TCP SYN personalizado
En este paso, crearás un paquete TCP SYN. Este tipo específico de paquete se utiliza con frecuencia en el escaneo de redes (como el escaneo sigiloso de Nmap) para comprobar si un puerto específico está abierto en una máquina objetivo sin establecer una conexión completa.
Este es un buen ejemplo de cómo pequeños cambios en el encabezado producen comportamientos de red muy diferentes. No estás cambiando el host o puerto de destino, solo los flags y los campos del protocolo, pero esos detalles definen el significado del paquete y cómo lo interpretará el objetivo.
Al igual que con el paquete ICMP, un paquete TCP requiere una capa IP subyacente. Encima de ella, añadirás una capa TCP donde podrás especificar el puerto de destino y los flags TCP. El flag S significa SYN (Synchronize).
Si sigues en la misma sesión de nano, continúa editando packet_crafter.py. De lo contrario, ábrelo de nuevo:
nano packet_crafter.py
Añade el siguiente código a tu script. Reutilizaremos el ip_layer que creaste en el paso anterior y apilaremos una nueva capa TCP encima, apuntando al puerto 80 (HTTP).
## Crear una capa TCP dirigida al puerto 80 con el flag SYN
tcp_layer = TCP(dport=80, flags="S")
## Apilar las capas IP y TCP
tcp_packet = ip_layer / tcp_layer
print("\n--- Estructura del paquete TCP SYN ---")
tcp_packet.show()
Guarda el archivo con Ctrl+O y Enter. Sal con Ctrl+X solo cuando quieras ejecutar el script desde la terminal, o sigue editando y continúa con el paso final.
Ejecuta el script de nuevo para inspeccionar la estructura de tu nuevo paquete TCP SYN.
sudo python3 packet_crafter.py
La salida ahora incluirá los detalles de la capa TCP, mostrando el puerto de destino configurado como http (puerto 80) y los flags configurados como S.
--- Estructura del paquete TCP SYN ---
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = tcp
chksum = None
src = 10.0.2.15
dst = 8.8.8.8
\options \
###[ TCP ]###
sport = ftp_data
dport = http
seq = 0
ack = 0
dataofs = None
reserved = 0
flags = S
window = 8192
chksum = None
urgptr = 0
options = []
Enviar y analizar la respuesta de la red
En este paso final, enviarás realmente el paquete ICMP que forjaste a través de la red y capturarás la respuesta.
Enviar el paquete completa el modelo mental: definir capas, construir el paquete, transmitirlo y luego interpretar la respuesta. Ese es el mismo ciclo de alto nivel detrás de muchas herramientas personalizadas de prueba de red.
Scapy proporciona varias funciones para enviar paquetes. La función sr1() es particularmente útil porque envía un paquete y espera a recibir la primera respuesta que llegue. La "s" significa send (enviar), "r" significa receive (recibir) y "1" indica un solo paquete.
Si mantuviste el archivo abierto, continúa editándolo. De lo contrario, abre packet_crafter.py:
nano packet_crafter.py
Añade el siguiente código para enviar el icmp_packet y analizar la respuesta. Incluimos un parámetro timeout para que el script no se quede bloqueado indefinidamente si el paquete se pierde o es bloqueado.
print("\n--- Enviando paquete ICMP ---")
## Enviar el paquete y esperar 1 respuesta, con un tiempo de espera de 2 segundos
## verbose=0 oculta la salida predeterminada de envío de Scapy para obtener resultados más limpios
response = sr1(icmp_packet, timeout=2, verbose=0)
if response:
print(f"Respuesta recibida de: {response[IP].src}")
print("\n--- Estructura del paquete de respuesta ---")
response.show()
else:
print("No se recibió respuesta. Es posible que el paquete haya sido descartado.")
Guarda el archivo y sal del editor.
Ejecuta tu script para enviar el paquete a Internet y esperar a que el servidor DNS de Google responda.
sudo python3 packet_crafter.py
Si la red permite la solicitud ICMP, verás la estructura del paquete de respuesta. Observa que el tipo de ICMP en la respuesta es echo-reply.
--- Enviando paquete ICMP ---
Respuesta recibida de: 8.8.8.8
--- Estructura del paquete de respuesta ---
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 28
id = 0
flags =
frag = 0
ttl = 114
proto = icmp
chksum = 0x67d8
src = 8.8.8.8
dst = 10.0.2.15
\options \
###[ ICMP ]###
type = echo-reply
code = 0
chksum = 0xffff
id = 0x0
seq = 0x0
unused = ''
###[ Padding ]###
load = '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Resumen
Aprendiste a configurar un script de Python con Scapy, a forjar manualmente paquetes ICMP y TCP capa por capa usando el operador /, y a enviar estos paquetes a través de la red para analizar las respuestas en bruto. Este conocimiento fundamental es crucial para comprender cómo operan los protocolos de red, realizar evaluaciones de seguridad y desarrollar herramientas personalizadas de análisis de red.



