Saltar al contenido
Tutoriales Lucio CODLYX

Wireshark

Análisis de paquetes y ciberseguridad defensiva

Curso completo en cinco partes: fundamentos de captura, los protocolos capa por capa (Ethernet, ARP, IPv4, IPv6, ICMP, TCP, UDP, DNS, DHCP, HTTP y TLS), las herramientas de Wireshark a fondo, análisis defensivo de tráfico y doce laboratorios prácticos con desafíos.

Interfaz
wlan0
Tu IP
10.2.3.170
Gateway
10.2.3.1
Versión
4.7.2
Sistema
Arch / CachyOS
Índice del tutorial

Guía práctica · CachyOS · wlan0 — «Wireshark en 9 capturas»

Nueve ejercicios en orden, cada uno construido sobre el anterior. Abres Wireshark, ejecutas el comando, miras lo que aparece. Al final sabes leer una conversación de red entera.

Esa era la promesa de la primera versión y sigue en pie: los nueve ejercicios están todos aquí. Alrededor han crecido cuatro partes más, hasta cubrir el camino completo —qué es un paquete, cómo se lee cada protocolo, cómo se maneja Wireshark de verdad y cómo se usa todo eso para investigar tráfico sospechoso—. Puedes leerlo de principio a fin como un curso, o entrar por el índice a la sección que necesites.

Parte 01Fundamentos

Fundamentos

Qué es un paquete, qué hace Wireshark con él y cómo se mueve uno por el programa.

Qué es Wireshark y qué no es

Antes de instalar nada, conviene saber qué esperas de la herramienta.

Wireshark es un analizador de protocolos de red. Hace dos cosas, y es útil separarlas desde el principio porque son independientes:

1 · Capturar
Le pide al sistema operativo una copia de cada trama que entra o sale por una interfaz de red, y la guarda. Esta parte es privilegiada y en Linux la hace un binario aparte, dumpcap.
2 · Analizar
Coge esos bytes y los disecciona: reconoce que los primeros catorce son una cabecera Ethernet, que dentro hay IP, dentro TCP, dentro HTTP, y te lo presenta con nombres. Esta parte no necesita permisos: puedes analizar un fichero guardado sin capturar nada.

Un sniffer es cualquier programa que hace lo primero. Wireshark es un sniffer, pero su valor está en lo segundo: conoce más de tres mil protocolos y sabe desmontarlos campo a campo.

Lo que Wireshark no hace

Esto ahorra malentendidos, y algunos son frecuentes:

  • No bloquea, no modifica, no inyecta. Es un microscopio, no un cortafuegos. Si algo va mal en tu red, Wireshark te dice qué está pasando, pero arreglarlo es otra herramienta.
  • No descifra tráfico ajeno. Sin las claves, HTTPS es ruido. Más adelante descifrarás tráfico tuyo porque tu propio navegador te presta sus claves; no hay forma de conseguir las de nadie más.
  • No detecta ataques por su cuenta. No es un IDS. Marca anomalías de protocolo, y eres tú quien decide si significan algo.
  • No ve lo que no pasa por tu interfaz. Esta es la limitación que más sorprende y merece su propio apartado.

Trama, paquete y qué ve realmente tu tarjeta

Los términos se usan indistintamente en conversación, pero designan cosas distintas y Wireshark los distingue en el árbol:

Unidades de datos por capa
NombreCapaQué incluye
Trama (frame)EnlaceTodo lo que viaja por el cable o el aire, cabecera Ethernet incluida. Es la unidad que Wireshark numera y cronometra.
Paquete (packet)RedLa cabecera IP y su contenido, sin la envoltura Ethernet.
SegmentoTransporteLa unidad de TCP. En UDP se llama datagrama.

Por eso el campo frame.len mide la trama completa y ip.len solo el paquete IP: son números distintos y la diferencia son los 14 bytes de Ethernet.

Tráfico propio, tráfico ajeno y modo promiscuo

Una tarjeta de red normal descarta las tramas que no van dirigidas a su MAC. En modo promiscuo deja de descartarlas y entrega todo lo que oye. Suena potente, pero en una red moderna oye menos de lo que parece:

  • En una red con switch (todas las cableadas de hoy), el switch envía cada trama solo al puerto de su destinatario. En modo promiscuo verás tu propio tráfico, el broadcast y el multicast — no las conversaciones de tus vecinos.
  • En wifi hace falta además el modo monitor, que es otra cosa: captura tramas 802.11 en bruto del aire. Muchos controladores no lo soportan y al activarlo pierdes la conexión.
  • Para ver tráfico de terceros de forma legítima se usa un port mirroring / SPAN configurado en el switch, o un TAP físico. Es una decisión de infraestructura, no una casilla de Wireshark.

Las cuatro limitaciones de cualquier captura

Tenlas presentes antes de sacar conclusiones de una investigación:

  1. Punto de observación. Solo ves lo que pasa por donde capturas. Un mismo incidente se ve distinto desde el portátil, desde el router o desde el servidor.
  2. Ventana temporal. Una captura de dos minutos no dice nada sobre un patrón que se repite cada hora.
  3. Cifrado. Ves con quién se habla y cuánto, casi nunca qué se dice.
  4. Pérdida. Si el equipo va justo de CPU o disco, dumpcap descarta tramas. El diálogo Statistics → Capture File Properties te dice cuántas se perdieron; si el número no es cero, tu captura está incompleta.

Instalar y entender los permisos

Dos paquetes y un grupo de usuario. Y una lección de diseño seguro.

Wireshark en Arch viene partido en dos: wireshark-cli trae el motor de captura y las herramientas de terminal, wireshark-qt añade la interfaz gráfica. Instalando el segundo entra el primero como dependencia.

bash
$ sudo pacman -S wireshark-qt

Capturar paquetes es una operación privilegiada: le estás pidiendo al kernel que te entregue tramas en crudo de la tarjeta de red. Ejecutar toda la GUI como root sería una mala idea (es un programa enorme que parsea datos hostiles de la red), así que Wireshark aísla esa parte en un binario diminuto, dumpcap, y da acceso solo a los miembros del grupo wireshark.

bash
$ sudo usermod -aG wireshark $USER

Verifica que todo está en su sitio:

bash
$ tshark --version | head -1
$ getcap /usr/bin/dumpcap
/usr/bin/dumpcap cap_net_admin,cap_net_raw=ep

Esas dos capabilities son exactamente los permisos mínimos: cap_net_raw para leer tramas crudas y cap_net_admin para poner la interfaz en modo promiscuo. Nada más.

Leer la salida de getcap, letra a letra

Las capabilities de Linux trocean el poder de root en permisos sueltos, para poder dar uno sin dar todos. La salida tiene forma nombre=letras y cada letra es un conjunto:

Conjuntos de capabilities en la salida de getcap
LetraConjuntoSignificado
eeffectiveActiva en cuanto arranca el proceso, sin que el programa tenga que pedirla.
ppermittedEl proceso tiene derecho a usarla.
iinheritableSe transmite a procesos hijos que también la tengan marcada.

Así que cap_net_admin,cap_net_raw=ep se lee: «este binario puede leer tramas crudas y administrar la interfaz, y esos permisos están activos desde el arranque». Si tu salida incluye además cap_dac_override o termina en =eip, tu distribución ha sido algo más generosa; es habitual y no es un problema, pero ahora sabes leerlo.

Comprueba también quién puede ejecutarlo:

bash
$ ls -l /usr/bin/dumpcap
-rwxr-xr-- 1 root wireshark ... /usr/bin/dumpcap

El último tramo de permisos es ---: quien no sea root ni miembro del grupo wireshark ni siquiera puede ejecutarlo. Ese es el mecanismo completo.

Identificar la interfaz correcta

Capturar en la interfaz equivocada es el error número uno de quien empieza: la captura sale vacía y parece que Wireshark no funciona. Averigua primero cuál usas de verdad.

bash
$ ip addr

Busca la interfaz que tenga una dirección inet de tu red y la marca state UP. En este equipo es wlan0 con 10.2.3.170/24. El /24 te dice además que tu red local va de 10.2.3.1 a 10.2.3.254: cualquier IP fuera de ese rango sale por el router.

bash
$ ip link

Muestra lo mismo sin las direcciones IP, pero incluye la MAC (link/ether) y el estado físico del enlace. Es donde verías la marca PROMISC si una interfaz estuviera en modo promiscuo.

bash
$ ip route | head -1
default via 10.2.3.1 dev wlan0

Tu gateway. Apúntalo: aparecerá constantemente, porque todo lo que sale de tu red lleva su MAC como destino en la capa 2.

Y la lista tal y como la ve Wireshark:

bash
$ tshark -D
1. wlan0
2. any
3. lo (Loopback)
4. enp8s0
5. docker0 (Docker Bridge)

Tres de esas merecen un comentario: lo es el tráfico que tu equipo se manda a sí mismo (útil para depurar un servidor local, invisible desde fuera); any es una pseudointerfaz que agrega todas a la vez, cómoda para no fallar al elegir pero sin cabecera Ethernet real; y docker0 solo tiene tráfico si hay contenedores corriendo. Si tshark -D no lista ninguna interfaz real, el grupo todavía no está activo: vuelve al aviso de arriba.

La interfaz por dentro

Un recorrido por el programa antes de empezar a capturar.

La pantalla de inicio

Al abrir Wireshark no hay ninguna captura: hay una lista de interfaces con una sparkline al lado de cada una. Esa gráfica en miniatura es tráfico en vivo, y es la forma más rápida de acertar con la interfaz: la que se mueve es la que está en uso. Doble clic sobre ella empieza a capturar.

Debajo de la lista hay un campo etiquetado «…using this filter»: ahí va el capture filter, no el de visualización. Es una distinción que confunde a todo el mundo al principio y tiene su propia sección más abajo.

La barra de herramientas

De izquierda a derecha, los controles que vas a usar de verdad:

Controles principales de la barra de herramientas
ControlQué hace
Aleta azulIniciar captura en la interfaz seleccionada.
Cuadrado rojoDetener. La captura sigue en memoria y se puede analizar y guardar.
Flecha circularReiniciar: descarta lo capturado y vuelve a empezar.
LupaBuscar dentro de los paquetes (Ctrl+F), por cadena, hex o filtro.
Flechas ← →Ir al paquete anterior/siguiente del historial de navegación.
Regla / relojPoner el tiempo a cero desde el paquete seleccionado. Imprescindible para medir intervalos.
ColoresActiva o desactiva las reglas de coloreado.

La barra de estado

La franja de abajo se ignora y no debería. De izquierda a derecha lleva:

  • Un círculo de color con el nivel máximo de Expert Information de la captura. Rojo es «error». Pulsarlo abre el diálogo directamente.
  • El fichero de captura y su tamaño.
  • Packets (capturados), Displayed (los que pasan el filtro actual, con su porcentaje) y Dropped. Vigila ese último número.
  • El perfil activo, a la derecha. Pulsar ahí cambia de perfil.

Preferences: lo que merece la pena tocar

En Edit → Preferences, tres ajustes cambian el día a día:

  • Appearance → Layout. Coloca los tres paneles. En pantallas anchas, poner Packet Details y Packet Bytes uno al lado del otro gana mucho espacio vertical.
  • Appearance → Columns. Las columnas de la lista; tiene sección propia más abajo.
  • Protocols. Un ajuste por disector. Aquí desactivarás los números de secuencia relativos de TCP y configurarás el descifrado de TLS.

Name Resolution: cómodo y peligroso a la vez

En View → Name Resolution puedes pedir que Wireshark traduzca lo que ve. Hay tres tipos y no son equivalentes:

Tipos de resolución de nombres
TipoConvierteCuidado
PhysicalMAC → fabricante (b8:1e:a4 → el OUI del fabricante)Ninguno: es una tabla local.
TransportPuerto → servicio (443 → https)Es una convención, no un hecho: un servicio puede usar cualquier puerto.
NetworkIP → nombre de dominioGenera consultas DNS desde tu equipo.

Los tres paneles

Siempre son los mismos tres, siempre significan lo mismo.

Arriba · Packet List
Una línea por paquete. No. orden de captura · Time segundos desde que empezaste · Source y Destination · Protocol el más alto que Wireshark supo reconocer · Length bytes totales · Info el resumen legible. Los colores vienen de reglas configurables: negro sobre rojo casi siempre significa problema.
Medio · Packet Details
El paquete seleccionado, desmontado en el árbol de capas de arriba. Cada rama se despliega. Aquí es donde se aprende: despliega TCP y verás los puertos, el número de secuencia, los flags, la ventana. Clic derecho sobre cualquier campo → Apply as Filter construye el filtro por ti.
Abajo · Packet Bytes
Los bytes reales en hexadecimal y ASCII. Al pinchar un campo del árbol, se resaltan sus bytes aquí. Es la prueba de que el árbol no se inventa nada: cada nombre bonito corresponde a una posición concreta.

Para empezar una captura: doble clic en wlan0 en la pantalla de inicio. La sparkline al lado de cada interfaz muestra actividad — así sabes cuál está viva antes de elegir. Para parar, el cuadrado rojo. Para descartar y volver a empezar, la escoba.

El puente entre el panel del medio y el de abajo

Esta correspondencia es el mejor ejercicio conceptual de todo Wireshark, porque demuestra que los nombres bonitos del árbol son solo una lectura de bytes concretos. Selecciona un paquete y mira dónde cae cada campo:

0x0000
b8 1e a4 5a ac 8d 2c 3a fd 11 04 e0 08 00 45 00
0x0010
00 541a 2b40 00 40017c d9 0a 02 03 aa
0x0020
01 01 01 01 08 00c9 77
Los primeros 36 bytes de un echo request. Al pinchar Time to Live en el árbol, Wireshark resalta el byte marcado: 40 hexadecimal = 64.
  • Ethernet: MAC destino, MAC origen, EtherType
  • IPv4: versión, longitud, TTL, protocolo, IP origen y destino
  • ICMP: tipo, código, identificador

Compruébalo tú: pincha Time to Live y verás un solo byte resaltado abajo; pincha Source Address y se resaltan cuatro; pincha la rama Internet Protocol Version 4 entera y se resaltan los veinte de la cabecera. El panel de bytes es la verdad; el árbol es su traducción.

El menú View → Time Display Format cambia lo que significa la columna Time: segundos desde el inicio de la captura (por defecto), hora del día, o delta respecto al paquete anterior. El delta es el que usarás para medir periodicidad.

Encapsulación: el modelo mental

Un paquete es una cebolla. Wireshark la pela.

Cuando tu navegador pide una página, ese dato no viaja solo: cada capa de la pila de red lo envuelve con su propia cabecera antes de pasarlo abajo. Lo que sale por la antena wifi es este bloque de bytes:

Ethernet14 bytes
IPv420 bytes
TCP20+ bytes
HTTP · datoslo que realmente querías
Diagrama de encapsulado: la cabecera Ethernet de 14 bytes envuelve la cabecera IPv4 de 20 bytes, que envuelve la cabecera TCP de 20 o más bytes, que envuelve los datos HTTP.
  • MAC origen y destino — el salto físico
  • IP origen y destino — la ruta global
  • Puertos, secuencia, flags — la conversación
  • El contenido

Cada capa solo sabe de la siguiente. Ethernet entrega la trama al router de al lado; IP sabe llevarla hasta el otro extremo del mundo; TCP se encarga de que llegue completa y en orden; HTTP es el idioma que hablan los dos programas. Wireshark hace una cosa: coge esos bytes y te los desmonta capa por capa, con nombres.

Y algo que conviene tener claro desde el principio: Wireshark no toca nada. No bloquea, no modifica, no inyecta. Es un microscopio, no un cortafuegos. Si algo va mal en tu red, Wireshark te dice qué está pasando, pero arreglarlo es otra herramienta.

Dónde encaja cada protocolo

El modelo OSI tiene siete capas y el de TCP/IP cuatro. Wireshark no dibuja ninguno de los dos: dibuja lo que hay realmente en la trama. Esta tabla traduce entre ambos mundos y te dice qué escribir en la barra de filtros para quedarte con cada nivel:

Correspondencia entre capas, protocolos y filtros
OSITCP/IPProtocolosFiltro
7–5 AplicaciónAplicaciónHTTP, DNS, DHCP, TLShttp · dns · dhcp · tls
4 TransporteTransporteTCP, UDPtcp · udp
3 RedInternetIPv4, IPv6, ICMPip · ipv6 · icmp
2 EnlaceAcceso a redEthernet, ARPeth · arp
1 FísicaAcceso a redCable, radioNo se captura

Dos detalles que rompen la simetría del dibujo y conviene saber: ARP no tiene cabecera IP —vive entre la capa 2 y la 3, y por eso no se puede filtrar por ip.addr—; y TLS no es una capa OSI, sino una envoltura que se coloca entre TCP y la aplicación, que es exactamente como Wireshark lo muestra en el árbol.

Filtros: la distinción que hay que interiorizar

Hay dos tipos de filtro y no se parecen en nada.

Este es el punto donde más gente se atasca. Wireshark tiene dos sistemas de filtrado distintos, con sintaxis distintas, en momentos distintos.

Capture filter — antes de capturar

