Se você já conectou o Wireshark a um segmento do barramento de processo de uma subestação digital real, conhece a cena: pouco depois de iniciar a captura, o Wireshark trava — é um problema bem conhecido. O problema é especialmente sério em subestações com tráfego Sampled Values.

A razão é prosaica: um único fluxo Sampled Values a 4000 quadros por segundo (80 amostras por ciclo, 50 Hz) já gera uma carga considerável. Em um segmento real do barramento de processo há dezenas desses fluxos — mais GOOSE, mais PTP, mais tráfego broadcast e de serviço. Não é que o Wireshark "não consiga" analisar — ele simplesmente não consegue gravar e exibir todos esses pacotes em tempo real.

A wiki do Wireshark dá uma recomendação direta sobre isso:

Se você não está interessado em todos os pacotes, um filtro de captura que seleciona apenas os pacotes de interesse pode reduzir o tempo total de processamento, pois os pacotes podem ser descartados pelo filtro de captura antes mesmo de serem gravados em arquivo — e, em sistemas com filtragem de captura no kernel, são descartados antes de serem copiados do kernel para o Wireshark.

A ideia-chave: o filtro de captura descarta pacotes antes de chegarem ao Wireshark. Diferentemente do filtro de exibição, que trabalha sobre tráfego já gravado. Então, se você sabe de antemão o que está procurando, o filtro de captura é seu melhor amigo.

Filtro de captura vs Filtro de exibição: não confunda!

Há dois tipos de filtros no Wireshark que são frequentemente confundidos. A diferença é fundamental:

Parâmetro Capture Filter Display Filter
Quando é aplicado Antes da gravação do pacote Depois da gravação
Pode ser alterado em tempo real Não (exige parar a captura) Sim
Sintaxe BPF (como em tcpdump) Sintaxe própria do Wireshark
Impacto no desempenho Reduz carga em disco e memória Nenhum sobre a captura
Efeito sobre os dados Descarta permanentemente Apenas oculta, não apaga

O filtro de captura decide o que entra na sua "coleção" de dados; o filtro de exibição decide o que você vai analisar nessa coleção já reunida.

Para tarefas do tipo "vamos ver o que tem na rede" em um segmento sobrecarregado, é praticamente impossível trabalhar sem filtro de captura.

Como aplicar um filtro de captura no Wireshark

Há três formas padrão:

Forma 1. Tela inicial. Na tela inicial, antes de escolher a interface, digite a expressão do filtro de captura. Capture Filter Start Screen.png

Forma 2. Menu Capture. Capture → Options → campo Capture Filter for selected interfaces ao lado da interface escolhida. Capture Options Menu.png

Existem outras formas, mas essas duas bastam para começar :)

Se houver erro de sintaxe, o Wireshark destaca o campo em vermelho e não permite iniciar a captura. Verde significa que o filtro é sintaticamente válido — mas isso não garante que ele faça o que você quis. Verificar continua sendo necessário.

Algumas peculiaridades do BPF a se lembrar

As expressões dos filtros de captura são escritas em BPF — a mesma linguagem usada pelo tcpdump. A sintaxe é compacta, mas no tráfego de subestação há alguns detalhes não óbvios.

VLAN quebra os deslocamentos

A palavra-chave vlan em um filtro BPF não é um simples predicado "tem VLAN tag". É uma diretiva que desloca todos os offsets subsequentes do filtro como se o VLAN tag não estivesse presente. Ou seja, ether proto 0x88b8 antes da diretiva vlan captura quadros sem tag, e depois — quadros com tag.

Situação clássica: você precisa pegar todo o tráfego GOOSE, e parte dos quadros tem tag VLAN, parte não. A abordagem intuitiva

(vlan and ether proto 0x88b8) or ether proto 0x88b8

não funciona como esperado. O tráfego não-tagueado não passa, porque depois do vlan os offsets já estão deslocados, e o segundo ramo procura o EtherType no lugar errado.

A ordem correta é: caso sem tag primeiro, com tag depois:

ether proto 0x88b8 or (vlan and ether proto 0x88b8)

Regra geral: todas as expressões sem VLAN devem vir antes da primeira ocorrência de vlan no filtro.

Endereço MAC parcial

ether host xx:xx:xx:xx:xx:xx exige o MAC completo. Mas se você precisa, por exemplo, capturar tráfego de todos os dispositivos de um fabricante com OUI 00:0C:22, é preciso escrever um filtro por offset de byte:

(ether[0:4] & 0xffffff00 = 0x000c2200) or (ether[6:4] & 0xffffff00 = 0x000c2200)

Aqui ether[0:4] são quatro bytes a partir do offset 0 (campo MAC de destino), ether[6:4] são quatro bytes a partir do offset 6 (campo MAC de origem). O operador : no BPF aceita apenas tamanhos 1, 2 ou 4 — três bytes não podem ser selecionados — por isso pegamos quatro e zeramos o quarto extra com a máscara 0xffffff00.

Alternativamente, pode-se comparar byte a byte — mais longo, mas mais legível:

