Mikrotik

Static loop no Mikrotik: rota blackhole para pool e CGNAT

Espiral roxa e laranja entre dois roteadores representando o pacote preso no static loop

O static loop é um daqueles problemas que não aparecem no dia em que a rede é montada. Tudo funciona, os clientes navegam, o BGP está estabelecido. Meses depois o link de trânsito começa a encher em horário estranho, a CPU da borda sobe e ninguém acha um cliente responsável. Muitas vezes a causa é um pacote para um endereço que ninguém usa, preso entre dois roteadores até o TTL acabar.

Este post mostra como o static loop nasce num provedor com borda e concentrador Mikrotik, como reconhecer os sintomas com traceroute e fping, e como fechar o buraco com rotas blackhole para o bloco anunciado, para os pools PPPoE e para o CGNAT. Os comandos seguem a sintaxe do RouterOS v7 conferida na documentação da MikroTik, com o equivalente em NULL0 para quem tem borda Huawei.

Resposta rápida

Todo bloco que chega até um roteador e que ele não sabe entregar por inteiro precisa de uma rota blackhole. Na prática:

  1. Na borda, crie uma rota blackhole para cada prefixo que você anuncia ou que o trânsito roteia para você, em IPv4 e IPv6.
  2. No concentrador, crie blackhole para o pool PPPoE, para o pool público do CGNAT, para a faixa 100.64 dos clientes e para o pool de prefixos delegados.
  3. Use distance=254, para que qualquer rota real ganhe da blackhole.
  4. Teste com traceroute para um endereço livre: o caminho deve parar, e não alternar entre dois saltos.

Como o static loop nasce

Pense numa borda com duas coisas na tabela: uma rota default apontando para o trânsito e rotas específicas para as partes do bloco que estão em uso. O trânsito, por sua vez, manda para a borda tudo que é do seu /24, seja por BGP, seja por uma rota estática do lado dele. Agora chega um pacote para 203.0.113.200, um endereço que não está em pool nenhum.

  1. O trânsito entrega o pacote para a borda, porque o /24 é seu.
  2. A borda procura uma rota para 203.0.113.200. Não existe rota específica, então vale a default.
  3. A default aponta para o trânsito. O pacote volta pelo mesmo link.
  4. O trânsito olha a tabela de novo e devolve para a borda.
  5. O vai e volta continua até o TTL zerar. Só aí alguém descarta o pacote e responde com ICMP Time Exceeded.

Um pacote que chega ao trânsito com TTL 50 atravessa o link umas 50 vezes antes de morrer; quem ataca pode sair com TTL 255 e passar das 200 voltas. Ou seja, cada pacote que entra para um endereço sem uso vira dezenas de pacotes no seu link de trânsito, nos dois sentidos. Quem descobre isso e manda tráfego para a faixa vazia consegue lotar o link com uma fração da banda que precisaria num ataque comum. É por isso que o static loop é tratado como risco de segurança, e não só como erro de configuração.

Diagrama: pacote para endereço sem uso indo e voltando entre trânsito e borda até o TTL acabar, e a rota blackhole na borda descartando o pacote
Sem rota para o endereço livre, a borda devolve o pacote pela default e ele vai e volta até o TTL zerar. Com a rota blackhole do bloco, o pacote morre na primeira chegada.

Cenário do laboratório

O exemplo usa uma borda Mikrotik ligada ao trânsito e um concentrador PPPoE que também faz CGNAT. É o desenho mais comum em provedor pequeno, montado como nos posts sobre PPPoE server no Mikrotik RouterOS v7 e CGNAT no Mikrotik com netmap.