Se escribe en la pantalla de inicio, debajo de la lista de interfaces. Decide qué paquetes se guardan y cuáles se tiran a la basura sin mirarlos. Usa sintaxis BPF, la misma de tcpdump: host 1.1.1.1, port 53, tcp and not port 22. Lo que descartas aquí, lo pierdes para siempre. Se usa cuando el volumen es tan alto que capturarlo todo no es viable.

Display filter — después de capturar

La barra verde ancha en la parte superior de la ventana principal. Filtra la vista; los paquetes ocultos siguen ahí y vuelven en cuanto borras el filtro. Sintaxis propia de Wireshark, mucho más rica: ip.addr == 1.1.1.1, dns, tcp.flags.syn == 1 && tcp.flags.ack == 0.

Dos detalles de sintaxis que ahorran confusión: ip.addr == X significa «origen o destino es X», mientras que ip.src e ip.dst son direccionales. Y escribir solo el nombre de un protocolo (dns, tls, arp) filtra todos los paquetes que lo contienen — es el filtro más útil y más corto que existe.

Comparación lado a lado

Capture filter frente a display filter
Capture filterDisplay filter
CuándoAntes de capturarSobre lo ya capturado
DóndePantalla de inicio, bajo las interfacesBarra ancha superior
SintaxisBPF, la de tcpdumpPropia de Wireshark
ReversibleNo: lo descartado se pierdeSí: borras el filtro y vuelve todo
CamposPocos, de bajo nivelMás de 300 000 campos
Igualdadhost 10.2.3.1ip.addr == 10.2.3.1
Puertoport 53tcp.port == 53 || udp.port == 53
Negaciónnot arp!arp
Conjuncióntcp and port 443tcp && tcp.port == 443
Para quéContener el volumen en enlaces cargadosInvestigar

El lenguaje de los display filters

Construir un filtro por capas en lugar de memorizarlo.

Un display filter es una expresión que se evalúa contra cada paquete: si da verdadero, el paquete se muestra. Hay tres formas de construirla, de menor a mayor precisión.

Nivel 1 · Solo el nombre del protocolo

Escribir el nombre de un protocolo es un filtro completo: significa «este paquete contiene ese protocolo en alguna capa».

Displaydns

Nivel 2 · Un campo comparado con un valor

La forma campo operador valor. Los operadores de comparación:

Operadores de comparación
OperadorAliasSignificadoEjemplo
==eqIgualip.src == 10.2.3.170
!=neDistintotcp.dstport != 443
>gtMayor queframe.len > 1400
<ltMenor queip.ttl < 10
>=geMayor o igualhttp.response.code >= 400
<=leMenor o igualtcp.window_size_value <= 1000

Nivel 3 · Combinar condiciones

Operadores lógicos
OperadorAliasSignificado
&&andSe cumplen las dos condiciones
||orSe cumple al menos una
!notNiega la condición

Operadores de contenido

Operadores de contenido y pertenencia
OperadorQué haceEjemplo
containsBusca una secuencia de bytes o texto dentro del campo. Distingue mayúsculas.dns.qry.name contains "example"
matchesExpresión regular PCRE. Antepón (?i) para ignorar mayúsculas.http.host matches "(?i)cdn"
inPertenencia a un conjunto. Los elementos van separados por comas.tcp.port in {80, 443, 8080}
bash
$ dftest 'tcp.port in {80, 443, 8080}'   # válido
$ dftest 'tcp.port in {80 443 8080}'     # error de sintaxis

Otro conjunto útil es el rango, con dos puntos suspensivos: ip.ttl in {1 .. 5} selecciona los TTL del 1 al 5, que es lo que verías en un traceroute.

Construir un filtro por capas

No escribas el filtro completo de una vez. Empieza ancho y ve estrechando, mirando cuántos paquetes quedan en Displayed después de cada paso:

  1. Todo lo que tenga que ver con ese equipo: ip.addr == 10.2.3.170
  2. Solo lo que sale de él: ip.src == 10.2.3.170
  3. Solo TCP: ip.src == 10.2.3.170 && tcp
  4. Solo HTTPS: ip.src == 10.2.3.170 && tcp.port == 443
  5. Solo aperturas de conexión: ip.src == 10.2.3.170 && tcp.flags.syn == 1 && tcp.flags.ack == 0

Si en un paso el resultado se queda vacío, sabes exactamente qué condición lo vació. Depurar un filtro de cinco condiciones escrito de golpe es mucho más difícil.

El atajo que hace innecesario memorizar campos

Nadie recuerda que el nombre del servidor en TLS es tls.handshake.extensions_server_name. No hace falta: clic derecho sobre el campo en el árbol → Apply as Filter → Selected. Wireshark escribe el filtro correcto en la barra. Así es como se aprenden los nombres de los campos — trabajando, no estudiando una lista.

Variantes del mismo menú que conviene conocer:

  • Prepare as Filter escribe el filtro en la barra pero no lo aplica: sirve para seguir editándolo antes de pulsar Intro.
  • …and Selected / …or Selected añade la condición al filtro que ya tenías, en vez de sustituirlo.
  • …not Selected lo añade negado. Es la forma rápida de ir quitando ruido: aplica, ves lo que sobra, lo excluyes, repites.

Y el botón + al final de la barra guarda el filtro actual como botón con nombre. Si repites un filtro cada día, déjalo ahí.

Parte 02Protocolos

Protocolos

Capa por capa, de la MAC al TLS: qué campos importan, cómo se filtran y qué revelan.

Ethernet

La capa 2: catorce bytes que deciden el siguiente salto.

Qué es. Ethernet mueve tramas entre dos equipos del mismo segmento de red. No sabe nada de internet ni de rutas: solo «entrega esto a la tarjeta cuya dirección física es esta».

Cómo funciona. Su cabecera son 14 bytes con tres campos:

MAC destino6 bytes
MAC origen6 bytes
EtherType2 bytes
Cabecera Ethernet II. Después viene directamente el paquete de la capa superior.

Una dirección MAC son 6 bytes, escritos como b8:1e:a4:5a:ac:8d. Los tres primeros son el OUI, el identificador del fabricante: Wireshark lo traduce solo, y por eso en la columna a veces ves IntelCor_5a:ac:8d en lugar del hexadecimal. Es información real y gratuita: te dice qué clase de dispositivo hay detrás de una MAC.

El EtherType dice qué viene después. Los tres que verás:

Valores de EtherType habituales
ValorContenidoFiltro
0x0800IPv4eth.type == 0x0800
0x0806ARPeth.type == 0x0806
0x86ddIPv6eth.type == 0x86dd

Unicast, broadcast y multicast

La MAC de destino determina quién recoge la trama, y el bit menos significativo del primer byte lo decide:

Tipos de destino Ethernet
TipoDestinoQuién la recibe
UnicastUna MAC concretaUn solo equipo. Es la inmensa mayoría del tráfico.
Broadcastff:ff:ff:ff:ff:ffTodos los equipos del segmento. ARP y DHCP lo usan.
MulticastPrimer byte impar (p. ej. 01:00:5e:…)Los que se han suscrito a ese grupo. mDNS, SSDP, IPv6.

Cómo lo veo en Wireshark

Despliega la rama Ethernet II del panel del medio. Dentro de Destination hay dos subcampos que Wireshark calcula por ti: LG bit (dirección local o global) e IG bit (individual o de grupo). Ese IG bit a 1 es precisamente la definición de multicast/broadcast.

Filtros

Displayeth.addr == b8:1e:a4:5a:ac:8d

Todo lo que sale o entra en esa tarjeta. Útil cuando investigas un equipo cuya IP cambia (DHCP) pero cuya MAC no.

Displayeth.src == b8:1e:a4:5a:ac:8d

Solo lo que ese equipo emite. Con eth.dst, solo lo que recibe.

Displayeth.dst == ff:ff:ff:ff:ff:ff

Todo el broadcast del segmento: ARP, DHCP, anuncios de servicios. Es un buen primer vistazo a «quién hay» en una red desconocida, porque los equipos se anuncian solos.

Displayeth.ig == 1

Broadcast y multicast a la vez. Si el tráfico de grupo se dispara sin motivo, aquí se ve.

Error común. Buscar la MAC de un servidor de internet en la captura. Nunca aparecerá: solo ves las MAC de tu propio segmento.

ARP

Cómo encuentra tu equipo al router — y por qué es el protocolo más fácil de abusar.

Objetivo: ver la capa 2 en acción, por debajo de IP.

En el apartado anterior tu equipo puso la MAC del router en la trama. ¿Cómo la sabía? La preguntó a gritos. Filtra:

Displayarp

Fuerza uno borrando la entrada de la tabla y volviendo a hablar con el router:

bash
$ sudo ip neigh flush all
$ ping -c 2 10.2.3.1

Verás el par clásico. El primero va a destino ff:ff:ff:ff:ff:ff — broadcast, lo recibe toda la red local — y su Info dice Who has 10.2.3.1? Tell 10.2.3.170. El segundo es la respuesta directa: 10.2.3.1 is at ....

ARP no tiene cabecera IP. Es capa 2 pura: solo funciona dentro de tu red local, y por eso no hay ARP para 1.1.1.1 — para salir de la red, todo va al router y él se encarga.

Los dos mensajes, y cómo separarlos

El campo arp.opcode distingue la pregunta de la respuesta:

Displayarp.opcode == 1

Request. Va en broadcast porque el emisor todavía no sabe a quién preguntar. El campo «Target MAC address» va a ceros: es justo lo que está preguntando.

Displayarp.opcode == 2

Reply. Va en unicast, directo al que preguntó. Lleva la MAC en arp.src.hw_mac.

La caché ARP

El resultado se guarda unos minutos para no preguntar cada vez. Puedes verla:

bash
$ ip neigh
10.2.3.1 dev wlan0 lladdr 2c:3a:fd:11:04:e0 REACHABLE

Esa tabla es la que un atacante intenta envenenar, y por eso ARP importa en seguridad.

Ciberseguridad: reconocer ARP anómalo

ARP se diseñó en 1982 sin ninguna autenticación: cualquier equipo puede responder a cualquier pregunta, y el que pregunta se cree la respuesta. Un atacante en el mismo segmento puede afirmar «10.2.3.1 soy yo» y hacer que tu tráfico pase por su máquina. Eso se llama ARP spoofing o poisoning.

No vas a aprender a hacerlo aquí. Vas a aprender qué rastro deja, que es lo que te sirve como defensor:

  • Dos MAC distintas afirmando ser la misma IP. Es la señal más directa. En una red sana, cada IP tiene una sola MAC.
  • Replies sin request previo (ARP «gratuito» en exceso). Uno ocasional es normal —los equipos lo usan al arrancar para anunciarse—; un goteo constante hacia un mismo objetivo, no.
  • La MAC del gateway cambia a mitad de la captura. El gateway es el objetivo preferido porque por él pasa todo.
  • Frecuencia anormal. El envenenamiento hay que refrescarlo antes de que caduque la caché legítima, así que suele verse un ritmo regular.

Wireshark trae un detector para el primer caso, y es el filtro que deberías conocer:

Displayarp.duplicate-address-detected

Marca los paquetes donde el disector ha visto que una IP cambia de MAC. Junto a él, arp.duplicate-address-frame apunta al número de trama del conflicto anterior, para poder comparar los dos.

Práctica. Aplica arp a una captura de diez minutos de tu red y abre Statistics → Endpoints → Ethernet. Anota qué MAC corresponde a tu gateway. Esa es tu línea base: si otro día no coincide, tienes algo que investigar.

IPv4

Veinte bytes que llevan un paquete de un extremo del mundo al otro.

Qué es. IP es el protocolo que sabe llegar a cualquier destino de internet. Es no fiable a propósito: no garantiza entrega, ni orden, ni ausencia de duplicados. Todo eso lo pone TCP encima. IP solo se ocupa de direccionar y de que el paquete no dé vueltas para siempre.

La cabecera, campo a campo

Este es el diagrama que conviene tener en la cabeza. Cada fila son 32 bits (4 bytes); la cabecera mínima son cinco filas, 20 bytes:

Version4 bits
IHL4 bits
DSCP6 bits
ECN2
Total Length16 bits
Identification16 bits
Flags3
Fragment Offset13 bits
TTL8 bits
Protocol8 bits
Header Checksum16 bits
Source Address32 bits · 4 bytes
Destination Address32 bits · 4 bytes
Cabecera IPv4. Las opciones, si existen, van después; por eso hace falta el campo IHL.
Campos de la cabecera IPv4 y su significado
CampoQué significaFiltro
VersionSiempre 4 aquí. Es lo que distingue IPv4 de IPv6 al empezar a leer.ip.version
IHLLongitud de la cabecera en palabras de 4 bytes. Vale 5 (=20 bytes) salvo que haya opciones. Wireshark ya lo muestra en bytes.ip.hdr_len
DSCPMarca de calidad de servicio. Voz y vídeo la usan para pedir prioridad; el resto va a 0.ip.dsfield.dscp
ECNNotificación de congestión. Permite avisar de congestión sin descartar el paquete.ip.dsfield.ecn
Total LengthCabecera IP + contenido, en bytes. No incluye Ethernet: por eso es 14 menos que frame.len.ip.len
IdentificationIdentificador del datagrama original. Todos los fragmentos de un mismo paquete lo comparten: así se reensambla.ip.id
FlagsTres bits. DF (no fragmentar) y MF (vienen más fragmentos).ip.flags
Fragment OffsetPosición de este fragmento dentro del original, en unidades de 8 bytes.ip.frag_offset
TTLCada router lo decrementa en 1. Al llegar a 0 el paquete se descarta y se devuelve un ICMP. Evita bucles infinitos.ip.ttl
ProtocolQué viene después: 1=ICMP, 6=TCP, 17=UDP.ip.proto
Header ChecksumSuma de verificación de la cabecera. Se recalcula en cada salto porque el TTL cambia.ip.checksum
Source / DestinationLas direcciones. Sobreviven todo el trayecto, a diferencia de las MAC.ip.src · ip.dst

El TTL cuenta una historia

Este es el campo que más información gratuita da. Los sistemas operativos parten de valores conocidos: Linux y macOS de 64, Windows de 128, muchos routers de 255. Como cada salto resta 1, la distancia al origen es la diferencia.

Haz un ping a 1.1.1.1 y compara: el request sale con ttl=64 y la respuesta llega con ttl=51. Como 64 − 51 = 13, esa respuesta atravesó 13 routers para llegar a ti. Y como el valor de partida era 64, el equipo del otro lado es casi seguro un Linux.

Displayip.ttl < 20

Paquetes que han recorrido muchos saltos. En una captura de red local no debería aparecer casi nada; si tu tráfico interno tiene TTL bajo, algo lo está enrutando de más.

Fragmentación

Si un paquete no cabe en el MTU de un enlace (típicamente 1500 bytes), se parte. Los fragmentos comparten ip.id, todos menos el último llevan el bit MF a 1, y cada uno indica su posición en ip.frag_offset.

Displayip.flags.mf == 1 || ip.frag_offset > 0

Ese filtro muestra todos los fragmentos. En una red bien dimensionada la fragmentación IPv4 es rara: si aparece mucha, suele haber un problema de MTU (una VPN, un túnel) que además degrada el rendimiento. Wireshark reensambla los fragmentos y te muestra el paquete completo en el último, indicando de qué tramas lo ha compuesto.

Filtros de dirección: la diferencia que hay que tener clara

Displayip.addr == 10.2.3.170

Origen o destino. Es «todo lo que tenga que ver con este equipo».

Displayip.src == 10.2.3.170

Solo lo que sale. ip.dst para lo que entra.

Displayip.addr == 10.2.3.0/24

Una red entera en notación CIDR. Combinado con una negación, aísla el tráfico que sale de tu red — que es justo lo que interesa mirar en un análisis de exfiltración:

Displayip.src == 10.2.3.0/24 && !(ip.dst == 10.2.3.0/24)

Práctica. Captura treinta segundos de navegación normal y aplica ip.ttl < 64 && ip.ttl > 40. Ordena por la columna Source. Los grupos de TTL iguales son grupos de servidores a la misma distancia de ti.

IPv6

Está en tu captura aunque no lo hayas configurado.

Abre una captura cualquiera y filtra por ipv6: casi seguro que hay tráfico. Los sistemas modernos lo traen activado y prefieren IPv6 cuando hay ambos disponibles. Merece la pena reconocerlo aunque no lo administres.

Lo que cambia respecto a IPv4:

Diferencias entre IPv4 e IPv6
IPv4IPv6
Dirección32 bits · 10.2.3.170128 bits · fe80::b81e:a4ff:fe5a:ac8d
Cabecera20 bytes variables40 bytes fijos, más simple
ChecksumNo: lo hacen las capas de arriba
FragmentaCualquier routerSolo el origen
Equivale a TTLip.ttlipv6.hlim (hop limit)
Siguiente capaip.protoipv6.nxt
ARPARPNDP, dentro de ICMPv6
BroadcastExisteNo existe: solo multicast

Las direcciones que empiezan por fe80:: son link-local: se autoconfiguran solas, solo valen dentro del segmento y no salen a internet. Son las que más verás en una captura doméstica.

Displayipv6
Displayipv6.addr == fe80::1
Displayicmpv6

Ese último es importante: en IPv6, el descubrimiento de vecinos (el equivalente a ARP), el anuncio de routers y la autoconfiguración van todos dentro de ICMPv6. Si filtras icmpv6 en tu red verás los Router Advertisement y los Neighbor Solicitation que hacen ese trabajo.