(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

Agora ao que interessa. Abaixo — receitas prontas para tarefas típicas de subestação digital.

GOOSE

Todo GOOSE (sem VLAN):

ether proto 0x88b8

Todo GOOSE incluindo quadros com VLAN:

ether proto 0x88b8 or (vlan and ether proto 0x88b8)

GOOSE de um IED específico (filtro por MAC de origem):

ether proto 0x88b8 and ether src 00:0c:22:12:34:56

GOOSE para um endereço multicast específico:

ether proto 0x88b8 and ether dst 01:0c:cd:01:00:01

GOOSE de todos os dispositivos de um fabricante (por OUI, ex.: 00:0C:22):

ether proto 0x88b8 and (ether[6:4] & 0xffffff00 = 0x000c2200)

GOOSE com APPID específico (ex.: 0x1000). APPID são os dois bytes logo após o EtherType, no offset 14–15 num quadro sem tag:

ether proto 0x88b8 and ether[14:2] = 0x1000

Com VLAN:

(ether proto 0x88b8 and ether[14:2] = 0x1000) or (vlan and ether proto 0x88b8 and ether[14:2] = 0x1000)

Faixa de APPID GOOSE (ex.: de 0x1000 a 0x10FF):

ether proto 0x88b8 and ether[14:2] & 0xff00 = 0x1000

Faixa de destino multicast GOOSE:

ether proto 0x88b8 and (ether[0:4] & 0xffffff00 = 0x010ccd00) and (ether[4:2] & 0xff00 = 0x0100)

Sampled Values

Todos os SV (sem VLAN):

ether proto 0x88ba

Todos os SV incluindo VLAN:

ether proto 0x88ba or (vlan and ether proto 0x88ba)

SV de uma MU específica (por MAC de origem):

ether proto 0x88ba and ether src 00:0c:22:aa:bb:cc

SV para um endereço multicast específico:

ether proto 0x88ba and ether dst 01:0c:cd:04:00:01

SV com APPID específico (ex.: 0x4000):

ether proto 0x88ba and ether[14:2] = 0x4000

SV de todas as MUs de um fabricante (por OUI):

ether proto 0x88ba and (ether[6:4] & 0xffffff00 = 0x000c2200)

SV da faixa 01:0C:CD:04:xx:xx:

ether proto 0x88ba and (ether[0:4] & 0xffffff00 = 0x010ccd00) and (ether[4:2] & 0xff00 = 0x0400)

Sobre filtragem por goID e svID

Aqui vem a má notícia: não dá para filtrar de forma confiável GOOSE por goID ou SV por svID usando filtro de captura. Esses campos vivem dentro do APDU codificado em BER, e o offset deles a partir do início do quadro depende do tamanho dos campos anteriores (gocbRef / cabeçalho svID etc.). Já o BPF só trabalha com offsets fixos.

O que dá para fazer na prática:

  1. Usar o APPID como proxy. Em um publisher bem configurado, o APPID é único e corresponde a um único gocbRef / svCB. Filtrar por APPID é a forma mais confiável de pegar um fluxo específico no nível de captura.
  2. Usar o MAC de destino multicast. Também recomenda-se mantê-lo único por fluxo num sistema bem projetado e comissionado.
  3. Capturar primeiro todo o tráfego de um tipo, depois filtrar com filtro de exibição. Se o fluxo não for muito grande, funciona. Para SV num barramento de processo carregado — não é boa ideia.
  4. Escrever um filtro por offset de byte para o caso específico. Capture alguns quadros do fluxo desejado sem filtro, veja em qual offset está a string de interesse, e escreva um filtro do tipo ether[N:4] = 0xXXXXXXXX. Funciona, mas é extremamente frágil — qualquer mudança nos campos APDU anteriores desloca o offset e o filtro para de pegar.

Em 90 % dos casos, a combinação "EtherType + APPID" ou "EtherType + dst MAC" resolve.

Filtros de exclusão — quando é mais fácil cortar o ruído

Outro truque útil é capturar tudo exceto um ou dois fluxos especialmente barulhentos. Por exemplo, pegar todo o barramento de processo sem dois fluxos SV específicos, para o Wireshark não engasgar:

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)

Ou, ao contrário, capturar GOOSE e PTP, mas não SV:

ether proto 0x88b8 or ether proto 0x88f7

Para casos do tipo "tudo exceto comunicações MMS com um servidor específico":

not (tcp port 102 and host 192.168.1.10)

Algumas dicas práticas para finalizar

  1. Comece sempre com o filtro de captura ao trabalhar no barramento de processo. A tentativa de "ver o que tem e descobrir depois" termina com o Wireshark travado.
  2. Tenha o cheatsheet por perto. BPF não é uma linguagem que se aprende de primeira. Uma tabela com expressões prontas economiza dezenas de minutos a cada depuração.
  3. Para diagnosticar problemas reais de GOOSE/SV, a combinação "filtro de captura por EtherType + filtro de exibição" geralmente funciona melhor. Um filtro grosso na captura corta 95 % do ruído; um filtro de exibição preciso permite trocar rapidamente entre fluxos no traço já coletado.

BPF não é a linguagem mais amigável, mas dominar uma dúzia de construções deste material já cobre praticamente todas as tarefas de captura de tráfego IEC 61850 — e ainda dá para parar de assistir o Wireshark lutar pela vida e morrer no barramento de processo.