Si alguna vez has conectado Wireshark a un segmento del bus de proceso de una subestación digital real, conoces la escena: poco después de iniciar la captura, Wireshark se congela — es un problema conocido. Se nota especialmente en subestaciones con tráfico Sampled Values.
La razón es prosaica: un único flujo Sampled Values a 4000 tramas por segundo (80 muestras por ciclo, 50 Hz) ya genera una carga considerable. En un segmento real del bus de proceso hay decenas de esos flujos — más GOOSE, más PTP, más tráfico broadcast y de servicio. No es que Wireshark "no pueda" con el análisis — simplemente no alcanza a registrar y mostrar todos esos paquetes en tiempo real.
La wiki de Wireshark tiene una recomendación directa al respecto:
Si no le interesan todos los paquetes, un filtro de captura que seleccione solo los paquetes de interés puede reducir el tiempo total de procesamiento, ya que los paquetes pueden ser descartados por el filtro de captura antes de ser escritos en el archivo — y, en sistemas con filtrado de captura en el kernel, son descartados antes de copiarse desde el kernel a Wireshark.
La idea clave: el filtro de captura descarta paquetes antes de que lleguen a Wireshark. A diferencia del filtro de visualización, que trabaja sobre tráfico ya registrado. Así que si sabes de antemano qué buscas, el filtro de captura es tu mejor amigo.
Filtro de captura vs Filtro de visualización: ¡no los confundas!
En Wireshark hay dos tipos de filtros que se confunden a menudo. La diferencia es esencial:
| Parámetro | Capture Filter | Display Filter |
|---|---|---|
| Cuándo se aplica | Antes de escribir el paquete | Después de escribir el paquete |
| Se puede cambiar al vuelo | No (requiere detener la captura) | Sí, en tiempo real |
| Sintaxis | BPF (como en tcpdump) |
Sintaxis propia de Wireshark |
| Impacto en rendimiento | Reduce carga en disco y memoria | Ninguno sobre la captura |
| Efecto sobre los datos | Descarta permanentemente | Solo oculta, no borra |
El filtro de captura decide qué entra en tu "colección" de datos; el filtro de visualización decide qué examinarás dentro de la colección ya reunida.
Para tareas tipo "veamos qué hay en la red" en un segmento cargado, es prácticamente imposible trabajar sin filtro de captura.
Cómo aplicar un filtro de captura en Wireshark
Hay tres formas estándar:
Forma 1. Pantalla de inicio.
En la pantalla de inicio, antes de elegir interfaz, escribe la expresión del filtro de captura.

Forma 2. Menú Capture.
Capture → Options → campo Capture Filter for selected interfaces junto a la interfaz elegida.