ICMP

El protocolo más simple que hay — y por eso el mejor para aprender a leer el árbol.

Objetivo: leer el árbol de capas de un paquete que entiendes entero.

Empieza la captura en wlan0. Verás una avalancha de tráfico de fondo — es normal, tu equipo habla solo todo el rato. Pega este filtro en la barra verde para quedarte solo con lo tuyo:

Displayicmp

La lista se queda vacía. Ahora, en la terminal:

bash
$ ping -c 4 1.1.1.1

Aparecen ocho paquetes: cuatro Echo (ping) request y cuatro Echo (ping) reply, alternados. Selecciona el primer request y despliega el árbol del panel del medio. Vas a ver exactamente las tres capas del diagrama de arriba:

  • Ethernet II — origen b8:1e:a4:5a:ac:8d (tu tarjeta wifi) y destino la MAC de tu router. Fíjate: la MAC destino no es la de Cloudflare. Es la del siguiente salto.
  • Internet Protocol Version 4 — origen 10.2.3.170, destino 1.1.1.1. Aquí sí está el destino final. Despliega y busca Time to Live: es el contador de saltos que evita que un paquete perdido dé vueltas para siempre.
  • Internet Control Message Protocol — tipo 8 (request). En la respuesta será tipo 0 (reply). Al final hay un campo Data con bytes de relleno.

Pincha el campo TTL en el árbol y mira el panel de abajo: se resalta un byte. Ese byte es el TTL. No hay magia.

Emparejar request y reply

Un ping son pares. Despliega el árbol ICMP y verás dos campos que los enlazan:

  • Identifier — igual en toda la serie. Identifica esta ejecución de ping, para que dos pings simultáneos no se mezclen.
  • Sequence Number — incrementa 1, 2, 3, 4. Identifica cada envío.

Wireshark hace el emparejamiento por ti: en la respuesta verás una línea [Request In: 1], y en el request un [Response In: 2]. Y en la respuesta añade [Response Time: …ms], que es la latencia real medida sobre el paquete, no la que estima ping.

Displayicmp.ident == 0xc977

Aísla una ejecución concreta de ping cuando hay varias mezcladas.

Los tipos que vas a encontrar

Tipos de mensaje ICMP habituales
TipoNombreQué significa
8Echo Request«¿Estás ahí?» — lo que envía ping.
0Echo Reply«Sí». Ojo al orden contraintuitivo: la respuesta es el tipo 0.
3Destination UnreachableNo hay camino. El code dice por qué: 0 red, 1 host, 3 puerto, 13 prohibido administrativamente (un cortafuegos).
11Time ExceededEl TTL llegó a 0. Es lo que hace funcionar a traceroute.
5Redirect«Usa mejor este otro router». Poco frecuente y a menudo indeseado.
Displayicmp.type == 8
Displayicmp.type == 3 && icmp.code == 13

Ese segundo es muy útil al diagnosticar: significa que un cortafuegos está bloqueando y avisando. Si no llega nada en absoluto, el cortafuegos descarta en silencio, que es lo habitual.

Ciberseguridad: qué mirar en ICMP

ICMP es una herramienta de diagnóstico legítima y necesaria. Bloquearlo entero es un error clásico que rompe el descubrimiento de MTU. Pero hay patrones que merecen mirada:

  • Barrido (ping sweep). Un origen envía echo request a muchas IP consecutivas del rango en poco tiempo. La señal es la forma: un origen, muchos destinos, secuencial, sin respuestas para la mayoría.
  • Volumen desproporcionado. ICMP debería ser una fracción mínima del tráfico. Compruébalo en Statistics → Protocol Hierarchy: si ICMP es un porcentaje llamativo, pregúntate por qué.
  • Payload grande o con contenido. El campo Data de un ping normal es relleno predecible. Paquetes ICMP con cargas grandes y variables, de forma sostenida y bidireccional, son el patrón de un túnel sobre ICMP.
  • Periodicidad. Echo requests cada N segundos exactos hacia un destino externo fijo.
Displayicmp && data.len > 64

TCP

La sección más larga, porque es el protocolo del que más se diagnostica.

Objetivo: entender cómo TCP abre una conexión — el concepto central del protocolo.

Qué es. TCP convierte el servicio no fiable de IP en un flujo de bytes ordenado y sin pérdidas. Para conseguirlo numera cada byte, confirma lo recibido, retransmite lo que falta y controla el ritmo para no ahogar al receptor ni a la red. Todo eso deja rastro en la cabecera, y ese rastro es lo que lees en Wireshark.

Puertos: cómo se identifica una conversación

Una conexión TCP se identifica por cuatro valores: IP origen, puerto origen, IP destino, puerto destino. Esa tupla es única, y es lo que permite a tu navegador tener veinte conexiones al mismo servidor a la vez: cambia el puerto origen.

El puerto de destino identifica el servicio (443 = HTTPS); el de origen lo elige el sistema al azar en el rango alto (32768–60999 en Linux) y se llama puerto efímero. Por eso, en una captura, el lado con puerto alto es casi siempre el cliente.

El handshake de tres vías

Antes de que se envíe un solo byte útil, los dos extremos se sincronizan con tres paquetes:

10.2.3.170 servidor:80 SYN Seq=0 · «quiero hablar» SYN, ACK Seq=0 Ack=1 · «vale, y yo también» ACK Ack=1 · conexión abierta
Tres paquetes, cero bytes de datos. Después ya se puede hablar.

Vamos a verlo. Este filtro aísla exactamente los paquetes de apertura — SYN activo y ACK apagado, que solo ocurre en el primer paquete de cada conexión nueva:

Displaytcp.flags.syn == 1 && tcp.flags.ack == 0
bash
$ curl -s -o /dev/null http://neverssl.com

Aparece un SYN. Ahora quita el filtro y en su lugar haz clic derecho sobre ese paquete → Conversation Filter → TCP. Wireshark escribe solo un filtro con las dos IPs y los dos puertos, y te deja la conversación completa: los tres paquetes del handshake, la petición HTTP, la respuesta, y el cierre con FIN.

En el árbol de cada paquete despliega Flags dentro de TCP. Los bits que importan:

Flags de TCP y su significado
FlagSignifica
SYNAbriendo conexión, sincroniza números de secuencia
ACKConfirmo lo que me has mandado hasta el byte N
PSHEntrega estos datos a la aplicación ya, no esperes
FINHe terminado de enviar, cierre ordenado
RSTCorte abrupto. Casi siempre señal de problema

Sequence y Acknowledgement, sin misterio

Estos dos números confunden hasta que se entiende que cuentan bytes, no paquetes:

  • tcp.seq — el número del primer byte de datos que va en este segmento.
  • tcp.ack — el número del siguiente byte que espero recibir. Es decir: «tengo todo hasta el byte ack−1».
  • tcp.len — cuántos bytes de datos lleva este segmento. Los ACK puros llevan 0.

La aritmética es siempre la misma: si recibo un segmento con seq=1 y len=500, responderé con ack=501. Con números relativos esto se lee de un vistazo.

SYN y FIN consumen un número de secuencia aunque no lleven datos. Por eso el ack=1 del handshake, cuando no se había enviado ningún byte: el 0 lo gastó el SYN.

Window size: el control de flujo

tcp.window_size_value es lo que el emisor anuncia; tcp.window_size es ese valor ya multiplicado por el factor de escala que se negoció en el handshake. Wireshark calcula el segundo por ti, y es el que debes mirar.

Significa «tengo sitio para tantos bytes más sin confirmar». Si baja mucho, el receptor no da abasto procesando. Si llega a cero, se para todo:

Displaytcp.analysis.zero_window

Ventana cero es un hallazgo de primera categoría cuando alguien reporta lentitud: el problema no está en la red, está en el equipo que anuncia el cero, que no lee su buffer lo bastante rápido.

Cerrar la conexión

Hay dos formas, y distinguirlas importa:

Formas de cerrar una conexión TCP
CierreSecuenciaQué significa
Ordenado (FIN)FIN → ACK → FIN → ACKCada lado dice que terminó de enviar. Es lo normal y garantiza que no se pierden datos en vuelo.
Abrupto (RST)RST«Se acabó, ya». Descarta lo que hubiera pendiente.
Displaytcp.flags.fin == 1
Displaytcp.flags.reset == 1

El motor de análisis de Wireshark

Wireshark no solo muestra los campos: sigue el estado de cada conexión y marca lo que no cuadra. Esos son los campos tcp.analysis.*, y son la herramienta de diagnóstico más potente del programa.

Campos de análisis TCP y cómo interpretarlos
FiltroQué detectóCómo interpretarlo
tcp.analysis.retransmissionDatos ya enviados vuelven a enviarseAlgo se perdió por el camino, o el ACK no llegó a tiempo.
tcp.analysis.fast_retransmissionRetransmisión disparada por ACK duplicados, sin esperar al temporizadorPérdida detectada rápido. Es el mecanismo funcionando bien.
tcp.analysis.duplicate_ackEl receptor repite el mismo ACK«Me falta un trozo». Tres seguidos disparan la retransmisión rápida.
tcp.analysis.out_of_orderUn segmento llegó antes que otro anteriorSuele ser reordenación de la red, no pérdida. No es grave por sí solo.
tcp.analysis.lost_segmentHay un hueco en la numeraciónOjo: puede significar que se perdió, o solo que no lo capturaste.
tcp.analysis.zero_windowVentana anunciada a 0El receptor está saturado. Problema de aplicación, no de red.
tcp.analysis.flagsCualquiera de las anterioresEl filtro de barrido: empieza siempre por aquí.
Displaytcp.analysis.flags

Muestra solo los paquetes que Wireshark ha marcado como problemáticos. En una red sana, apenas aparece nada.

Navegar por una conexión

tcp.stream es un número que Wireshark asigna a cada conexión de la captura, empezando en 0. Es la forma más rápida de moverse:

Displaytcp.stream eq 3

Y tcp.time_delta es el tiempo desde el paquete anterior de la misma conexión — mucho más útil que el delta global cuando hay tráfico mezclado. Para usarlo hay que activarlo en Edit → Preferences → Protocols → TCP → «Calculate conversation timestamps».

Displaytcp.time_delta > 1

Paquetes que llegaron más de un segundo después del anterior de su conexión. Es la forma de encontrar dónde exactamente se quedó parada una transferencia lenta.

Práctica. Captura un curl a cualquier web, aplica tcp.flags.syn == 1 && tcp.flags.ack == 0 para localizar la apertura, anota el número de tcp.stream, y filtra por él. Sigue la conversación entera contando los paquetes: tres de handshake, la petición, la respuesta, el cierre. Si sabes explicar cada paquete de esa lista, entiendes TCP.

UDP

Ocho bytes de cabecera y ninguna promesa.

Qué es. UDP es la alternativa mínima a TCP: pone puertos sobre IP y poco más. No hay conexión, ni confirmación, ni orden, ni retransmisión. Si un datagrama se pierde, se pierde y nadie se entera — salvo la aplicación, si le importa.

Eso, que suena a defecto, es exactamente lo que quieren DNS (una pregunta, una respuesta: montar una conexión costaría más que reintentar), el vídeo en tiempo real (un fotograma retransmitido llega tarde y ya no sirve) y DHCP (todavía no tienes ni IP).

Source Port16 bits
Destination Port16 bits
Length16 bits
Checksum16 bits
Cabecera UDP completa: 8 bytes. La de TCP son 20 como mínimo.
  • udp.srcport / udp.dstport — igual que en TCP.
  • udp.length — cabecera más datos. Como la cabecera son 8, el contenido es udp.length − 8.
  • udp.checksum — opcional en IPv4, obligatorio en IPv6.

TCP frente a UDP, de un vistazo

Comparación entre TCP y UDP
TCPUDP
ConexiónHandshake de 3 víasNinguna: se envía y ya
Cabecera20 bytes mínimo8 bytes fijos
EntregaGarantizada y en ordenSin garantía
RetransmiteSí, automáticamenteNo: si acaso, la aplicación
Control de flujoSí (window)No
En WiresharkEstado por conexión, tcp.analysis.*, Follow StreamSin estado: cada datagrama es independiente
Se usa enHTTP, HTTPS, SSH, correoDNS, DHCP, NTP, QUIC, voz y vídeo
Displayudp
Displayudp.port == 53
Displayudp.length > 512

DNS

Nombres a números — y el protocolo que más cuenta sobre lo que hace un equipo.

Objetivo: emparejar consulta y respuesta, y ver el primer protocolo de aplicación.

Displaydns
bash
$ dig +short archlinux.org

Dos paquetes: Standard query y Standard query response. Despliega la consulta y fíjate en el Transaction ID — un número aleatorio de 16 bits. Ahora mira la respuesta: tiene el mismo ID. Así se emparejan; DNS va normalmente sobre UDP, que no tiene conexión, así que la correspondencia hay que llevarla en el propio mensaje.

Dentro de la respuesta, despliega Answers: ahí están las direcciones IP reales. Y observa el campo Time que Wireshark añade a la respuesta — te dice cuánto tardó tu resolver. Eso convierte a Wireshark en una herramienta de diagnóstico: un DNS lento se ve aquí de un vistazo.

Tipos de registro

El campo dns.qry.type dice qué se pregunta. Los que verás:

Tipos de registro DNS
TipoDevuelveNota para el analista
A1Una IPv4El caso normal.
AAAA28Una IPv6Los navegadores piden A y AAAA a la vez.
CNAME5Un alias hacia otro nombreEncadena: el nombre real puede estar a varios saltos.
MX15Servidor de correoUn equipo de escritorio no debería consultarlos a menudo.
TXT16Texto libreLegítimo (SPF, verificaciones) pero es el registro preferido para sacar datos por DNS.
PTR12IP → nombre (inverso)También lo usa mDNS para descubrir servicios en la red local.
NS2Servidor autoritativo del dominioFrecuente en resolvers, raro en clientes.
Displaydns.qry.type == 16
Displaydns.flags.response == 0

Solo las preguntas. Con == 1, solo las respuestas.

Displaydns.qry.name contains "archlinux"
Displaydns.time > 0.5

Resoluciones que tardaron más de medio segundo: el diagnóstico directo de «internet va lento» cuando la culpa es del DNS.

Cuando la respuesta es «no existe»

El código de respuesta va en dns.flags.rcode. El valor 0 es éxito; el 3 es NXDOMAIN, «ese nombre no existe».

Displaydns.flags.rcode == 3

Algún NXDOMAIN suelto es normal: una errata al teclear, un dominio de búsqueda mal configurado. Un volumen alto y sostenido, no — y ahí empieza el interés defensivo.

Ciberseguridad: DNS es donde primero se ve casi todo

Aunque el contenido esté cifrado, el nombre que se resuelve casi nunca lo está. Por eso DNS es el registro más valioso en una investigación: te dice a dónde intentó ir un equipo, incluso si la conexión luego falló. Estos son los patrones que se miran, con lo que de verdad significa cada uno:

Indicadores DNS y su interpretación
IndicadorPor qué llama la atenciónExplicación benigna frecuente
Muchos NXDOMAIN distintosUn algoritmo que genera dominios va probando hasta acertar con el que está registradoSufijos de búsqueda mal configurados; un cliente de correo reintentando; antivirus con listas de reputación
Subdominios muy largos y aleatoriosLos datos se codifican en el propio nombre para sacarlos por DNSCDN, antivirus en la nube y servicios de reputación usan nombres largos generados
Consultas a intervalos exactosUn implante consultando a su servidor de controlSincronización horaria, actualizaciones, telemetría, sondas de monitorización
Volumen alto de TXTTXT admite más datos por respuesta que AValidación de dominios, SPF/DKIM en servidores de correo
Resolver distinto del habitualUn equipo salta el DNS corporativo y su registroDoH del navegador activado por defecto; VPN; un móvil con su propia configuración

Filtros para explorar cada uno:

Displaydns.flags.rcode == 3 && dns.flags.response == 1
Displaydns.qry.name.len > 50
Displaydns && !(ip.dst == 10.2.3.1)

Ese último saca las consultas DNS que no van a tu resolver habitual. Sustituye la IP por la de tu red.

Práctica. Abre Statistics → DNS sobre una captura de navegación normal. Mira el reparto por tipo de consulta y el de códigos de respuesta. Esa distribución es tu línea base de DNS: cuando algo se salga de ella, lo notarás.

DHCP

Cómo un equipo consigue una IP cuando todavía no tiene ninguna.

El problema. Un equipo que acaba de arrancar no tiene dirección IP, así que no puede enviar un paquete dirigido a nadie. La solución es hablar en broadcast: origen 0.0.0.0, destino 255.255.255.255, y que conteste quien sepa.

DORA: los cuatro mensajes

  1. DDiscoverCliente → broadcast. «¿Hay algún servidor DHCP?»
  2. OOfferServidor → cliente. «Te ofrezco 10.2.3.170»
  3. RRequestCliente → broadcast. «Acepto esa». Va en broadcast para que los demás servidores retiren su oferta.
  4. AAcknowledgeServidor → cliente. «Confirmado, y aquí van máscara, gateway y DNS»
El intercambio DORA. Renovar una concesión ya existente usa solo Request y ACK.
Displaydhcp

Para provocar un intercambio completo, renueva la concesión mientras capturas. En un sistema con NetworkManager basta con desconectar y reconectar la interfaz.

