Filtros de paquetes de Berkeley (BPF)

WiresharkBeginner
Practicar Ahora

Introducción

¡Bienvenido al laboratorio de filtros de paquetes de Berkeley (BPF)!

Imagina que intentas encontrar una conversación específica en un estadio lleno de gente y ruido. Así es como se siente analizar el tráfico de red en bruto. Un servidor ocupado puede gestionar miles de paquetes cada segundo. Para encontrar los datos específicos que necesitas, requieres un colador de alta precisión.

Aquí es donde entran en juego los filtros de paquetes de Berkeley (BPF). BPF es una tecnología profundamente integrada y altamente eficiente que te permite establecer reglas —como una red de pesca especializada— para capturar solo el tráfico de red que te interesa, dejando que el resto pase desapercibido.

Lo importante es entender que el filtrado no es solo una cuestión de conveniencia. Se trata de reducir el ruido antes de que se convierta en un problema. Sin filtros, el análisis de paquetes se convierte rápidamente en una sobrecarga de información. Con filtros, puedes transformar un flujo enorme y caótico en una pregunta enfocada, como "muéstrame el tráfico de este host" o "muéstrame solo las solicitudes web a este puerto". Esa capacidad es una de las razones principales por las que tcpdump sigue siendo útil incluso en grandes entornos de producción.

En este laboratorio, utilizarás tcpdump para practicar la escritura de estas reglas BPF. Aprenderás a filtrar el caótico flujo de red por direcciones IP específicas, controlar la dirección del tráfico (envío frente a recepción) y apuntar a puertos de aplicaciones específicos. Al finalizar, sabrás cómo combinar estas reglas para extraer quirúrgicamente los eventos exactos que necesitas.

Filtrar por dirección IP (Host/Red)

La forma más básica de filtrar el tráfico es centrándose en una máquina específica, identificada por su dirección IP. Cuando ejecutas tcpdump sin ningún filtro, captura implacablemente cada paquete que ve. Para indicarle que ignore todo excepto el tráfico que involucra a una máquina en particular, utilizas la palabra clave host seguida de la dirección IP.

Este es un buen momento para separar dos conceptos que los principiantes suelen confundir: una interfaz es el lugar donde estás escuchando, mientras que un filtro IP describe qué conversaciones quieres obtener desde ese punto de escucha. En otras palabras, -i lo decide dónde se coloca tu micrófono, y host 127.0.0.1 decide qué orador en la sala te interesa.

Para asegurarnos de que tenemos tráfico que observar, ya hay un script en segundo plano ejecutándose en tu entorno. Envía datos continuamente a tu máquina local, que siempre tiene la dirección IP interna 127.0.0.1 (también conocida como localhost).

Capturemos 5 paquetes que involucren a este host local. Usaremos -i lo para escuchar en la interfaz de bucle local (loopback) y -c 5 para detenernos automáticamente.

Ejecuta el siguiente comando en tu terminal:

sudo tcpdump -i lo -c 5 host 127.0.0.1

Tu pantalla mostrará una salida similar a esta:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:15:32.123456 IP localhost.45678 > localhost.http-alt: Flags [S], seq 123456789, win 65495, options [mss 65495,sackOK,TS val 123456 ecr 0,nop,wscale 7], length 0
10:15:32.123489 IP localhost.http-alt > localhost.45678: Flags [S.], seq 987654321, ack 123456790, win 65483, options [mss 65495,sackOK,TS val 123456 ecr 123456,nop,wscale 7], length 0
10:15:32.124000 IP localhost > localhost: ICMP echo request, id 1234, seq 1, length 64
...
5 packets captured

Observa que en cada paquete listado, localhost (que es el nombre amigable para 127.0.0.1) está presente. El filtro host es altamente inclusivo: captura el paquete independientemente de si la dirección IP especificada envió los datos o los recibió.

Si alguna vez necesitas monitorear todo un vecindario de computadoras en lugar de una sola casa, puedes cambiar la palabra clave host por net (por ejemplo, net 192.168.1.0/24). Por ahora, nos limitaremos a explorar nuestro único host.

Filtrar por dirección (Origen/Destino)

Saber que una computadora específica está involucrada en una conversación es útil, pero a veces necesitas más precisión. Imagina una oficina de correos: podrías querer mirar solo las cartas que una persona está enviando, ignorando por completo las que está recibiendo.