ItemValorOnde fica
Bloco próprio203.0.113.0/24 e 2001:db8::/32Anunciado ao trânsito
Link de trânsito198.51.100.0/30 (trânsito .1, borda .2)Default da borda
Borda e concentrador192.0.2.0/30 (borda .1, concentrador .2)Default do concentrador
Pool PPPoE público203.0.113.0/25No concentrador
Pool público do CGNAT203.0.113.128/27No concentrador
Clientes CGNAT100.64.0.0/22No concentrador
Prefixos delegados2001:db8:a000::/40No concentrador
Sem uso203.0.113.160 a 203.0.113.255Onde o loop aparece

A tabela de rotas da borda, antes da correção, tem a default e as rotas para o que está em uso no concentrador:

/ip route
add dst-address=0.0.0.0/0 gateway=198.51.100.1
add dst-address=203.0.113.0/25 gateway=192.0.2.2
add dst-address=203.0.113.128/27 gateway=192.0.2.2

E o concentrador só conhece as próprias redes e uma default para a borda:

/ip route
add dst-address=0.0.0.0/0 gateway=192.0.2.1

Esse par parece certo e funciona para todo cliente conectado. O problema está no que sobra: o pedaço do /24 que ninguém usa, os IPs do pool PPPoE que estão livres naquele momento e as portas e endereços do CGNAT sem tradução ativa.

Os dois lugares onde o static loop aparece

Entre a borda e o trânsito

É o caso do diagrama. Qualquer endereço do bloco sem rota específica na borda volta pela default. O tráfego de fora chega pelo trânsito, então o loop acontece no link mais caro e mais visível da rede. Em IPv6 o problema é igual e costuma ser maior, porque o bloco é enorme e quase todo vazio.

Entre o concentrador e a borda

A borda manda o /25 do PPPoE para o concentrador. Se o 203.0.113.37 não está com nenhum cliente naquele momento, o concentrador não tem a rota /32 dinâmica que a sessão PPPoE cria. Ele cai na default, devolve para a borda, a borda manda de novo para o concentrador, e assim até o TTL acabar. O mesmo vale para o pool público do CGNAT: pacote para um IP ou porta sem tradução ativa não é traduzido e segue a tabela de rotas comum.

A faixa 100.64.0.0/22 tem um caso parecido no sentido contrário. Um cliente que tenta falar com um 100.64 que não está em uso faz o concentrador mandar o pacote para a borda. Se a borda tiver alguma rota que leve esse destino de volta ao concentrador, o static loop fecha dentro da sua rede; se não tiver, um endereço privado sai pela default rumo ao trânsito, o que também não deveria acontecer.

Sintomas e como detectar o static loop

SintomaO que significa
Link de trânsito cheio nos dois sentidosEntrada e saída sobem juntas, com volumes parecidos
Muitos pacotes por segundo sem cliente responsávelO tráfego é para endereços sem uso
ICMP Time Exceeded vindo da sua borda ou do trânsitoO TTL acabou no meio do loop
Traceroute alternando entre dois saltosA assinatura clássica do static loop
CPU da borda ou do concentrador alta em horário sem picoCada pacote é roteado dezenas de vezes

O teste mais direto é um traceroute para um endereço que você sabe que está livre. Da própria borda:

/tool traceroute 203.0.113.200

Com o loop presente, a saída alterna entre o trânsito e a borda até o fim. A saída abaixo está resumida nas colunas principais:

 #  ADDRESS          LOSS  SENT  LAST
 1  198.51.100.1     0%     3  0.6ms
 2  198.51.100.2     0%     3  1.1ms
 3  198.51.100.1     0%     3  1.7ms
 4  198.51.100.2     0%     3  2.2ms
 5  198.51.100.1     0%     3  2.8ms
 6  198.51.100.2     0%     3  3.3ms

Para varrer o bloco inteiro, rode o fping de uma máquina fora da sua rede, como um servidor em outro provedor. Ele manda um ping para cada endereço do bloco, e os avisos de Time Exceeded apontam exatamente os endereços presos num static loop:

fping -g 203.0.113.0/24 2>&1 | grep -i exceeded
ICMP Time Exceeded from 198.51.100.1 for ICMP Echo sent to 203.0.113.200
ICMP Time Exceeded from 198.51.100.1 for ICMP Echo sent to 203.0.113.201