El tipo de mensaje va en la opción 53:

Displaydhcp.option.dhcp == 1

Discover. Los valores son 1=Discover, 2=Offer, 3=Request, 5=ACK, 6=NAK, 7=Release.

Qué mirar en un paquete DHCP

  • dhcp.hw.mac_addr — la MAC del cliente. Es lo que identifica al equipo en todo el intercambio.
  • dhcp.option.hostnameel nombre que el equipo se da a sí mismo. En una red desconocida, filtrar DHCP y leer esta opción es la forma más rápida de saber qué dispositivos hay: los nombres suelen delatar el modelo y el dueño.
  • dhcp.option.requested_ip_address — la IP que pide, normalmente la que tenía antes.
  • En el ACK, las opciones de router (gateway) y Domain Name Server: la configuración de red completa que va a usar el equipo.
Displaydhcp.option.hostname

Ciberseguridad: dos cosas que mirar

  • Servidor DHCP inesperado. Si en tus capturas aparecen Offers desde una IP o una MAC que no es la de tu router, hay un segundo servidor DHCP en la red. Casi siempre es un accidente —alguien enchufó un router doméstico por el puerto equivocado—, pero un DHCP falso puede repartir un gateway y un DNS controlados por un tercero, y eso redirige todo el tráfico del que le haga caso.
  • Inventario. DHCP es el mejor censo de una red: cada dispositivo que se conecta pasa por aquí, con su MAC y su nombre. Guarda esa lista; es la base para detectar el día que aparezca uno que no reconoces.

Práctica. Captura mientras reconectas la wifi, filtra dhcp y localiza los cuatro mensajes. En el ACK, despliega las opciones y anota gateway y DNS: compáralos con lo que devuelven ip route y resolvectl status. Deben coincidir; si no coinciden, algo ha cambiado tu configuración después.

HTTP

Texto plano: todo lo que se ve, se ve porque nadie lo cifró.

HTTP es una conversación en texto sobre TCP. El cliente manda una petición, el servidor una respuesta, y ambas tienen la misma forma: una línea inicial, unas cabeceras, una línea en blanco y un cuerpo opcional.

Displayhttp
bash
$ curl -s -o /dev/null http://neverssl.com

La petición

petición http
GET / HTTP/1.1
Host: neverssl.com
User-Agent: curl/8.x
Accept: */*
  • MétodoGET pide, POST envía datos en el cuerpo, HEAD pide solo las cabeceras, PUT y DELETE modifican recursos.
  • Host — obligatorio en HTTP/1.1. Permite alojar muchos sitios en una IP, y es el campo que te dice a qué sitio se pedía realmente.
  • User-Agent — quién dice ser el cliente. Es texto libre y se puede poner cualquier cosa, pero delata la herramienta.

La respuesta

respuesta http
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1256
...
Familias de códigos de estado HTTP
RangoFamiliaEjemplos
2xxÉxito200 OK · 204 sin contenido
3xxRedirección301 permanente · 302 temporal · 304 no modificado
4xxError del cliente401 no autenticado · 403 prohibido · 404 no existe
5xxError del servidor500 interno · 502 puerta de enlace · 503 no disponible
Displayhttp.request
Displayhttp.request.method == "GET"
Displayhttp.response.code >= 400
Displayhttp.host contains "example"
Displayhttp.user_agent

Extraer los ficheros que viajaron

File → Export Objects → HTTP lista todos los objetos que pasaron por la captura —páginas, imágenes, scripts, descargas— con su host, tamaño y tipo, y te los reconstruye en disco. En una investigación es la forma de recuperar exactamente qué se descargó.

Ciberseguridad: por qué HTTP sin cifrar es un problema

Con HTTP, cualquiera que esté en el camino ve la petición completa: la URL, las cabeceras, las cookies de sesión y el cuerpo del POST. No hace falta ninguna herramienta especial ni ningún ataque: está ahí, en claro, y Wireshark simplemente lo muestra.

Cosas concretas que quedan expuestas y por qué importan:

  • La URL completa, incluidos parámetros. Si una aplicación pasa un identificador de sesión o un token en la query string, viaja visible.
  • Las cookies (http.cookie). Una cookie de sesión interceptada equivale a la sesión: por eso existe la marca Secure.
  • El cuerpo de un POST (http.file_data): el formulario tal cual se envió.
  • La cabecera Authorization (http.authorization). En autenticación básica es el usuario y la contraseña, solo codificados en Base64 — que no es cifrado, es una forma de escribirlos.
Displayhttp.authorization
Displayhttp.request.method == "POST" && http.content_type contains "form"

Indicadores de tráfico HTTP que merece revisar:

  • User-Agent llamativo: vacío, muy corto, con errores de escritura, o de una herramienta que nadie debería estar usando en ese equipo. Recuerda que es texto libre: un agente que dice ser un navegador puede no serlo, y uno raro puede ser un dispositivo legítimo mal programado.
  • Peticiones a una IP en vez de a un nombre. Un navegador humano llega casi siempre por DNS; una petición a http://203.0.113.9/algo sin consulta DNS previa es, como mínimo, distinta del resto.
  • Métodos poco habituales en un cliente de escritorio: PUT, DELETE, o un CONNECT hacia un destino inesperado.
  • La misma petición repetida a intervalos regulares, con respuestas pequeñas y casi idénticas. Es el patrón de beaconing, que tiene sección propia.
  • Descargas de ejecutables por HTTP: mira los tipos en Export Objects.
Displayhttp.user_agent matches "(?i)curl|wget|python|powershell"

Error común. Filtrar http y concluir que no hay tráfico web. Hoy casi todo es HTTPS, y con HTTPS no hay ningún paquete que Wireshark clasifique como http: el disector solo ve TLS. Para ver el tráfico web real filtra tls o tcp.port == 443. Y si una aplicación usa HTTP en un puerto raro, clic derecho → Decode As… le dice a Wireshark que lo interprete como HTTP.

HTTPS y TLS

Qué protege exactamente el cifrado — y qué sigue estando a la vista.

Objetivo: entender qué protege TLS exactamente y qué no.

Displaytls
bash
$ curl -s -o /dev/null https://archlinux.org

Ahora el Follow Stream devuelve ruido binario: el contenido está cifrado. Pero el sobre no lo está. Selecciona el primer paquete, el Client Hello, y despliega hasta las extensiones. Busca server_name:

Displaytls.handshake.extensions_server_name

Ahí está archlinux.org, en texto plano. Es el SNI: el cliente tiene que decir a qué sitio se conecta antes de que exista el cifrado, porque una misma IP aloja muchos dominios y el servidor necesita saber qué certificado enviar.

Así que un observador en la red ve: tu IP, la IP del servidor, el dominio (por SNI y por DNS), el momento, el volumen y el ritmo del tráfico. Lo que no ve es el contenido: qué páginas concretas, qué escribiste, qué te devolvieron.

Despliega también el Certificate en la respuesta del servidor — está sin cifrar y contiene el emisor, la validez y el nombre común. Es exactamente lo que tu navegador comprueba.

El handshake, mensaje a mensaje

El campo tls.handshake.type identifica cada paso:

Mensajes del handshake TLS
TipoMensajeQué lleva y qué se ve
1Client HelloVersiones que acepta, cipher suites que soporta, y el SNI en claro. Su combinación concreta de opciones es tan característica del cliente que se usa como huella (JA3/JA4).
2Server HelloLa versión y el cipher suite elegidos. A partir de aquí, en TLS 1.3, casi todo lo demás va cifrado.
11CertificateLa cadena de certificados. En TLS 1.2 va en claro; en 1.3 va cifrada.
16Client Key ExchangeMaterial para derivar la clave (solo TLS 1.2 y anteriores).
Displaytls.handshake.type == 1
Displaytls.handshake.type == 2
Displaytls.handshake.type == 11

Distinguir la versión tiene truco: tls.record.version suele valer 1.2 por compatibilidad incluso en conexiones 1.3. La versión real negociada está en la extensión supported_versions del Server Hello. Si necesitas inventariar versiones de TLS, fíjate en esa, no en la del registro.

Displaytls.alert_message

Las alertas TLS marcan handshakes fallidos: certificado caducado, autoridad desconocida, no hay cipher suite en común. Es lo primero que hay que mirar cuando una aplicación «no conecta» y no da más detalle.

Ciberseguridad: analizar lo que no puedes leer

Que el contenido esté cifrado no deja al analista sin nada. Estos son los metadatos que siguen siendo válidos:

  • El SNI — el destino real, aunque el contenido no se vea. Es el dato más valioso de una conexión TLS.
  • El tamaño y el ritmo — una conexión que envía 200 bytes cada 60 segundos exactos tiene una forma reconocible aunque no sepas qué dice.
  • La duración — conexiones muy largas y muy silenciosas destacan frente a la navegación normal.
  • El cipher suite y la huella del Client Hello — dos programas distintos negocian TLS de forma distinta. Un cliente cuya huella no coincide con ningún navegador conocido, en un equipo donde solo debería haber navegadores, es una anomalía.
  • Certificados llamativos (cuando son visibles): autofirmados, con validez muy corta, o con campos de organización claramente generados.
Displaytls.handshake.extensions_server_name contains "duckdns"

Ejemplo del método: buscar en el SNI proveedores de DNS dinámico, muy usados para infraestructura efímera. Sustituye la cadena por lo que estés investigando. Y recuerda que esos servicios también tienen usos completamente legítimos.

Parte 03Intermedio

Wireshark a fondo

Las herramientas del programa que convierten una lista de paquetes en una investigación.

Follow Stream

Dejar de mirar paquetes sueltos y ver el diálogo.

Objetivo: dejar de mirar paquetes sueltos y ver el diálogo.

Un paquete aislado dice poco. Lo interesante es la conversación reensamblada. Con la captura de HTTP del ejercicio anterior todavía abierta, clic derecho en cualquier paquete de esa conexión → Follow → TCP Stream.

Se abre una ventana con el diálogo completo en texto: en un color lo que tú enviaste, en otro lo que respondió el servidor. Verás literalmente la petición HTTP:

follow tcp stream
GET / HTTP/1.1
Host: neverssl.com
User-Agent: curl/8.x
Accept: */*

HTTP/1.1 200 OK
Content-Type: text/html
...

Eso es lo que significa que HTTP «no es seguro»: no hace falta ninguna herramienta especial, está ahí en claro. Fíjate en que el User-Agent te identifica y el Host dice qué sitio pides.

Al cerrar la ventana, Wireshark deja puesto un filtro tcp.stream eq N. Ese número identifica la conexión dentro de la captura, y es una de las formas más rápidas de moverse: cambia el número y saltas a otra conversación.

Prueba también File → Export Objects → HTTP: Wireshark lista todos los ficheros que viajaron por la captura (páginas, imágenes, scripts) y te los guarda en disco reconstruidos.

La ruta completa del menú

La entrada oficial es Analyze → Follow, y también está en el menú contextual de la lista de paquetes. El submenú ofrece un tipo de flujo por protocolo: TCP, UDP, DCCP, TLS, HTTP, HTTP/2, QUIC, WebSocket, SIP y USB CDC. Elegir el correcto importa:

  • TCP Stream te da el flujo de bytes tal cual viajó, con las cabeceras HTTP incluidas.
  • HTTP Stream aplica además la descompresión: si la respuesta venía con Content-Encoding: gzip, aquí la ves legible y en TCP Stream no.
  • TLS Stream muestra el contenido descifrado, y solo sirve si has configurado las claves como se explica más abajo.

El diálogo por dentro

Abajo del todo hay tres controles que se pasan por alto:

  • Un desplegable de dirección: la conversación entera, solo cliente→servidor o solo servidor→cliente. Aislar un sentido es lo que hace legible una conversación larga.
  • Show data as, con los formatos ASCII, C Arrays, EBCDIC, HEX Dump, UTF-8, UTF-16, YAML y Raw. Si ASCII se ve como basura, el contenido es binario: pasa a HEX Dump, que muestra offset, hexadecimal y texto a la vez.
  • Un campo de búsqueda dentro del flujo, y los botones para navegar entre streams sin cerrar la ventana.

Limitaciones

  • Solo reconstruye lo que capturaste. Si empezaste a capturar a mitad de la conexión, faltará el principio y Wireshark lo indicará.
  • Necesita el flujo completo. Con paquetes perdidos, aparecen huecos.
  • No descifra por sí solo. Sin claves, TLS es binario.
  • Se carga en memoria. Seguir una descarga de dos gigabytes puede dejar el programa inutilizable un buen rato.
  • El texto que ves es datos, no comandos. Un flujo puede contener cualquier cosa que el otro extremo haya querido enviar; trátalo como material a analizar.

El menú Statistics

Pasar del paquete al panorama. Aquí es donde se diagnostica de verdad.

Objetivo: pasar del paquete al panorama. Aquí es donde se diagnostica de verdad.

Captura treinta segundos de navegación normal, para y recorre el menú Statistics:

Protocol Hierarchy

Un desglose porcentual de todo lo capturado por protocolo. Es la primera parada ante una captura desconocida: en diez segundos sabes si esto es sobre todo TLS, o hay un torrente de UDP, o alguien está haciendo mucho DNS.

Conversations

Una fila por par de extremos, con bytes y duración. Ordena por la columna Bytes descendente y tienes al instante quién está consumiendo el ancho de banda. Clic derecho en una fila → Apply as Filter para bajar al detalle.

Endpoints

Lo mismo pero por dirección individual, no por pareja. La pestaña IPv4 tiene una casilla de resolución geográfica útil para ver adónde sale tu tráfico.

I/O Graph

Tráfico en el tiempo. Sirve para ver picos, cortes y patrones periódicos. Puedes añadir varias líneas, cada una con su propio display filter — por ejemplo una con tcp.analysis.retransmission superpuesta al total, y si las retransmisiones suben cuando sube el tráfico, tienes congestión.

Expert Information

La lista de todo lo que Wireshark considera anómalo, clasificado por severidad. Retransmisiones, ACKs duplicados, ventanas a cero, conexiones reiniciadas. Ante «la red va lenta», este diálogo es el atajo.

Y el filtro de diagnóstico que más se usa:

Displaytcp.analysis.flags

Muestra solo los paquetes que Wireshark ha marcado como problemáticos. En una red sana, apenas aparece nada.

Cómo se usan de verdad en una investigación

Cada diálogo responde a una pregunta distinta. En este orden:

Capture File Properties · ¿me puedo fiar de esta captura?

Antes que nada. Da el intervalo temporal cubierto, el número de paquetes y —lo importante— cuántos se descartaron. Si hay descartes, cualquier conclusión sobre pérdidas es sospechosa: puede que el problema fuera tu propio equipo capturando. También tiene un campo de comentarios que se guarda dentro del .pcapng: úsalo para anotar dónde y cuándo capturaste.

Protocol Hierarchy · ¿qué hay aquí dentro?

El árbol con el porcentaje de bytes de cada protocolo. Lo que hay que buscar no es un valor concreto sino lo que no encaja: un protocolo que no debería estar en ese segmento, un porcentaje de «Data» alto (tráfico que Wireshark no supo clasificar, a menudo por ir en puertos no estándar), o UDP dominando donde esperabas TCP. Clic derecho en cualquier fila → Apply as Filter para bajar al detalle.

Conversations · ¿quién habla con quién?

Una fila por par de extremos, con pestañas Ethernet, IPv4, IPv6, TCP y UDP. Tres columnas que se leen juntas: Bytes A→B y B→A (la asimetría cuenta la historia: descargar es normal, subir mucho no siempre), Duration y Bits/s.

Marca la casilla Limit to display filter para que el diálogo respete el filtro que tengas puesto. Sin ella verás la captura entera y te preguntarás por qué no cuadran los números.

Endpoints · ¿con cuántos sitios distintos?

Por dirección individual. La pestaña IPv4 admite resolución geográfica si tienes las bases de datos de MaxMind configuradas. Ordenar por número de paquetes revela al instante los destinos dominantes; ordenar por número de conversaciones revela a un equipo que habla con muchísimos sitios, que es la forma de un escaneo.

Packet Lengths · ¿qué forma tiene este tráfico?

Un histograma por rangos de tamaño. Es más útil de lo que parece porque cada tipo de tráfico tiene su perfil: la navegación mezcla paquetes pequeños (peticiones, ACK) con grandes (contenido). Un flujo compuesto casi solo de paquetes pequeños de tamaño casi idéntico no se parece a navegación humana — puede ser telemetría, una sesión interactiva o un canal de control.

I/O Graphs · ¿cuándo pasó?

El eje del tiempo. Añade una línea por filtro, ajusta el intervalo y compara. Con intervalos de un segundo ves ráfagas; con intervalos de un minuto ves patrones de fondo. Es la herramienta central para detectar periodicidad, y aparece otra vez en la sección de beaconing.

Flow Graph · ¿en qué orden?

Un diagrama de secuencia con el tiempo en vertical y los equipos en columnas. Limitado al flujo TCP que estés investigando, es la mejor forma de explicarle a otra persona qué pasó en una conexión: se ve el handshake, los datos y el cierre como una escalera.

Expert Information

La lista de todo lo que a Wireshark le ha parecido raro.

Se abre en Analyze → Expert Information, o pulsando el círculo de color de la esquina inferior izquierda. Agrupa los avisos por tipo, con el número de ocurrencias y un desplegable con los paquetes concretos.