La dirección importa porque el tráfico de envío y recepción a menudo responde a diferentes preguntas de investigación. El tráfico saliente puede revelar con qué está intentando contactar un host, lo cual es útil al buscar devoluciones de llamadas de malware o exfiltración de datos. El tráfico entrante puede revelar qué servicios están siendo atacados, lo cual es útil al investigar escaneos o ataques contra un servidor.

BPF te ofrece los modificadores src (origen) y dst (destino) para dictar la dirección exacta del tráfico.

Refinemos nuestro filtro para capturar solo los paquetes que se originan desde 127.0.0.1. Al combinar el modificador src con nuestra palabra clave host anterior, le decimos a tcpdump exactamente qué buscar.

Ejecuta el siguiente comando:

sudo tcpdump -i lo -c 3 src host 127.0.0.1

Un consejo rápido: escribir src 127.0.0.1 también funciona porque se asume la palabra host, pero escribirlo como src host se considera una buena práctica, ya que hace que tu comando sea increíblemente fácil de leer.

Tu salida se verá así:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:20:15.555111 IP localhost.54321 > localhost.http-alt: Flags [P.], seq 1:85, ack 1, win 512, options [nop,nop,TS val 234567 ecr 234567], length 84
10:20:15.555888 IP localhost.http-alt > localhost.54321: Flags [.], ack 85, win 512, options [nop,nop,TS val 234568 ecr 234567], length 0
10:20:16.111222 IP localhost > localhost: ICMP echo request, id 5678, seq 1, length 64
3 packets captured

Si observas detenidamente la salida, la primera parte de la descripción del paquete (la sección antes del símbolo >) representa al remitente (origen). Debido a que estamos capturando en la interfaz de bucle local interna, ambos lados dicen localhost, pero en un escenario del mundo real que abarca varias computadoras, src garantiza que solo estás viendo el tráfico saliente desde esa dirección específica.

Por el contrario, si quisieras actuar como receptor y solo observar el tráfico entrante que llega a la máquina, simplemente usarías dst host 127.0.0.1.

Filtrar por puerto y protocolo

Filtrar por direcciones IP nos lleva a la máquina correcta, pero los servidores modernos realizan muchas tareas simultáneamente. Un solo servidor puede actuar al mismo tiempo como servidor web, servidor de correo y punto de acceso seguro. Estos diferentes servicios se mantienen separados mediante el uso de "puertas" numeradas llamadas puertos.

Los puertos no son enchufes físicos. Son números lógicos utilizados por el sistema operativo para mantener muchas conversaciones separadas al mismo tiempo. Es por eso que "mismo host" no significa necesariamente "misma aplicación". Una máquina puede estar involucrada en muchas actividades de red no relacionadas, y el filtrado por puerto te ayuda a aislar el servicio exacto que pretendes estudiar.

Por ejemplo, el tráfico web regular casi siempre fluye a través del puerto 80. Para acercarnos a un servicio específico e ignorar el resto, usamos la palabra clave port.

Nuestro script en segundo plano está generando silenciosamente tráfico web en el puerto 8080. Configuremos tcpdump para capturar solo los datos que pasan a través de esta puerta específica.

Ejecuta el siguiente comando:

sudo tcpdump -i lo -c 4 port 8080

Ejemplo de salida:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:25:10.123456 IP localhost.34567 > localhost.http-alt: Flags [S], seq 1122334455, win 65495, options [mss 65495,sackOK,TS val 345678 ecr 0,nop,wscale 7], length 0
10:25:10.123489 IP localhost.http-alt > localhost.34567: Flags [S.], seq 5544332211, ack 1122334456, win 65483, options [mss 65495,sackOK,TS val 345678 ecr 345678,nop,wscale 7], length 0
10:25:10.123501 IP localhost.34567 > localhost.http-alt: Flags [.], ack 1, win 512, options [nop,nop,TS val 345678 ecr 345678], length 0
10:25:10.124111 IP localhost.34567 > localhost.http-alt: Flags [P.], seq 1:85, ack 1, win 512, options [nop,nop,TS val 345679 ecr 345678], length 84
4 packets captured

Quizás recuerdes de los pasos anteriores que había paquetes ICMP (ping) flotando. Sin embargo, en esta salida, no hay absolutamente ninguna señal de ellos. El filtro port 8080 ignoró con éxito toda la charla no relacionada, proporcionando una vista limpia solo del servicio web.

Además de los puertos, también puedes filtrar por el protocolo de red general directamente nombrándolo, usando palabras clave como tcp, udp o icmp. Probemos esto capturando solo los paquetes ICMP (ping), ignorando efectivamente el tráfico web ocupado.