Repita a varredura para cada bloco que você anuncia. Um endereço sem uso que não responde nada é o resultado esperado; um que devolve Time Exceeded é um loop esperando para ser explorado.

A correção: rota blackhole no RouterOS v7

A rota blackhole descarta em silêncio tudo que casar com ela. Como o roteador sempre escolhe a rota mais específica, uma blackhole para o bloco inteiro só pega o que não tem rota melhor. No RouterOS v7, a palavra blackhole entra sozinha, sem o type=blackhole do v6.

Na borda: o bloco inteiro

/ip route
add dst-address=203.0.113.0/24 blackhole distance=254
/ipv6 route
add dst-address=2001:db8::/32 blackhole distance=254

Com isso, 203.0.113.200 casa com o /24 blackhole e é descartado na primeira chegada. As rotas específicas para o /25 e o /27 continuam ganhando, porque são mais longas. O mesmo vale para o /32 de IPv6.

No concentrador: pools, CGNAT e prefixos delegados

/ip route
add dst-address=203.0.113.0/25 blackhole distance=254
add dst-address=203.0.113.128/27 blackhole distance=254
add dst-address=100.64.0.0/22 blackhole distance=254
/ipv6 route
add dst-address=2001:db8:a000::/40 blackhole distance=254
  • Pool PPPoE: cada cliente conectado ganha uma rota /32 dinâmica, mais específica que o /25. Os IPs livres do pool caem na blackhole em vez da default.
  • Pool público do CGNAT: o tráfego de volta das traduções ativas é tratado pelo connection tracking antes da decisão de rota. O post sobre CGNAT no Mikrotik com netmap já usa essa mesma rota.
  • 100.64.0.0/22: os clientes conectados têm a rota da sessão; endereço sem sessão não sai mais pela default.
  • Prefixos delegados: no prefixo delegado no PPPoE, cada sessão instala a rota do prefixo do cliente. O resto do /40 fica na blackhole.

Por que distance=254

A distance só desempata rotas com o mesmo prefixo. Com 254, se o mesmo /24 aparecer por outro caminho, como OSPF ou iBGP vindo de outro roteador, a rota real ganha e a blackhole fica de reserva. Com uma distance baixa, a blackhole poderia vencer uma rota legítima de mesmo tamanho e derrubar tráfego que deveria passar.

A blackhole não substitui filtro. Ela só resolve o destino sem dono. Ataque contra um IP em uso continua chegando; para isso, veja RTBH com blackhole via BGP.

Blackhole e anúncio BGP

No RouterOS v7, o que é anunciado ao trânsito sai de uma lista de endereços referenciada pelo output.network do template ou da conexão BGP:

/ip firewall address-list
add list=bgp-networks address=203.0.113.0/24

Como mostra o post sobre BGP no Mikrotik RouterOS v7, o prefixo precisa existir na tabela de rotas para ser anunciado de forma estável. A blackhole do /24 faz esse papel de âncora: o anúncio não depende de nenhuma interface estar de pé e, ao mesmo tempo, impede o static loop do bloco. Uma rota resolve os dois problemas.

Há uma consequência que vale ter em mente: se a borda perder o caminho para o concentrador, o /24 continua anunciado, e o tráfego para os clientes é descartado na borda em vez de dar voltas. Para o link de trânsito, é o melhor cenário possível numa falha interna.

Equivalente no Huawei: NULL0

Na borda Huawei VRP, a rota para a interface NULL0 cumpre o mesmo papel da blackhole do Mikrotik:

ip route-static 203.0.113.0 255.255.255.0 NULL0
ipv6 route-static 2001:db8:: 32 NULL0