Niveles de severidad de Expert Information
NivelQué agrupaEjemplos
ErrorAlgo está mal formado o es inválidoPaquete malformado, checksum incorrecto
WarningComportamiento anómalo del protocoloConexión reiniciada, ventana a cero, ACK de segmento no visto
NoteComportamiento normal pero digno de menciónRetransmisión, ACK duplicado, fuera de orden
ChatEventos normales del flujoSYN, FIN, petición HTTP
CommentComentarios añadidos a paquetesAnotaciones tuyas guardadas en el pcapng

El desplegable Severity filtra la vista, y la casilla Limit to Display Filter restringe el análisis a lo que estés mirando — imprescindible en capturas grandes, donde la lista completa es inmanejable.

Cada línea tiene un menú contextual con Apply as Filter: de la lista agregada saltas directamente a los paquetes implicados.

Práctica. Abre Expert Information sobre una captura de tu navegación normal. Anota qué avisos aparecen y cuántos. Esa es tu línea base: la próxima vez que investigues algo, sabrás qué parte de la lista es simplemente cómo se comporta tu red.

Coloring rules

Que la captura te avise antes de que la mires con detalle.

Los colores de la lista de paquetes no son decorativos ni fijos: son una lista de reglas en View → Coloring Rules. Cada regla es un display filter con un color de fondo y otro de texto. Wireshark evalúa de arriba abajo y aplica la primera que coincide; el orden es, por tanto, la parte importante.

Las reglas de fábrica ya dicen bastante: negro sobre rojo es «Checksum Errors», rojo claro es «Bad TCP» (retransmisiones, ACK duplicados, resets), gris es tráfico de control TCP como SYN y FIN. Por eso «negro sobre rojo casi siempre significa problema».

Crear una regla propia

  1. Abre View → Coloring Rules.
  2. Pulsa +: aparece una regla nueva al principio de la lista.
  3. Ponle un nombre descriptivo, por ejemplo DNS lento.
  4. En el campo de filtro escribe la condición: dns.time > 0.5.
  5. Con la regla seleccionada, elige Background y Foreground.
  6. Arrástrala por encima de las reglas más generales, o nunca llegará a evaluarse.
  7. OK. La lista se recolorea al instante.

Un atajo que ahorra tiempo: clic derecho sobre un paquete → Colorize with Filter → New Coloring Rule… crea la regla con el filtro ya rellenado.

Un juego de reglas orientado a seguridad

Estas cinco, en este orden, hacen que las anomalías salten a la vista:

Reglas de coloreado propuestas para análisis defensivo
NombreFiltroPara qué
SYN sin respuestatcp.flags.syn == 1 && tcp.flags.ack == 0Aperturas de conexión: un escaneo se ve como una franja de color.
Conexión rechazadatcp.flags.reset == 1Puertos cerrados y cortes abruptos.
DNS sin resolverdns.flags.rcode == 3NXDOMAIN, para verlos agrupados.
Texto sin cifrarhttp || ftp || telnetProtocolos que exponen contenido.
Salida de la redip.src == 10.2.3.0/24 && !(ip.dst == 10.2.3.0/24)Todo lo que abandona tu segmento.

Las reglas se guardan en el perfil activo, en un fichero colorfilters. Se pueden exportar e importar desde el mismo diálogo, que es como se comparte un juego de reglas con un equipo.

Columnas propias

Ver el dato que importa sin abrir el árbol en cada paquete.

Las columnas por defecto son genéricas. Al investigar un protocolo concreto, poner ese campo en una columna cambia la forma de trabajar: puedes ordenar por él, compararlo entre paquetes de un vistazo y exportarlo a CSV.

La forma rápida

Selecciona el campo en el árbol → clic derecho → Apply as Column. Ya está. Para quitarla, clic derecho en su cabecera → Remove this Column.

La forma completa está en Edit → Preferences → Appearance → Columns, donde puedes reordenarlas, ocultarlas sin borrarlas y elegir el tipo (usa Custom y escribe el nombre del campo).

Columnas que merecen la pena

Columnas personalizadas recomendadas
ColumnaCampoPor qué ayuda
Puerto origentcp.srcportDistinguir cliente de servidor de un vistazo.
Puerto destinotcp.dstportOrdenando por él, un escaneo de puertos se ve como una escalera.
Streamtcp.streamSaber a qué conexión pertenece cada paquete sin abrir el árbol.
Consulta DNSdns.qry.nameLeer todos los dominios consultados como una lista.
Host HTTPhttp.hostIgual, para peticiones web sin cifrar.
SNItls.handshake.extensions_server_nameEl destino real de cada conexión HTTPS. La columna más útil hoy.
TTLip.ttlAgrupar orígenes y detectar incoherencias.
Delta de conexióntcp.time_deltaMedir periodicidad dentro de una misma conexión.

Con las columnas puestas, File → Export Packet Dissections → As CSV exporta exactamente esas columnas de los paquetes mostrados. Es la forma de llevar un hallazgo a una hoja de cálculo o a un informe.

Perfiles

Un Wireshark distinto para cada tipo de trabajo.

Un perfil es un conjunto completo de configuración: columnas, reglas de coloreado, filtros guardados, preferencias de disectores y diseño de paneles. Wireshark guarda cada uno en su propio directorio y se cambia entre ellos al instante.

La razón de usarlos es práctica: la configuración que quieres para diagnosticar una red lenta no es la que quieres para investigar un incidente. En vez de reconfigurar cada vez, cambias de perfil.

Crear uno

  1. Abre Edit → Configuration Profiles (o pulsa la esquina inferior derecha de la barra de estado, donde pone el perfil actual).
  2. Pulsa + y ponle nombre, por ejemplo Cybersecurity.
  3. Con el perfil ya activo, añade las columnas de la sección anterior.
  4. Añade las reglas de coloreado de la sección de coloring rules.
  5. Guarda como botón los filtros que más repitas, con el + de la barra de filtros.
  6. Ajusta Preferences → Protocols → TCP para activar los timestamps de conversación.

Para partir de una copia de otro perfil en vez de empezar en blanco, selecciónalo y usa el botón de copiar del mismo diálogo.

Los perfiles viven en el directorio personal de configuración, dentro de profiles/. Puedes verlo desde Help → About Wireshark → Folders, que te da la ruta exacta en tu sistema. Copiar esa carpeta a otro equipo lleva el perfil entero con él.

Descifrar tu propio TLS

Ver HTTPS en claro usando las claves de tu propio navegador, en tu propio laboratorio.

Objetivo: ver HTTPS en claro usando las claves de tu propio navegador.

No es un ataque: es que el navegador te presta sus claves de sesión porque tú se lo pides. Firefox y Chrome escriben las claves efímeras en un fichero si defines SSLKEYLOGFILE, y Wireshark sabe leerlo.

bash
$ export SSLKEYLOGFILE=~/tls-keys.log
$ firefox --new-instance

Firefox tiene que arrancar desde esa misma terminal para heredar la variable; si ya estaba abierto, ciérralo del todo antes. Luego, en Wireshark:

wireshark · preferencias
Edit → Preferences → Protocols → TLS
  → (Pre)-Master-Secret log filename: /home/lucio/tls-keys.log

Empieza la captura, navega a cualquier sitio HTTPS, y filtra por http2. Los paquetes que antes eran «Application Data» ilegible ahora aparecen desmontados: cabeceras, cookies, JSON, todo. Follow → HTTP/2 Stream lo muestra en texto.

Por qué esto funciona

Merece entenderse, porque explica a la vez el alcance y el límite de la técnica.

TLS moderno usa intercambio de claves con secreto hacia adelante: las claves que cifran la sesión se generan al vuelo para esa conexión y no se derivan de la clave privada del servidor. Por eso, ni siquiera teniendo la clave privada del servidor se puede descifrar una sesión TLS 1.3 grabada.

Lo que sí existe es el material de la sesión, dentro de la memoria del cliente. El navegador, si le pides que colabore, lo escribe en el fichero de SSLKEYLOGFILE. Wireshark lee ese fichero y descifra. Es decir: funciona porque uno de los dos extremos de la conversación —tú— coopera voluntariamente.

De ahí se sigue lo importante:

  • Solo descifra las conexiones cuyas claves están en tu fichero, es decir, las que hizo tu navegador mientras la variable estaba puesta.
  • No hay forma de obtener las claves de otra persona con esta técnica. No es una debilidad de TLS: es una función de depuración.
  • Si capturaste antes de arrancar el navegador con la variable, esas conexiones no se descifrarán nunca.

Riesgos del fichero de claves

  • Mientras la variable esté activa, todas tus sesiones TLS quedan descifrables por quien tenga el fichero y la captura. Incluidas las que no pretendías analizar: correo, banca, sesiones de trabajo.
  • Un .pcapng puede llevar las claves dentro, si usas File → Export Packet Dissections o incrustas el secrets block. Cómodo para compartir un caso con un compañero; catastrófico si ese fichero acaba donde no debe.
  • Ponlo en la variable solo en la terminal donde lo necesites; jamás en .bashrc, .profile ni en el entorno del escritorio.
  • Bórralo al terminar, y borra también las capturas de laboratorio que ya no necesites.

tshark

Lo mismo sin ventana: servidores, scripts y sesiones SSH.

Objetivo: capturar en servidores, en scripts y en sesiones SSH.

tshark es el mismo motor sin GUI, con los mismos display filters. Captura diez paquetes DNS y muéstralos:

bash
$ tshark -i wlan0 -c 10 -f "port 53"

Fíjate en -f: es el capture filter (sintaxis BPF). El display filter va con -Y:

bash
$ tshark -i wlan0 -Y "dns.flags.response == 0"

Lo más potente es extraer campos concretos en columnas, listo para sort o awk:

bash
$ tshark -i wlan0 -Y dns -T fields \
      -e frame.time_relative -e ip.src -e dns.qry.name

El flujo de trabajo habitual es capturar sin interfaz y analizar con la GUI:

bash
# capturar 60 s a fichero
$ tshark -i wlan0 -a duration:60 -w ~/captura.pcapng

# abrirlo en la GUI
$ wireshark ~/captura.pcapng

El formato .pcapng es estándar: lo lee cualquier herramienta de análisis, y es lo que te pasarán si alguien te pide ayuda con un problema de red. Guardar la captura (Ctrl+S) es parte del trabajo, no un extra.

Recetas que resuelven preguntas reales

Aquí es donde tshark supera a la interfaz: contar, agrupar y ordenar.

Los veinte dominios más consultados

bash
$ tshark -r captura.pcapng -Y "dns.flags.response == 0" \
      -T fields -e dns.qry.name | sort | uniq -c | sort -rn | head -20

La primera pregunta de casi cualquier investigación. Si un dominio desconocido aparece cientos de veces, ya tienes por dónde empezar.

Todos los destinos HTTPS, por nombre

bash
$ tshark -r captura.pcapng -Y "tls.handshake.type == 1" \
      -T fields -e tls.handshake.extensions_server_name | sort -u

Quién habla con quién y cuánto

bash
$ tshark -r captura.pcapng -q -z conv,tcp

La misma tabla que Statistics → Conversations, en texto. -q silencia el volcado de paquetes y -z pide una estadística. Otras útiles: -z io,phs (jerarquía de protocolos) y -z endpoints,ip.

Intervalos entre conexiones, para medir periodicidad

bash
$ tshark -r captura.pcapng \
      -Y "tcp.flags.syn == 1 && tcp.flags.ack == 0 && ip.dst == 203.0.113.9" \
      -T fields -e frame.time_epoch \
  | awk 'NR>1 {printf "%.1f\n", $1-prev} {prev=$1}'

Imprime el hueco en segundos entre cada intento de conexión. Si la columna es casi constante, tienes periodicidad — el indicador central de la sección de beaconing.

Cortar una captura enorme

bash
# quedarse solo con un equipo
$ tshark -r grande.pcapng -Y "ip.addr == 10.2.3.170" -w recorte.pcapng

Trabajar sobre un recorte es más rápido y, si vas a compartirlo, expone mucho menos.

PCAP y su custodia

El formato de las capturas, y por qué un fichero de estos es información sensible.

Hay dos formatos y conviene distinguirlos:

Formatos de captura
FormatoCaracterísticas
.pcapEl clásico. Una sola interfaz, marcas de tiempo con precisión de microsegundo, sin metadatos. Máxima compatibilidad con herramientas antiguas.
.pcapngEl actual, y el que Wireshark usa por defecto. Varias interfaces en un fichero, nanosegundos, comentarios por paquete, metadatos del equipo que capturó y bloques de secretos.

Trabajar sobre ficheros en lugar de capturar en vivo es lo normal en análisis: es repetible, se puede compartir, y no te obliga a estar delante cuando ocurre el problema.

Operaciones habituales

  • Abrir: File → Open, o wireshark fichero.pcapng.
  • Guardar solo lo filtrado: File → Export Specified Packets…, con la opción All packets / Displayed. Es la forma correcta de reducir una captura a lo relevante.
  • Anotar: clic derecho en un paquete → Packet Comment…. El comentario se guarda dentro del .pcapng y aparece en Expert Information. Es la manera de dejar dicho por qué ese paquete importa.
  • Unir o dividir: las herramientas de línea de comandos mergecap y editcap. Por ejemplo, trocear por tiempo:
bash
# dividir en trozos de 60 segundos
$ editcap -i 60 grande.pcapng trozo.pcapng

Un PCAP es información sensible

Reglas prácticas para manejarlos:

  • Captura lo mínimo necesario. Un capture filter bien puesto es también una medida de protección de datos: lo que no capturas no puede filtrarse.
  • Recorta antes de compartir. Export Specified Packets con solo la conversación relevante.
  • Anonimiza si el destinatario no necesita las direcciones. Existen herramientas específicas de sanitizado de PCAP; ten en cuenta que anonimizar bien es más difícil de lo que parece, porque los identificadores aparecen en muchos sitios a la vez.
  • Para aprender, usa capturas públicas de laboratorio en lugar de tráfico real de una organización.
  • Trátalos como evidencia si lo son: calcula el hash al obtenerlos, guarda dónde y cuándo se capturaron, y no trabajes sobre el original sino sobre una copia.
  • Bórralos cuando ya no hagan falta. Una carpeta de capturas viejas es un problema esperando a ocurrir.
Parte 04Ciberseguridad

Ciberseguridad

Análisis defensivo: reconocer, investigar y documentar. Nada de esta parte enseña a atacar.

Wireshark para análisis defensivo

Qué se puede y qué no se puede concluir mirando tráfico.

Todo lo que viene ahora está escrito desde el lado del defensor: alguien que tiene una captura de una red que administra o que está autorizado a analizar, y que necesita responder «¿esto es normal?».

Wireshark no es un IDS. No tiene firmas, no puntúa amenazas, no avisa. Lo que aporta es la máxima resolución posible: el paquete exacto, con todos sus campos. Por eso es la herramienta de la fase de confirmación, no la de detección. El camino típico es: una alerta llega de otro sitio → se recupera la captura → Wireshark responde qué pasó exactamente.

Las tres preguntas que ordenan cualquier análisis

  1. ¿Qué veo? Hechos observables en la captura. «El equipo 10.2.3.55 abrió 40 conexiones al puerto 443 de 203.0.113.9 en diez minutos.» Esto no se discute: está en el fichero.
  2. ¿Qué significa? Interpretación, que depende del contexto. «Cuarenta conexiones en diez minutos a intervalos casi constantes no se parecen a navegación humana.»
  3. ¿Qué no puedo saber desde aquí? El límite. «No sé qué se envió, porque va cifrado. No sé si ese destino es legítimo. No sé si el proceso que lo generó es malicioso.»

Lo que una captura no te va a decir

  • Qué proceso lo generó. La captura ve puertos, no programas. Eso se responde en el equipo, con ss -tanp o el registro del sistema.
  • Quién estaba delante. Una IP identifica un equipo, y solo mientras dure la concesión DHCP.
  • El contenido cifrado. Salvo que sea tu propio tráfico y tengas las claves.
  • Qué pasó fuera de la ventana capturada.
  • Si el destino es malicioso. Eso es inteligencia externa, no análisis de paquetes.

Reconocer estos límites en voz alta es lo que distingue un análisis serio. Las secciones que siguen dan indicadores concretos; ninguno es una conclusión por sí mismo.

Línea base

Para reconocer el tráfico malo primero hay que conocer el normal.

Este es el consejo más importante de toda esta parte, y el que más se ignora. Sin una referencia de cómo se comporta tu red cuando no pasa nada, cualquier captura parece sospechosa: verás retransmisiones, dominios que no reconoces, conexiones a nubes de medio mundo. Y casi todo será normal.

La solución es barata: dedica una tarde a capturar tu red funcionando bien y anota qué hay. Ese documento vale más que cualquier lista de filtros.

Qué apuntar

Elementos de una línea base de red
DimensiónDónde se miraQué anotar
EquiposStatistics → Endpoints (IPv4 y Ethernet)Qué IP y qué MAC existen; cuál es el gateway.
ProtocolosStatistics → Protocol HierarchyReparto porcentual habitual. Qué protocolos aparecen y cuáles no.
DestinosColumna SNI + consultas DNSLos veinte o treinta dominios recurrentes.
PuertosStatistics → Conversations → TCP/UDPQué puertos de destino son normales aquí.
VolumenStatistics → I/O GraphsTráfico típico por minuto, y la forma de las horas punta.
PeriodicidadI/O Graphs con intervalo largoQué cosas ya laten solas: actualizaciones, NTP, monitorización.
Anomalías normalesAnalyze → Expert InformationCuántas retransmisiones y ACK duplicados hay de normal.