Ejecuta este comando:

sudo tcpdump -i lo -c 2 icmp

Ejemplo de salida:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:28:05.999111 IP localhost > localhost: ICMP echo request, id 9012, seq 1, length 64
10:28:05.999133 IP localhost > localhost: ICMP echo reply, id 9012, seq 1, length 64
2 packets captured

El uso de palabras clave de port y protocolo te permite cortar el ruido y concentrarte exactamente en la aplicación que estás tratando de investigar.

Combinar filtros con lógica (AND/OR)

Para dominar verdaderamente los filtros de paquetes de Berkeley, debemos aprender a combinar múltiples reglas. Las investigaciones del mundo real rara vez son sencillas; a menudo necesitas definir escenarios altamente específicos.

Aquí es donde BPF comienza a sentirse menos como una lista de palabras clave y más como un pequeño lenguaje de consulta para paquetes. Estás describiendo el tráfico que deseas de una manera estructurada y lógica. Más adelante en el curso, esta forma de pensar reaparecerá en muchas herramientas: las búsquedas SIEM, las reglas de detección de intrusos e incluso las consultas de registros al estilo de bases de datos dependen del mismo hábito de reducir un conjunto de datos amplio a una condición precisa.

BPF te permite unir condiciones utilizando operadores lógicos estándar:

  • and (ambas reglas deben ser verdaderas)
  • or (al menos una regla debe ser verdadera)
  • not (la regla debe ser explícitamente falsa)

Un consejo importante: al usar operadores lógicos como estos en la terminal de Linux, es una muy buena costumbre envolver toda tu expresión BPF entre comillas (como "port 80 and tcp"). Esto asegura que el shell de Linux no confunda accidentalmente tus comandos de filtro con comandos del sistema.

Probemos esto. Queremos capturar tráfico que utilice estrictamente el protocolo TCP y que se dirija activamente al puerto de destino 8080.

Ejecuta el siguiente comando:

sudo tcpdump -i lo -c 4 "tcp and dst port 8080"

Ejemplo de salida:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:32:15.111222 IP localhost.45678 > localhost.http-alt: Flags [S], seq 2233445566, win 65495, options [mss 65495,sackOK,TS val 456789 ecr 0,nop,wscale 7], length 0
10:32:15.111255 IP localhost.45678 > localhost.http-alt: Flags [.], ack 3344556678, win 512, options [nop,nop,TS val 456789 ecr 456789], length 0
...
4 packets captured

En este resultado personalizado, localhost.http-alt solo aparece en el lado derecho de la flecha >, lo que demuestra que solo capturamos paquetes destinados a ese puerto exacto.

Finalmente, veamos el operador not. Es increíblemente útil para filtrar el "ruido conocido" para que puedas concentrarte en lo desconocido. Imagina que queremos monitorear todo el tráfico en la interfaz de bucle local, excepto nuestro tráfico web ruidoso en el puerto 8080.

Ejecuta este comando:

sudo tcpdump -i lo -c 2 "not port 8080"

Ejemplo de salida:

tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:35:22.333444 IP localhost > localhost: ICMP echo request, id 3456, seq 1, length 64
10:35:22.333466 IP localhost > localhost: ICMP echo reply, id 3456, seq 1, length 64
2 packets captured

Debido a que le dijimos explícitamente a tcpdump que desterrara el puerto 8080 de los resultados, capturó pacíficamente los paquetes ICMP ping de fondo subyacentes. Al encadenar estratégicamente and, or y not, puedes forjar una lente increíblemente precisa para ver exactamente lo que necesitas en cualquier red.

Resumen

¡Felicidades! Has entrado con éxito en el mundo del filtrado avanzado de paquetes.

Has aprendido a tamizar un flujo de red caótico para encontrar exactamente lo que necesitas. Practicaste cómo apuntar a computadoras específicas usando la palabra clave host y controlaste la dirección del flujo con src y dst. Aislaste aplicaciones particulares filtrando por un port y protocolo distintos. Lo más importante es que aprendiste a combinar todas estas piezas individuales utilizando operadores lógicos (and, or, not) para construir búsquedas quirúrgicas y altamente específicas.

Estas habilidades son indispensables. Ya seas un administrador de sistemas que busca una conexión no autorizada o un analista de seguridad que rastrea un ataque sofisticado, dominar los filtros de paquetes de Berkeley garantiza que nunca más te verás abrumado por el ruido de la red. ¡Sigue experimentando con diferentes combinaciones!