Hay otras formas, pero estas dos bastan para empezar :)
Si hay un error de sintaxis, Wireshark resalta el campo en rojo y no permite iniciar la captura. Verde significa que el filtro es sintácticamente válido — pero no garantiza que haga lo que pretendías. Verificar sigue siendo necesario.
Algunas peculiaridades de BPF a recordar
Las expresiones de los filtros de captura se escriben en BPF — el mismo lenguaje que usa tcpdump. La sintaxis es compacta, pero en tráfico de subestación hay un par de detalles no obvios.
VLAN rompe los desplazamientos
La palabra clave vlan en un filtro BPF no es un simple predicado "hay etiqueta VLAN". Es una directiva que desplaza todos los offsets siguientes del filtro como si la etiqueta VLAN no estuviera. Es decir, ether proto 0x88b8 antes de la directiva vlan captura tramas sin etiqueta, y después — tramas etiquetadas.
Situación clásica: necesitas atrapar todo el tráfico GOOSE, y parte de las tramas viene con etiqueta VLAN y parte sin ella. La opción intuitiva
(vlan and ether proto 0x88b8) or ether proto 0x88b8
no funciona como se espera. El tráfico sin etiqueta no entra, porque tras vlan los offsets ya están desplazados, y la segunda rama busca el EtherType en el lugar incorrecto.
El orden correcto es: caso sin etiqueta primero, con etiqueta después:
ether proto 0x88b8 or (vlan and ether proto 0x88b8)
Regla general: todas las expresiones sin VLAN deben ir antes de la primera aparición de vlan en el filtro.
Dirección MAC parcial
ether host xx:xx:xx:xx:xx:xx exige la MAC completa. Pero si necesitas, por ejemplo, capturar el tráfico de todos los dispositivos de un fabricante con OUI 00:0C:22, hay que escribir un filtro por offset de byte:
(ether[0:4] & 0xffffff00 = 0x000c2200) or (ether[6:4] & 0xffffff00 = 0x000c2200)
Aquí ether[0:4] son cuatro bytes a partir del offset 0 (campo MAC de destino), ether[6:4] son cuatro bytes a partir del offset 6 (campo MAC de origen). El operador : en BPF solo acepta tamaños 1, 2 o 4 — tres bytes no se pueden seleccionar — por eso tomamos cuatro y ponemos a cero el cuarto extra con la máscara 0xffffff00.
Como alternativa, se puede comparar byte por byte — más largo, pero más claro:
(ether[0]=0x00 and ether[1]=0x0c and ether[2]=0x22) or (ether[6]=0x00 and ether[7]=0x0c and ether[8]=0x22)
Cheatsheet: filtros de captura para IEC 61850
Ahora lo importante. Abajo — recetas listas para tareas típicas de subestación digital.
GOOSE
Todo GOOSE (sin VLAN):
ether proto 0x88b8
Todo GOOSE incluyendo tramas con VLAN:
ether proto 0x88b8 or (vlan and ether proto 0x88b8)
GOOSE de un IED específico (filtro por MAC origen):
ether proto 0x88b8 and ether src 00:0c:22:12:34:56
GOOSE a una dirección multicast específica:
ether proto 0x88b8 and ether dst 01:0c:cd:01:00:01
GOOSE de todos los dispositivos de un fabricante (por OUI, ej. 00:0C:22):
ether proto 0x88b8 and (ether[6:4] & 0xffffff00 = 0x000c2200)
GOOSE con APPID específico (ej. 0x1000).
APPID son los dos bytes justo tras EtherType, en el offset 14–15 en una trama sin etiqueta:
ether proto 0x88b8 and ether[14:2] = 0x1000
Con VLAN:
(ether proto 0x88b8 and ether[14:2] = 0x1000) or (vlan and ether proto 0x88b8 and ether[14:2] = 0x1000)
Rango de APPID GOOSE (ej. de 0x1000 a 0x10FF):
ether proto 0x88b8 and ether[14:2] & 0xff00 = 0x1000
Rango de destino multicast GOOSE:
ether proto 0x88b8 and (ether[0:4] & 0xffffff00 = 0x010ccd00) and (ether[4:2] & 0xff00 = 0x0100)
Sampled Values
Todos los SV (sin VLAN):
ether proto 0x88ba
Todos los SV incluyendo VLAN:
ether proto 0x88ba or (vlan and ether proto 0x88ba)
SV de una MU específica (por MAC origen):
ether proto 0x88ba and ether src 00:0c:22:aa:bb:cc
SV a una dirección multicast específica:
ether proto 0x88ba and ether dst 01:0c:cd:04:00:01
SV con APPID específico (ej. 0x4000):
ether proto 0x88ba and ether[14:2] = 0x4000
SV de todas las MU de un fabricante (por OUI):
ether proto 0x88ba and (ether[6:4] & 0xffffff00 = 0x000c2200)
SV del rango 01:0C:CD:04:xx:xx:
ether proto 0x88ba and (ether[0:4] & 0xffffff00 = 0x010ccd00) and (ether[4:2] & 0xff00 = 0x0400)
Sobre el filtrado por goID y svID
Aquí toca una mala noticia: no se puede filtrar de forma fiable GOOSE por goID o SV por svID con un filtro de captura. Esos campos viven dentro del APDU codificado en BER, y su offset desde el inicio de la trama depende de la longitud de los campos previos (gocbRef / cabecera svID, etc.). BPF, en cambio, solo trabaja con offsets fijos.
Qué se puede hacer en la práctica:
- Usar APPID como proxy. En un publicador correctamente configurado, APPID es único y corresponde a un único
gocbRef/svCB. Filtrar por APPID es la forma más fiable de capturar un flujo específico a nivel de captura. - Usar la MAC de destino multicast. También se recomienda mantenerla única por flujo en un sistema bien diseñado y puesto en marcha.
- Primero capturar todo el tráfico de un tipo, después filtrar con filtro de visualización. Si el flujo no es demasiado grande, funciona. Para SV en un bus de proceso cargado — mala idea.
- Escribir un filtro por offset de byte para el caso concreto. Captura unas tramas del flujo objetivo sin filtro, mira en qué offset está la cadena que te interesa, y escribe un filtro del tipo
ether[N:4] = 0xXXXXXXXX. Funciona, pero es extremadamente frágil — cualquier cambio en los campos APDU anteriores desplaza el offset y el filtro deja de capturar.
En el 90 % de los casos, la combinación "EtherType + APPID" o "EtherType + dst MAC" cubre la tarea.
Filtros de exclusión — cuando es más fácil descartar el ruido
Otro truco útil es capturar todo excepto uno o dos flujos especialmente ruidosos. Por ejemplo, captar todo el bus de proceso sin dos flujos SV concretos para que Wireshark no se atragante:
not (ether proto 0x88ba and ether dst 01:0c:cd:04:00:01) and not (ether proto 0x88ba and ether dst 01:0c:cd:04:00:02)
O, al revés, captar GOOSE y PTP pero no SV:
ether proto 0x88b8 or ether proto 0x88f7
Para casos como "todo excepto comunicaciones MMS con un servidor específico":
not (tcp port 102 and host 192.168.1.10)
Algunos consejos prácticos para terminar
- Empieza siempre con un filtro de captura cuando trabajes en el bus de proceso. "Veo qué hay y luego ya pienso" termina con Wireshark colgado.
- Ten el cheatsheet a mano. BPF no es un lenguaje que se aprenda al primer intento. Una tabla con expresiones listas ahorra decenas de minutos en cada depuración.
- Para diagnosticar problemas reales de GOOSE/SV, suele funcionar mejor la combinación "filtro de captura por EtherType + filtro de visualización". Un filtro grueso en la captura corta el 95 % del ruido; un filtro de visualización preciso permite cambiar rápido entre flujos en la traza ya recogida.
BPF no es el lenguaje más amigable, pero dominar una decena de construcciones de este material basta para cubrir prácticamente todas las tareas de captura de tráfico IEC 61850 — y dejar de ver cómo Wireshark lucha por su vida y muere en el bus de proceso.