Ese último punto es el que más disgustos ahorra: si tu wifi genera de normal un 2 % de retransmisiones, encontrarlas durante un incidente no significa nada.

bash
# línea base de destinos: los 30 dominios más consultados
$ tshark -r baseline.pcapng -Y "dns.flags.response == 0" \
      -T fields -e dns.qry.name | sort | uniq -c | sort -rn | head -30 \
  > baseline-dominios.txt

Guarda ese fichero. La próxima vez, genera el mismo listado sobre la captura nueva y compáralos con comm o diff: lo que aparece y no estaba es tu lista de candidatos a investigar. Es una técnica sencilla y sorprendentemente eficaz.

Escaneo de puertos

Cómo se ve desde el lado del que lo recibe.

Qué es. Alguien quiere saber qué servicios tiene un equipo, así que intenta abrir conexiones a muchos puertos y observa qué contesta cada uno. No es en sí un ataque: es reconocimiento. Pero rara vez hay una razón legítima para que un equipo de tu red escanee a otro sin que tú lo sepas.

Qué rastro deja. La firma no está en ningún paquete individual —cada SYN es un SYN perfectamente normal— sino en la forma del conjunto:

  • Muchos SYN desde un mismo origen.
  • Hacia muchos puertos distintos (escaneo de puertos) o muchas IP distintas (barrido de red).
  • En una ventana de tiempo corta.
  • Con pocos handshakes completos: la mayoría acaba en RST (puerto cerrado) o sin respuesta (filtrado).
  • A menudo con puertos de destino secuenciales o siguiendo una lista conocida de servicios.

Cómo se investiga

  1. Aísla las aperturas de conexión: tcp.flags.syn == 1 && tcp.flags.ack == 0. Mira el contador Displayed: si es un número grande respecto al total, ya es un dato.
  2. Abre Statistics → Conversations con Limit to display filter marcado y ve a la pestaña TCP. Ordena por origen. Un escaneo se ve como cientos de filas con la misma IP A y puertos B distintos, cada una con muy pocos paquetes.
  3. Añade tcp.dstport como columna y ordena por ella: si los puertos suben en escalera, la forma es inconfundible.
  4. Comprueba qué contestó: tcp.flags.reset == 1 son puertos cerrados que respondieron. Los que no aparecen es que no contestaron nada.
  5. Busca los que se completaron: esos son los servicios que el escaneo encontró abiertos, y son el foco de lo que venga después.
  6. Mira el I/O Graph con la vista filtrada por los SYN: un escaneo produce un pico compacto, no una curva suave.
Displaytcp.flags.syn == 1 && tcp.flags.ack == 0
Displaytcp.flags.reset == 1 && tcp.flags.ack == 1
Displaytcp.completeness < 7

Este último aprovecha un campo que Wireshark calcula por conexión: marca las conexiones que no llegaron a completarse. Muchas conexiones incompletas desde un mismo origen es exactamente el patrón.

¿Qué distingue un escaneo de una aplicación con problemas?

Una aplicación que reintenta conectar contra un servicio caído también genera muchos SYN sin respuesta. Se distinguen por tres cosas:

  • Variedad de destino. La aplicación insiste contra el mismo puerto e IP; el escaneo recorre muchos.
  • Retransmisiones. El reintento legítimo de TCP retransmite el mismo SYN con intervalos que se van doblando (1 s, 2 s, 4 s…), y Wireshark lo marca como tcp.analysis.retransmission. Un escáner no espera: lanza y sigue.
  • Puerto origen. Los reintentos de una misma conexión conservan el puerto origen; un escaneo usa uno nuevo por cada intento.

Beaconing

El latido: conexiones regulares hacia un mismo destino.

Qué es. Un programa que se comunica periódicamente con un servidor para preguntar si hay órdenes. Es el patrón de comunicación de la mayoría del software de control remoto — el legítimo y el que no lo es. Lo que lo hace detectable es que un programa es regular de un modo en que una persona no lo es.

Beaconing · intervalo constante, transferencia mínima

Navegación humana · ráfagas irregulares y silencios largos

La diferencia no está en un paquete: está en el eje del tiempo.

Qué rastro deja:

  • Intervalo casi constante entre conexiones al mismo destino.
  • Transferencias pequeñas y de tamaño parecido — la mayoría de las veces la respuesta es «no hay nada para ti».
  • Persistencia en el tiempo, incluso fuera de horario laboral, cuando nadie está usando el equipo.
  • Un solo destino, o unos pocos, repetidos.

Cómo se mide la periodicidad

  1. Localiza al candidato en Statistics → Conversations: ordena por número de paquetes o de conexiones hacia un mismo destino externo.
  2. Filtra esa pareja: ip.addr == 10.2.3.55 && ip.addr == 203.0.113.9.
  3. Quédate solo con los inicios de conexión, que es lo que marca el ritmo: añade && tcp.flags.syn == 1 && tcp.flags.ack == 0.
  4. Cambia View → Time Display Format a Seconds Since Previous Displayed Packet. La columna Time pasa a ser directamente el intervalo.
  5. Mira esa columna: si los valores rondan siempre el mismo número, tienes periodicidad.
  6. Confírmalo visualmente en Statistics → I/O Graphs, con una línea para ese filtro y un intervalo de 1 segundo: el beaconing se dibuja como un peine regular.

Y la forma rápida, en terminal, sobre una captura ya guardada:

bash
$ tshark -r captura.pcapng \
      -Y "ip.dst == 203.0.113.9 && tcp.flags.syn == 1 && tcp.flags.ack == 0" \
      -T fields -e frame.time_epoch \
  | awk 'NR>1 {printf "%.1f\n", $1-prev} {prev=$1}' \
  | sort -n | uniq -c

Si la salida se concentra en uno o dos valores, el intervalo es fijo. Si está repartida por todas partes, es tráfico irregular — probablemente humano.

El jitter

El software de control moderno introduce una variación aleatoria deliberada en el intervalo, precisamente para no dibujar un peine perfecto. Un beacon de 60 segundos con un 20 % de jitter aparecerá entre 48 y 72. Sigue siendo detectable: la distribución continúa siendo estrecha comparada con la de un humano, que salta de dos segundos a media hora.

Por eso conviene mirar la dispersión, no solo la media. Con la columna de deltas exportada a CSV y una hoja de cálculo, la desviación típica dividida entre la media da un número: cuanto más cerca de cero, más regular.

DNS sospechoso

Checklist defensivo sobre el protocolo que más cuenta.

La sección de DNS ya explicó los indicadores. Aquí van convertidos en un procedimiento que puedes ejecutar sobre cualquier captura.

Checklist

Checklist de revisión de DNS
#ComprobaciónFiltro o herramienta
1¿Cuántas consultas hay y a qué resolver van?dns.flags.response == 0
2¿Alguien consulta a un resolver distinto del corporativo?dns && !(ip.dst == 10.2.3.1)
3¿Qué proporción de NXDOMAIN hay?dns.flags.rcode == 3
4¿Hay nombres anormalmente largos?dns.qry.name.len > 50
5¿Hay consultas TXT desde equipos de escritorio?dns.qry.type == 16
6¿Hay un dominio consultado con una frecuencia rara?tshark + uniq -c
7¿Hay muchos subdominios distintos de un mismo dominio padre?Ordenar la lista de nombres
8¿Aparece algún dominio que no esté en tu línea base?comm contra el fichero base

El punto 7 merece explicación porque es el más característico. Sacar datos por DNS obliga a codificarlos en el nombre consultado, y como cada consulta lleva pocos bytes, hacen falta muchas. El resultado es un mismo dominio padre con cientos o miles de subdominios distintos, cada uno consultado una sola vez.

bash
# subdominios distintos por dominio padre
$ tshark -r captura.pcapng -Y "dns.flags.response == 0" \
      -T fields -e dns.qry.name \
  | awk -F. '{print $(NF-1)"."$NF}' | sort | uniq -c | sort -rn | head

Un dominio con 3 000 consultas y 3 000 nombres distintos tiene una forma muy diferente de uno con 3 000 consultas al mismo nombre. El primero merece una mirada; el segundo es probablemente una caché mal configurada.

Qué explicaciones benignas hay que descartar primero
  • Antivirus y reputación en la nube. Consultan nombres generados a partir del hash de lo que analizan. Producen exactamente el patrón de «muchos subdominios largos y únicos».
  • Redes de distribución de contenido. Generan nombres largos y aparentemente aleatorios.
  • Sufijos de búsqueda. Un dominio de búsqueda mal configurado hace que cada nombre se intente varias veces, multiplicando los NXDOMAIN.
  • mDNS. El descubrimiento de impresoras y altavoces en la red local genera mucho tráfico con aspecto extraño en el puerto 5353. Es normal.
  • DoH del navegador. Explica que un equipo «no consulte» al resolver corporativo: sus consultas van cifradas dentro de HTTPS y no las verás como DNS.

Si ninguna de estas explica lo que ves, y el equipo no debería estar haciendo eso, entonces tienes un hallazgo que documentar — todavía no una conclusión.

ARP anómalo

Ejercicio defensivo sobre el protocolo sin autenticación.

La sección de ARP explicó el mecanismo. Aquí está el procedimiento para revisar una captura buscando inconsistencias, y —lo más importante— qué hacer con lo que encuentres.

  1. Filtra arp y abre Statistics → Conversations → Ethernet: obtienes las parejas de MAC que han hablado.
  2. Aplica arp.duplicate-address-detected. Si no hay nada, la captura no muestra conflictos y puedes pasar a otra cosa.
  3. Si hay algo, abre uno de esos paquetes: Wireshark te dice en arp.duplicate-address-frame con qué trama anterior choca. Compara ambas.
  4. Anota las dos MAC y la IP en disputa. Mira el fabricante que resuelve Wireshark para cada MAC: ¿son coherentes con dispositivos que existen en tu red?
  5. Comprueba si la IP en disputa es el gateway. Si lo es, sube la prioridad: es el objetivo con más valor.
  6. Mira la línea temporal: ¿fue un instante durante un cambio de red, o es persistente y se repite?
  7. Contrasta con tu tabla ARP local (ip neigh) y con la tabla de direcciones MAC del switch, si tienes acceso.
Displayarp.duplicate-address-detected
Displayarp.opcode == 2 && arp.src.proto_ipv4 == 10.2.3.1

Ese segundo filtro muestra todas las respuestas que afirman ser el gateway. En una red sana, todas traerán la misma MAC de origen. Añade la columna arp.src.hw_mac y compruébalo de un vistazo.

Defensas que se aplican después, y que no dependen de Wireshark: entradas ARP estáticas para el gateway en equipos críticos, inspección dinámica de ARP en switches gestionados, y segmentación para reducir cuántos equipos comparten un dominio de difusión.

Transferencias de salida inusuales

Detectar que salen datos, desde el lado del que vigila.

Qué se busca. Volumen de datos saliendo de la red hacia un destino que no corresponde. La detección es puramente estadística: no hace falta ver el contenido, solo medir cuánto sale, hacia dónde y cuándo.

El indicador central: la asimetría. La navegación normal es asimétrica en el sentido contrario — descargas mucho más de lo que subes. Una conversación donde el equipo interno envía mucho más de lo que recibe invierte el patrón habitual, y eso es lo que llama la atención.

Procedimiento

  1. Abre Statistics → Conversations, pestaña IPv4.
  2. Ordena por Bytes A→B descendente, asegurándote de qué lado es el interno (la columna A es la que aparece primero en la fila).
  3. Compara las columnas A→B y B→A de las primeras filas. Busca las que envían mucho más de lo que reciben.
  4. Descarta los destinos conocidos de tu línea base: copias de seguridad, sincronización de ficheros, subida de registros.
  5. De los que quedan, mira Duration y la hora de inicio. ¿Ocurrió cuando alguien estaba trabajando?
  6. Filtra esa pareja y mira el I/O Graph: ¿fue un bloque continuo o goteo constante durante horas?
  7. Comprueba el protocolo y el puerto. ¿Encaja con lo que ese equipo debería hacer?
  8. Si hay DNS previo, busca qué nombre resolvió esa IP: dns.a == 203.0.113.9.
Displayip.src == 10.2.3.0/24 && !(ip.dst == 10.2.3.0/24)

Todo lo que abandona tu red. Con este filtro puesto y Limit to display filter marcado en Conversations, las cifras que veas son exclusivamente de salida.

Displaydns.a == 203.0.113.9

Qué nombre de dominio resolvió a esa IP. Es la forma de convertir una dirección anónima en un destino con nombre, usando la propia captura en lugar de consultas externas que avisarían al otro lado.

Otros indicadores

  • Horario. Transferencias grandes fuera de la jornada, cuando el equipo debería estar inactivo.
  • Destino desconocido. Una IP o un dominio que no aparece en la línea base, en un proveedor de nube que la organización no usa.
  • Protocolo impropio. Un volumen alto por un protocolo que no está hecho para transportar datos: DNS, ICMP, o un puerto TCP no habitual en ese equipo.
  • Continuidad. Una sesión larga a ritmo constante encaja peor con trabajo humano que un pico y una pausa.
  • Puerto no estándar con protocolo estándar dentro, o al revés: Protocol Hierarchy con mucho «Data» sin clasificar es una pista.

Y el límite honesto: si el tráfico va cifrado —lo normal—, la captura te dice cuánto salió y hacia dónde, nunca qué. Determinar qué se llevaron exige el equipo de origen: registros de aplicación, auditoría de ficheros, herramientas de detección en el endpoint. Wireshark aporta la mitad de la respuesta, y hay que decirlo así en el informe.

Tráfico HTTP sospechoso

Qué revisar en el poco tráfico web sin cifrar que queda.

Que casi todo sea HTTPS hace que el HTTP restante sea, precisamente por eso, interesante: dispositivos antiguos, aparatos empotrados, portales cautivos... y programas que no se molestan en cifrar.

Qué revisar, en orden

Revisión de tráfico HTTP
QuéFiltroQué buscas
Inventario de destinoshttp.requestAñade http.host como columna. ¿Reconoces todos?
Agentes de usuariohttp.user_agentVacíos, con erratas, o de herramientas que ahí no pintan nada.
Peticiones a IP directahttp.host matches "^[0-9.]+$"Sin resolución DNS previa: poco propio de un navegador.
Métodos poco comuneshttp.request.method != "GET" && http.request.method != "POST"PUT, DELETE, CONNECT donde no se esperan.
Errores repetidoshttp.response.code >= 400Muchos 404 seguidos: alguien probando rutas.
DescargasFile → Export Objects → HTTPTipos de fichero ejecutables o comprimidos.
Repetición regularhttp.request.uri contains "/api"La misma petición cada N segundos: ver la sección de beaconing.
Displayhttp.user_agent matches "(?i)curl|wget|python|powershell"

Credenciales en texto claro

Por qué los protocolos sin cifrar son un riesgo, demostrado con datos ficticios.

Algunos protocolos veteranos transmiten la autenticación sin ninguna protección. No es un fallo de implementación: se diseñaron cuando la red era un entorno de confianza.

Protocolos que transmiten credenciales sin cifrar y sus alternativas
ProtocoloQué exponeAlternativa
TelnetLa sesión entera, incluida la contraseña tecleada carácter a carácterSSH
FTPUsuario y contraseña en los comandos USER y PASSSFTP o FTPS
HTTP básicoUsuario y contraseña en Base64, que no es cifradoHTTPS
SNMPv1/v2cLa community string, que funciona como contraseñaSNMPv3
POP3 / IMAP sin TLSCredenciales de correoSus variantes sobre TLS

Demostración de laboratorio

Así se ve un inicio de sesión FTP en un Follow TCP Stream. Los datos son ficticios y el servidor, uno de laboratorio propio:

follow tcp stream · ftp de laboratorio
220 Servidor FTP de laboratorio
USER usuario_demo
331 Please specify the password.
PASS password_demo
230 Login successful.

No hay ninguna técnica detrás: es Follow TCP Stream sobre una conexión FTP. El protocolo envía esas dos líneas tal cual.

Displayftp.request.command == "PASS"
Displayftp || telnet
Displayhttp.authorization

Resets, retransmisiones y cómo no equivocarse

Los hallazgos que más veces se malinterpretan.

Un RST o una retransmisión no dicen por sí solos qué ha pasado. Dicen que algo interrumpió el flujo esperado. La causa hay que deducirla del contexto, y hay varias posibles con firmas distintas.

Un RST: cuatro explicaciones

Interpretaciones posibles de un TCP reset
CausaCómo se distingue
Puerto cerradoEl RST responde inmediatamente a un SYN. Nunca hubo conexión. Es la respuesta correcta del sistema operativo.
La aplicación cerró de golpeHubo handshake y datos, y luego RST en vez de FIN. El programa terminó sin cerrar bien; muy común y no indica nada malo.
Un intermediario cortóRST a mitad de una sesión sana, a menudo desde los dos lados o con un TTL que no encaja con el del resto de la conversación. Cortafuegos o proxy.
Tiempo de espera agotadoRST después de un silencio largo. Un equipo de red descartó el estado de una conexión ociosa.

El truco del TTL es el más útil de la tabla: si todos los paquetes del servidor llegan con TTL 51 y de pronto aparece un RST «del servidor» con TTL 64, ese RST no lo envió el servidor. Lo envió algo mucho más cercano.

Displaytcp.flags.reset == 1

Retransmisiones: qué las causa de verdad

  • Pérdida real en la red. Congestión, enlace saturado, wifi con interferencias. Suele venir con ACK duplicados y afecta a varias conversaciones a la vez.
  • Pérdida solo en tu captura. Tu equipo no dio abasto y dumpcap descartó paquetes. Wireshark ve un hueco y lo marca. La red estaba perfectamente.
  • Punto de observación. Capturando en el cliente ves lo que le llegó al cliente; el paquete pudo llegar bien al servidor.
  • Reordenación. Marcado como out-of-order, no como pérdida. Es benigno.
  1. Comprueba primero Statistics → Capture File Properties: si hay paquetes descartados, sospecha de tu propia captura antes que de la red.
  2. Mira si el problema afecta a una sola conversación o a todas. Una sola apunta a ese servidor o esa ruta; todas apuntan al enlace local.
  3. Compara el porcentaje con tu línea base. En wifi, un pequeño porcentaje de retransmisiones es normal.
  4. Mira si hay tcp.analysis.zero_window: si lo hay, el cuello de botella es un extremo saturado, no la red.
  5. Superpón en el I/O Graph el tráfico total y las retransmisiones. Si suben juntas, es congestión.

Flujo de análisis en diez preguntas

El procedimiento que aplicar a cualquier captura, en este orden.

Cuando llega una captura y hay que decir algo sobre ella, el error es empezar a mirar paquetes al azar. Esta secuencia va de lo general a lo concreto y evita perderse.

  1. ¿Quién habla? Statistics → Endpoints

    Inventario de equipos que aparecen. ¿Reconoces todas las direcciones? ¿Hay alguna que no debería estar en este segmento?

  2. ¿Con quién? Statistics → Conversations

    Parejas y volumen. Ordena por bytes y por número de paquetes. Los extremos de la lista son siempre lo más informativo.

  3. ¿Qué protocolo? Statistics → Protocol Hierarchy

    Reparto por protocolo. Busca lo que no debería estar, y el porcentaje de tráfico sin clasificar.

  4. ¿Cuándo? Columna Time · Capture File Properties

    Ventana temporal cubierta y a qué hora ocurrió lo interesante. Pon el formato de hora absoluta para poder correlacionar con otros registros.

  5. ¿Con qué frecuencia? I/O Graphs · delta de tiempo

    ¿Es un evento único, una ráfaga o un latido regular? Cambia la escala del gráfico: lo que a un segundo parece ruido, a un minuto puede ser un patrón.

  6. ¿Cuánto tráfico? Conversations · bytes A→B y B→A

    Volumen y sobre todo dirección. La asimetría cuenta más que el total.

  7. ¿Qué contenido? Follow Stream · Export Objects

    Si está en claro, léelo. Si va cifrado, quédate con los metadatos: SNI, tamaños, tiempos. Y dilo explícitamente en el informe.

  8. ¿Es normal? Tu línea base

    La pregunta que da sentido a las siete anteriores. Sin referencia, todo parece sospechoso y nada lo es.

  9. ¿Qué evidencia tengo? Números de trama · marcas de tiempo · hash del fichero

    Anota tramas concretas, no impresiones. Otra persona debe poder abrir la misma captura y ver lo mismo.

  10. ¿Qué hipótesis tengo? Escrito aparte de la evidencia

    Formúlala como hipótesis, con lo que la apoya y lo que la contradice. Y anota qué haría falta para confirmarla, porque casi nunca está en la captura.

Mini informe de incidente

Una plantilla corta que obliga a separar lo observado de lo supuesto.

Un informe no tiene que ser largo. Tiene que ser reproducible: cualquiera con la misma captura debe llegar a los mismos hechos.

plantilla de informe
Fecha:                 2026-09-08 14:05–14:35 UTC-6
Captura:               incidente-20260908.pcapng
SHA-256 de la captura: 3f9a…  (calculado al obtenerla)
Punto de captura:      switch principal, puerto espejo del segmento 10.2.3.0/24
Equipo origen:         PC-CONTABILIDAD-04
IP origen:             10.2.3.55   (MAC 00:1a:2b:3c:4d:5e)
Destino:               203.0.113.9
Puerto / protocolo:    443/tcp · TLS 1.3 · SNI: api.ejemplo-desconocido.net
Primera conexión:      14:07:12
Última conexión:       14:34:48
Frecuencia:            cada 60 s ± 6 s  (28 conexiones)
Bytes enviados:        41 kB
Bytes recibidos:       12 kB
DNS relacionado:       trama 812 · A api.ejemplo-desconocido.net → 203.0.113.9

Indicadores observados:
  - Intervalo casi constante entre conexiones (tramas 815, 1042, 1288…)
  - Transferencias pequeñas y de tamaño similar en cada conexión
  - Dominio ausente de la línea base de 2026-08-15
  - Actividad continúa fuera del horario del usuario

Evidencia:
  - tcp.stream 14, 15, 16 … 41 en la captura citada
  - Consulta DNS en la trama 812
  - Statistics → Conversations: 28 conexiones, 53 kB totales

Hipótesis (NO confirmada):
  Proceso automatizado en el equipo consultando periódicamente un servicio
  externo. La periodicidad y el destino desconocido son compatibles con un
  canal de control, pero también con software legítimo no inventariado.

Lo que esta captura NO permite determinar:
  - Qué proceso del equipo generó el tráfico
  - Qué contenido se transmitió (TLS 1.3, sin claves)
  - Si el destino es legítimo

Siguientes pasos:
  1. En el equipo: ss -tanp durante una ventana de conexión
  2. Revisar inventario de software autorizado del puesto
  3. Consultar reputación del dominio en fuentes de inteligencia
  4. Ampliar la ventana de captura a 24 h para confirmar el patrón
  5. Revisar si otros equipos contactan el mismo destino

Los tres apartados que hacen que esta plantilla funcione:

  • Evidencia — números de trama y de stream. Verificable.
  • Hipótesis — marcada como tal, con la alternativa benigna incluida.
  • Lo que no se puede determinar — el apartado que casi nadie escribe y que evita que otra persona lea de más en tus conclusiones.
Parte 05Práctica

Práctica

Doce laboratorios sobre tu propia máquina, desafíos con solución razonada y la chuleta completa.

Doce laboratorios

Wireshark en una ventana, terminal en la otra. En orden. Cada uno se apoya en el anterior; todos sobre tu propio equipo.

01

Encontrar tu propia IP y tu interfaz

Fundamentos

Objetivo: no volver a capturar en la interfaz equivocada.

Preparación: ninguna. Solo una terminal.

  1. Ejecuta ip addr y localiza la interfaz con estado UP y una dirección inet.
  2. Anota interfaz, IP y máscara. Aquí: wlan0, 10.2.3.170/24.
  3. Ejecuta ip route | head -1 y anota el gateway.
  4. Ejecuta ip link y anota tu dirección MAC.
  5. Ejecuta tshark -D y comprueba que tu interfaz aparece la primera.

Qué observar: el /24 te dice el tamaño de tu red local. Todo lo que esté fuera de 10.2.3.0–10.2.3.255 saldrá por el gateway.

Comprobación: abre Wireshark y verifica que la sparkline de esa interfaz se mueve.

Error común: elegir any «por si acaso». Funciona, pero no tiene cabecera Ethernet real y luego los ejercicios de capa 2 no salen.

Qué has aprendido: los cuatro datos —interfaz, IP, máscara, gateway— que hacen falta antes de cualquier análisis.

02

Capturar un ping y leer el árbol

Fundamentos

Objetivo: leer las tres capas de un paquete que entiendes entero.

Preparación: Wireshark capturando en tu interfaz, filtro icmp puesto.

  1. En una terminal: ping -c 4 1.1.1.1.
  2. Selecciona el primer Echo (ping) request.
  3. Despliega Ethernet II y compara la MAC destino con la de tu gateway.
  4. Despliega IPv4 y localiza el TTL.
  5. Despliega ICMP y localiza tipo, identificador y número de secuencia.
  6. Pincha el campo TTL y mira qué byte se resalta abajo.
Displayicmp

Qué observar: ocho paquetes, cuatro request y cuatro reply. El identificador es igual en todos; la secuencia va 1, 2, 3, 4.

Explicación: el TTL de salida es 64 y el de vuelta menor; la diferencia son los saltos que recorrió la respuesta.

Comprobación: 64 menos el TTL de la respuesta debe dar un número razonable de saltos (entre 5 y 25 para un destino de internet).

Error común: no ver nada porque el filtro está en la barra de captura y no en la de visualización.

Qué has aprendido: a leer el árbol completo y a relacionar campo y byte.

03

Provocar y leer un intercambio ARP

Protocolos

Objetivo: ver la capa 2 en acción, por debajo de IP.

Preparación: capturando, filtro arp.

  1. Vacía la tabla: sudo ip neigh flush all.
  2. Provoca la resolución: ping -c 2 10.2.3.1 (tu gateway).
  3. Localiza el par request/reply.
  4. En el request, comprueba que el destino Ethernet es ff:ff:ff:ff:ff:ff.
  5. En el reply, anota la MAC del gateway.
  6. Contrasta con ip neigh en la terminal.

Qué observar: el request va en broadcast y el reply en unicast. En el request, el campo «Target MAC» está a ceros: es lo que se pregunta.

Comprobación: la MAC del reply y la de ip neigh deben coincidir.

Error común: esperar ARP para 1.1.1.1. No existe: para salir de la red todo va al gateway.

Qué has aprendido: cómo se resuelve IP→MAC, y cuál es la MAC de tu gateway — el dato base del laboratorio 12.

04

Observar una resolución DNS completa

Protocolos

Objetivo: emparejar consulta y respuesta y leer los registros.

Preparación: capturando, filtro dns.

  1. Ejecuta dig +short archlinux.org.
  2. Selecciona la consulta y anota el Transaction ID.
  3. Selecciona la respuesta y comprueba que el ID coincide.
  4. Despliega Answers y anota las IP devueltas.
  5. Busca el campo [Time: …] que Wireshark añade a la respuesta.
  6. Repite con dig AAAA archlinux.org y compara.
Displaydns

Qué observar: el nombre viaja en claro. El ID es lo único que empareja pregunta y respuesta, porque UDP no tiene conexión.

Comprobación: las IP de Answers deben ser las mismas que imprime dig +short.

Error común: no ver nada porque el sistema usa DNS sobre TLS o sobre HTTPS. Si es tu caso, dig a un resolver concreto: dig @10.2.3.1 archlinux.org.

Qué has aprendido: que DNS delata a dónde va un equipo aunque el resto vaya cifrado.

05

Reconstruir un handshake TCP

Protocolos

Objetivo: identificar los tres paquetes de apertura y su aritmética.

Preparación: capturando, sin filtro.

  1. Ejecuta curl -s -o /dev/null http://neverssl.com.
  2. Aplica tcp.flags.syn == 1 && tcp.flags.ack == 0 y localiza el SYN.
  3. Clic derecho sobre él → Conversation Filter → TCP.
  4. Cuenta los paquetes e identifica: SYN, SYN-ACK, ACK, petición, respuesta, cierre.
  5. En cada uno, despliega Flags y anota cuáles están activos.
  6. Anota Seq y Ack de los tres primeros.
Displaytcp.flags.syn == 1 && tcp.flags.ack == 0

Qué observar: con números relativos, SYN lleva Seq=0; SYN-ACK lleva Seq=0 y Ack=1; el ACK lleva Ack=1. El 0 lo consumió el SYN.

Comprobación: si sumas Seq + Len de un segmento con datos, obtienes el Ack con que responde el otro lado.

Error común: buscar el handshake en HTTPS y perderse entre los paquetes de TLS. Empieza por HTTP, que es más corto.

Qué has aprendido: a leer el estado de una conexión TCP a partir de sus flags y sus números.

06

Analizar un handshake TLS

Protocolos

Objetivo: ver qué revela HTTPS aunque el contenido esté cifrado.

Preparación: capturando, filtro tls.

  1. Ejecuta curl -s -o /dev/null https://archlinux.org.
  2. Localiza el Client Hello (tls.handshake.type == 1).
  3. Despliega hasta las extensiones y encuentra server_name.
  4. Añade tls.handshake.extensions_server_name como columna.
  5. Localiza el Server Hello y anota la versión y el cipher suite.
  6. Intenta un Follow TCP Stream y comprueba que el contenido es ilegible.
Displaytls.handshake.type == 1

Qué observar: el SNI está en claro. Con TLS 1.3 probablemente no veas certificados: van cifrados.

Comprobación: la columna SNI debe mostrar archlinux.org exactamente en el Client Hello y estar vacía en el resto.

Error común: concluir que «Wireshark no ve HTTPS». Ve bastante: el destino, el tamaño y el ritmo. No ve el contenido.

Qué has aprendido: a distinguir metadatos de contenido — la base de todo el análisis de tráfico cifrado.

07

Follow TCP Stream sobre HTTP

Intermedio

Objetivo: dejar de mirar paquetes y leer la conversación.

Preparación: la captura del laboratorio 5, con la petición a neverssl.com.

  1. Clic derecho en cualquier paquete de esa conexión → Follow → TCP Stream.
  2. Identifica en la ventana qué parte enviaste tú y cuál el servidor: van en colores distintos.
  3. Localiza la línea GET / HTTP/1.1 y las cabeceras Host y User-Agent.
  4. Cambia el desplegable de dirección a solo cliente → servidor.
  5. Cambia Show data as a HEX Dump y compara.
  6. Cierra y observa el filtro que Wireshark ha dejado puesto: tcp.stream eq N.

Qué observar: no hace falta ninguna herramienta especial para leer HTTP. Eso es lo que significa que no esté cifrado.

Comprobación: cambia el número de tcp.stream y verás otra conversación distinta de la captura.

Error común: usar Follow sobre TLS y concluir que está roto. El contenido cifrado se ve como basura binaria; es lo esperado.

Qué has aprendido: a reensamblar un diálogo completo y a moverte por la captura con tcp.stream.

08

Inventariar los endpoints principales

Intermedio

Objetivo: pasar del paquete al panorama con Statistics.

Preparación: captura de 2–3 minutos de navegación normal.

  1. Abre Statistics → Capture File Properties y comprueba que no hay paquetes descartados.
  2. Abre Statistics → Protocol Hierarchy y anota los tres protocolos con más bytes.
  3. Abre Statistics → Endpoints → IPv4 y ordena por bytes. Anota los cinco primeros.
  4. Abre Statistics → Conversations → TCP y ordena por bytes.
  5. Añade la columna SNI y anota los dominios que aparecen.
  6. Guarda todo esto: es tu primera línea base.

Qué observar: unos pocos destinos concentran casi todo el tráfico, y hay una cola larga de conexiones pequeñas. Esa forma es la normal.

Comprobación: los bytes de Protocol Hierarchy deben cuadrar aproximadamente con el tamaño del fichero.

Error común: olvidar Limit to display filter y no entender por qué los números no coinciden con lo que se ve en pantalla.

Qué has aprendido: el recorrido de Statistics que abre cualquier investigación, y tu primera referencia de normalidad.

09

Encontrar y explicar retransmisiones

Intermedio

Objetivo: diagnosticar sin saltar a conclusiones.

Preparación: una captura larga de wifi, mejor si la haces alejándote del router mientras descargas algo.

  1. Aplica tcp.analysis.flags y anota cuántos paquetes quedan.
  2. Abre Analyze → Expert Information y mira el reparto por severidad.
  3. Calcula el porcentaje: paquetes con anomalía sobre el total. Ese número es tu línea base de wifi.
  4. Aplica tcp.analysis.retransmission y comprueba si se concentran en una conversación o están repartidas.
  5. Comprueba en Capture File Properties si hubo descartes en la captura.
  6. Superpón en I/O Graphs el tráfico total y las retransmisiones.
Displaytcp.analysis.flags

Qué observar: si las retransmisiones suben cuando sube el tráfico, es congestión. Si están repartidas y son pocas, es el wifi comportándose como el wifi.

Comprobación: repite la captura pegado al router. El porcentaje debe bajar de forma apreciable.

Error común: concluir que la red está mal sin comprobar antes si fue tu propia captura la que perdió paquetes.

Qué has aprendido: que una anomalía necesita una línea base antes de significar algo.

10

Buscar tráfico llamativo en tu propia captura

Ciberseguridad

Objetivo: aplicar el checklist defensivo sobre datos reales y tuyos.

Preparación: una captura de 10–15 minutos de tu equipo con actividad normal. Guárdala en .pcapng.

  1. Lista los dominios consultados y ordénalos por frecuencia con tshark.
  2. Aplica dns.flags.rcode == 3 y cuenta los NXDOMAIN.
  3. Aplica dns.qry.name.len > 50 y mira si hay nombres largos.
  4. Busca conexiones de salida: ip.src == 10.2.3.0/24 && !(ip.dst == 10.2.3.0/24).
  5. En Conversations, ordena por bytes enviados y busca asimetrías hacia arriba.
  6. Para cada destino que no reconozcas, busca el SNI o el DNS que lo resolvió.
  7. Escribe, para cada uno, la explicación benigna que encuentres.

Qué observar: vas a encontrar muchos destinos que no reconoces, y casi todos tendrán explicación: CDN, telemetría, actualizaciones, servicios del sistema.

Explicación: ese es exactamente el punto del ejercicio. Aprender a explicar lo desconocido es más útil que aprender a alarmarse.

Comprobación: deberías poder justificar el 90 % de los destinos. El resto es tu lista de pendientes.

Error común: dar por sospechoso todo lo que no se reconoce.

Qué has aprendido: que la mayor parte del trabajo defensivo consiste en descartar, no en encontrar.

11

Detectar un patrón periódico

Ciberseguridad

Objetivo: medir periodicidad con datos que generas tú.

Preparación: vas a fabricar tu propio patrón periódico para tener un caso conocido. En una terminal, mientras capturas:

bash
$ while true; do curl -s -o /dev/null https://example.com; sleep 30; done

Déjalo cinco minutos y detén la captura con Ctrl+C.

  1. Filtra las aperturas hacia ese destino: tls.handshake.type == 1 && tls.handshake.extensions_server_name contains "example".
  2. Cambia View → Time Display Format a Seconds Since Previous Displayed Packet.
  3. Lee la columna Time: deberían ser todos cercanos a 30.
  4. Abre Statistics → I/O Graphs, pon intervalo de 1 s y una línea con ese filtro.
  5. Compara la forma con la de tu navegación normal en el mismo gráfico.
  6. Repite el cálculo de intervalos con la receta de tshark de la sección de beaconing.

Qué observar: el peine regular frente a las ráfagas irregulares de la navegación humana. Esa diferencia visual es la señal.

Comprobación: los intervalos deben agruparse en torno a 30 s con muy poca dispersión.

Error común: concluir que todo lo periódico es malicioso. Acabas de generar tú un patrón perfectamente periódico y perfectamente inocente.

Qué has aprendido: a medir periodicidad, y por qué la periodicidad sola no basta.

12

Redactar un informe de incidente

Ciberseguridad

Objetivo: convertir observaciones en un documento revisable.

Preparación: la captura del laboratorio 11, que contiene un patrón periódico conocido, provocado por ti.

  1. Copia la plantilla de la sección «Mini informe de incidente».
  2. Rellena los datos objetivos: fechas, IP, puerto, protocolo, SNI, bytes en ambos sentidos.
  3. Calcula el hash de la captura: sha256sum captura.pcapng.
  4. Anota los números de trama concretos que sostienen cada observación.
  5. En «Indicadores observados» escribe solo hechos, sin interpretación.
  6. En «Hipótesis» escribe tu explicación — que aquí conoces: el bucle que lanzaste.
  7. Rellena «Lo que esta captura NO permite determinar». Sé estricto.
  8. Dale el informe a otra persona con la captura y comprueba si llega a lo mismo.

Qué observar: el ejercicio real es el último apartado. Con la captura delante, no puedes saber qué proceso lo generó ni qué contenía la conexión.

Comprobación: si alguien puede reproducir tus hechos abriendo la captura, el informe sirve. Si tiene que fiarse de tu palabra, no.

Error común: mezclar evidencia e hipótesis en el mismo párrafo.

Qué has aprendido: a documentar de forma que otro pueda revisarte — la parte del análisis que más importa cuando hay consecuencias de por medio.

Desafíos

Preguntas sin respuesta inmediata. Intenta resolverlas antes de desplegar la solución.

Trabaja sobre una captura tuya de navegación normal, de unos minutos. Cada desafío tiene primero la misión, luego unas pistas, y solo después la solución razonada.

D1

Reconstruir una visita web completa

Intermedio

Misión: elige un dominio de tu captura y reconstruye toda la secuencia que llevó a conectar con él.

Debes poder rellenar esta cadena con datos concretos de tu captura:

cadena a reconstruir
DNS       consulta de ___________  →  responde ___________
   ↓
TCP       SYN a ___________:443   (trama ____)
   ↓
TLS       Client Hello, SNI = ___________  (trama ____)
   ↓
Datos     ____ bytes intercambiados en ____ segundos
Ver pistas
  • Empieza por el final: pon tls.handshake.extensions_server_name como columna y elige un dominio.
  • De ahí sacas la IP del servidor. Ahora busca hacia atrás en el tiempo.
  • Para encontrar el DNS que resolvió esa IP, el filtro es dns.a == esa.ip.
  • Para el handshake TCP, filtra por tcp.stream del Client Hello.
  • Los bytes y la duración están en Statistics → Conversations.
Ver solución razonada

El orden de trabajo correcto es hacia atrás, y esa es la lección del ejercicio. En una investigación real casi nunca empiezas por el principio: empiezas por el indicador que te llamó la atención —una IP, un dominio— y reconstruyes cómo se llegó hasta ahí.

  1. SNI → IP. El Client Hello te da nombre e IP a la vez. Es el punto de partida más rico de una captura moderna.
  2. IP → DNS. dns.a == 93.184.216.34 localiza la respuesta DNS que devolvió esa dirección. Si no aparece ninguna, es un dato en sí mismo: el equipo llegó a esa IP sin resolverla en esta captura (la tenía en caché, la llevaba escrita, o usó DoH).
  3. DNS → consulta. El Transaction ID te lleva a la pregunta, y con ella al momento exacto en que empezó todo.
  4. TCP. El tcp.stream del Client Hello te da la conexión entera: SYN, SYN-ACK, ACK, handshake TLS, datos, cierre.
  5. Volumen y tiempo. Conversations, con Limit to display filter marcado.

Si en el paso 2 no encuentras DNS, no des por hecho que es sospechoso: comprueba primero si tu navegador usa DNS sobre HTTPS, en cuyo caso las consultas van cifradas dentro de otra conexión y no aparecerán nunca como dns.

D2

Quién inició, quién respondió

Fundamentos

Misión: dada una conversación TCP cualquiera de tu captura, responde sin mirar los puertos conocidos.

  • ¿Qué equipo inició la conexión?
  • ¿Qué puerto usó cada extremo?
  • ¿Se completó el handshake?
  • ¿Cómo terminó: FIN o RST?
  • ¿Hubo retransmisiones?
  • ¿Cuántos bytes fue en cada sentido?
Ver pistas
  • El que inicia es el que envía el SYN sin ACK. Ese único paquete responde a las dos primeras preguntas.
  • El puerto alto y aleatorio es el del cliente; el bajo y estable, el del servicio.
  • tcp.completeness resume el estado de la conexión.
  • Para el final, mira los últimos paquetes del tcp.stream.
Ver solución razonada

Quién inició: el emisor del SYN sin ACK. Es el único paquete de una conexión con esa combinación, y por eso tcp.flags.syn == 1 && tcp.flags.ack == 0 es el filtro más usado de todo Wireshark.

Los puertos: el cliente elige uno efímero (en Linux, entre 32768 y 60999); el servidor escucha en uno fijo. Si ves 51234 → 443, la dirección está clara sin necesidad de saber que 443 es HTTPS.

Si se completó: tienen que estar los tres paquetes. Un SYN al que responde un RST es un puerto cerrado; un SYN sin ninguna respuesta es un puerto filtrado o un servidor caído. tcp.completeness lo resume en un valor.

Cómo terminó: FIN por ambos lados es un cierre limpio. Un RST puede ser normal (la aplicación cerró de golpe) o significar que alguien intervino: revisa el TTL del RST y compáralo con el del resto de paquetes de ese extremo.

Retransmisiones: añade && tcp.analysis.flags al filtro de la conversación.

Bytes: Statistics → Conversations, columnas A→B y B→A. La asimetría te dice si el equipo descargaba o subía.

D3

El equipo que no debería estar hablando

Ciberseguridad

Misión: en tu captura, encuentra el equipo con más destinos externos distintos y explica por qué.

Ver pistas
  • Statistics → Endpoints → IPv4, y ordena por la columna de número de conexiones o de paquetes.
  • Filtra la salida de tu red y vuelve a mirar con Limit to display filter.
  • Para cada destino, busca el SNI o el DNS asociado.
  • Pregúntate qué software del equipo explicaría esa cantidad de destinos.
Ver solución razonada

En una red doméstica el equipo con más destinos externos suele ser aquel en el que hay un navegador abierto: una sola página web moderna contacta con decenas de dominios —CDN, analítica, fuentes tipográficas, publicidad, APIs—. Eso, que parece alarmante, es simplemente cómo funciona la web hoy.

Lo que convierte este dato en interesante es el contraste: un servidor, una impresora o una cámara que hablan con decenas de destinos externos no tienen la misma explicación. La pregunta correcta no es «¿cuántos destinos?», sino «¿cuántos destinos para lo que es este equipo?».

Y el método para responderla es el mismo de siempre: mirar el SNI de cada destino, buscar la consulta DNS que lo resolvió, y comprobar si encaja con el software que debería estar corriendo ahí. Cuando no encaje y no encuentres explicación, tienes un hallazgo — y entonces se aplica el flujo de diez preguntas y la plantilla de informe.

Errores comunes

Los once tropiezos que se repiten, y cómo evitarlos.

Errores frecuentes al usar Wireshark y su solución
ErrorQué pasaSolución
Capturar en la interfaz equivocadaLa captura sale vacía o llena de tráfico que no es el tuyoip addr primero; fíjate en la sparkline
Confundir capture filter y display filterLa sintaxis se rechaza y parece que «el filtro no funciona»BPF abajo en la pantalla de inicio; Wireshark en la barra verde de arriba
Pensar que todo lo rojo es maloAlarma por retransmisiones normales de wifiLos colores son reglas configurables; compara con tu línea base
Retransmisión = ataqueSe concluye compromiso donde hay congestiónEs TCP corrigiendo errores. Mira si afecta a una conversación o a todas
Analizar sin contextoTodo parece sospechoso porque no hay referenciaConstruye la línea base antes de necesitarla
Olvidar los timestampsNo se puede correlacionar con registros de otros sistemasView → Time Display Format → hora absoluta; anota la zona horaria
Ignorar el DNSSe investigan IP sueltas sin saber a qué nombre correspondenEl DNS de la propia captura te da los nombres sin consultar fuera
Esperar leer HTTPSFrustración con Follow Stream sobre TLSVa cifrado. Analiza metadatos: SNI, tamaños, tiempos
Ejecutar Wireshark como rootSe expone todo el equipo a un fallo en un disectorGrupo wireshark y dumpcap con capabilities
Capturar demasiadoFicheros enormes, paquetes descartados, y un problema de privacidadCapture filter, límites de tamaño o de tiempo, ficheros en anillo
Concluir con un solo paqueteSe construye una teoría sobre una coincidenciaUn indicador no es evidencia. Busca varios independientes

Chuleta de display filters

Los que se usan a diario, por protocolo. Todos verificados contra el motor de filtros de Wireshark 4.7.

Los de uso diario

Display filters de uso diario y qué muestra cada uno
FiltroQué muestra
ip.addr == 10.2.3.1Todo lo que va o viene de esa IP
ip.src == 10.2.3.170Solo lo que sale de tu equipo
tcp.port == 443Tráfico HTTPS por puerto
dns || icmp || arpVarios protocolos a la vez
!(arp || dns)Todo menos el ruido de fondo
http.requestSolo peticiones HTTP, sin respuestas
http.response.code >= 400Errores HTTP
tcp.flags.reset == 1Conexiones cortadas de golpe
tcp.analysis.retransmissionPaquetes reenviados: pérdida en la red
tcp.stream eq 3Una conversación TCP concreta
frame contains "password"Busca una cadena en el contenido crudo
frame.len > 1400Paquetes grandes, cerca del MTU

Ethernet y ARP

Filtros de Ethernet y ARP
FiltroQué muestra
eth.addr == b8:1e:a4:5a:ac:8dTodo lo de esa tarjeta, entre y salga
eth.src · eth.dstDireccional: solo emitido o solo recibido
eth.dst == ff:ff:ff:ff:ff:ffBroadcast del segmento
eth.ig == 1Broadcast y multicast juntos
eth.type == 0x0806Tramas ARP por EtherType
arp.opcode == 1 · 2Preguntas · respuestas
arp.src.proto_ipv4 == 10.2.3.1Quién dice ser el gateway
arp.duplicate-address-detectedUna IP con dos MAC distintas

IPv4 e IPv6

Filtros de IPv4 e IPv6
FiltroQué muestra
ip.addr == 10.2.3.0/24Una red entera en notación CIDR
ip.ttl < 20Paquetes que han dado muchos saltos
ip.ttl in {1 .. 5}Rango de TTL: la firma de un traceroute
ip.flags.mf == 1 || ip.frag_offset > 0Paquetes fragmentados
ip.proto == 6Por número de protocolo: 1 ICMP, 6 TCP, 17 UDP
ip.len > 1400Paquetes IP grandes
ipv6Todo el tráfico IPv6
ipv6.hlim < 20El equivalente al TTL en IPv6
icmpv6Descubrimiento de vecinos y anuncios de router

ICMP

Filtros de ICMP
FiltroQué muestra
icmp.type == 8 · 0Echo request · echo reply
icmp.type == 3Destino inalcanzable
icmp.type == 3 && icmp.code == 13Bloqueado por un cortafuegos que avisa
icmp.type == 11TTL agotado: la base de traceroute
icmp.ident == 0xc977Una ejecución concreta de ping

TCP y UDP

Filtros de TCP y UDP
FiltroQué muestra
tcp.flags.syn == 1 && tcp.flags.ack == 0Aperturas de conexión. El filtro más usado
tcp.flags.fin == 1Cierres ordenados
tcp.port in {80, 443, 8080}Conjunto de puertos. Con comas
tcp.len > 0Solo segmentos con datos, sin ACK vacíos
tcp.analysis.flagsTodo lo que Wireshark marca como anómalo
tcp.analysis.duplicate_ack«Me falta un trozo»
tcp.analysis.zero_windowReceptor saturado
tcp.analysis.lost_segmentHueco en la numeración
tcp.completeness < 7Conexiones que no llegaron a completarse
tcp.time_delta > 1Pausas dentro de una misma conexión
tcp.window_size < 1000Ventana pequeña: posible cuello de botella
udp.port == 53DNS por UDP
udp.length > 512Datagramas UDP grandes

DNS y DHCP

Filtros de DNS y DHCP
FiltroQué muestra
dns.flags.response == 0 · 1Consultas · respuestas
dns.qry.name contains "ejemplo"Consultas de un dominio concreto
dns.qry.type == 1 · 28 · 5 · 15 · 16 · 12A · AAAA · CNAME · MX · TXT · PTR
dns.flags.rcode == 3NXDOMAIN: el nombre no existe
dns.qry.name.len > 50Nombres anormalmente largos
dns.time > 0.5Resoluciones lentas
dns.a == 203.0.113.9Qué nombre resolvió a esa IP
dns.count.answers == 0Respuestas sin registros
dhcpTodo DHCP (era bootp antes de la 2.6)
dhcp.option.dhcp == 1 · 2 · 3 · 5Discover · Offer · Request · ACK
dhcp.option.hostnameEl nombre que se da cada equipo

HTTP y TLS

Filtros de HTTP y TLS
FiltroQué muestra
http.request.method == "GET"Por método. Las comillas son obligatorias
http.host contains "ejemplo"Por sitio de destino
http.user_agentPaquetes que declaran agente de usuario
http.user_agent matches "(?i)curl|wget"Agentes que no son navegadores
http.authorizationAutenticación HTTP: credenciales expuestas
http.cookieCookies viajando en claro
http.file_dataCuerpo de la petición o la respuesta
tls.handshake.type == 1 · 2 · 11Client Hello · Server Hello · Certificate
tls.handshake.extensions_server_nameEl SNI: el destino real de cada conexión
tls.alert_messageHandshakes TLS fallidos
tls.record.content_type == 23Datos de aplicación cifrados

Análisis y ciberseguridad

Filtros orientados a análisis defensivo
FiltroPara qué
ip.src == 10.2.3.0/24 && !(ip.dst == 10.2.3.0/24)Todo lo que abandona tu red
dns && !(ip.dst == 10.2.3.1)Consultas a un resolver que no es el tuyo
tcp.flags.syn == 1 && tcp.flags.ack == 0Indicio de escaneo, junto con Conversations
tcp.flags.reset == 1 && tcp.flags.ack == 1Puertos cerrados que respondieron
ftp || telnet || http.authorizationAuditar protocolos que exponen credenciales
ftp.request.command == "PASS"Envío de contraseña por FTP
frame.len > 1400 && ip.dst != 10.2.3.0/24Paquetes grandes hacia fuera
http.host matches "^[0-9.]+$"Peticiones a IP directa, sin nombre

Operadores: == != > < para comparar; && o and, || o or, ! o not para combinar; contains para subcadenas y matches para expresiones regulares.

Y el atajo que hace innecesario memorizar nada: clic derecho sobre cualquier campo del árbol → Apply as Filter → Selected. Wireshark escribe el filtro correcto y así es como se aprenden los nombres de los campos — trabajando, no estudiando una lista.

← Volver a la biblioteca Tutoriales Lucio · CODLYX