A rota estática no VRP tem preferência 60 por padrão, e um número menor ganha. Isso quer dizer que, diferente do exemplo com distance 254 no Mikrotik, a NULL0 vence uma rota de mesmo prefixo aprendida por BGP (preferência 255) e perde para uma rota interna do OSPF (10), mas ganha de uma rota externa do OSPF (ASE, 150). Para o agregado que você mesmo origina isso costuma ser o desejado; se o mesmo prefixo também vier de outro roteador por BGP, ajuste a preferência da estática, como em ip route-static 203.0.113.0 255.255.255.0 NULL0 preference 254.

Erros comuns

ErroConsequênciaComo evitar
Blackhole com distance baixa no mesmo prefixo de uma rota realTráfego legítimo descartadoUsar distance=254
Blackhole só em IPv4Static loop continua no IPv6Criar a rota também em /ipv6 route
Blackhole só na bordaLoop entre concentrador e borda nos poolsRepetir nos concentradores
Pool novo sem blackholeLoop volta quando o pool cresceIncluir no procedimento de criar pool
Copiar type=blackhole de um tutorial do v6Sintaxe antigaNo v7 a palavra blackhole vai sozinha
Confiar só no firewallCada pacote ainda passa pelo filtroA rota resolve antes e custa menos

Depois de criar as rotas, confira se elas estão ativas e se a rota específica continua ganhando:

/ip route print where dst-address=203.0.113.0/24
/ip route print where dst-address=203.0.113.0/25
/tool traceroute 203.0.113.200

O traceroute para o endereço livre agora para logo no início, sem alternar saltos. Repita o fping de fora e guarde o resultado como evidência de que o static loop foi fechado.

Perguntas frequentes

O que é static loop em provedor?

É o loop de roteamento que acontece quando um roteador recebe tráfego para um endereço do próprio bloco sem rota específica e devolve pela default. O pacote vai e volta entre dois roteadores até o TTL acabar, multiplicando o tráfego no link.

A rota blackhole derruba os clientes conectados?

Não. As sessões PPPoE e as traduções ativas criam rotas ou entradas mais específicas, que sempre ganham da blackhole do bloco. Ela só pega o que não tem destino.

Preciso de blackhole se eu não uso BGP?

Precisa. Se o trânsito roteia o bloco para você por rota estática e a sua borda tem default para ele, o static loop acontece do mesmo jeito. O BGP só muda a forma como o trânsito aprende o bloco.

Qual a diferença entre essa blackhole e o RTBH?

Esta blackhole é permanente e cuida de endereços sem uso. O RTBH é temporário, marca um IP em uso que está sob ataque e pede ao trânsito que descarte o tráfego antes de chegar à sua rede.

Também preciso fazer isso no IPv6?

Sim, e com mais motivo. O bloco IPv6 é muito maior e quase todo vazio, então quase todo endereço cai no loop se faltar a blackhole do prefixo inteiro e dos pools de prefixo delegado.

Conclusão

O static loop custa pouco para evitar e caro para descobrir no meio de uma madrugada. A regra é curta: todo bloco que chega a um roteador ganha uma rota blackhole com distance alta, na borda e em cada concentrador, em IPv4 e IPv6. As rotas específicas continuam funcionando e o que sobra morre na primeira chegada.

Coloque a criação da blackhole no mesmo procedimento que cria um pool ou anuncia um prefixo, e rode a varredura com fping de tempos em tempos. Assim o static loop não volta quando a rede cresce.

Leitura recomendada: Static Loop, um erro que pode matar seu ISP/ITP, na wiki do Brasil Peering Forum (conteúdo sob licença CC BY-NC 4.0).

Compartilhar:

Sobre o autor

Ivan Alves

Especialista em redes de provedores (ISP)

Ivan Alves trabalha há mais de 15 anos com redes de provedores de internet, do NOC ao backbone e à borda BGP. Coordena infraestrutura e tecnologia em um provedor regional e escreve aqui os tutoriais que gostaria de ter encontrado quando começou: comandos testados, cenário explicado e o porquê de cada linha.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *