Uma expressão regular consome 100% da CPU global
Cloudflare · 2 de julho de 2019
Impacto: 27 minutos de queda global. Todo o tráfego HTTP/HTTPS da rede passou a responder erro 502.
O que aconteceu
Uma regra nova do firewall de aplicação foi publicada para toda a rede. Ela continha uma expressão regular destinada a detectar scripts maliciosos em requisições.
A expressão tinha um padrão com aninhamento de quantificadores — do tipo .*.*=.* — que, diante de certas entradas, faz o motor de regex explorar um número exponencial de caminhos antes de desistir. É o que se chama de retrocesso catastrófico.
Como o firewall roda em cada máquina da borda e a regra foi distribuída globalmente em segundos, todos os núcleos de todos os servidores da rede foram para 100% de CPU quase ao mesmo tempo. Sem CPU sobrando, nada era servido.
A recuperação exigiu desativar globalmente o módulo do firewall — o que só foi possível porque existia um interruptor global para isso.
A linha do tempo
- T+0
Regra nova de firewall publicada globalmente, em poucos segundos.
- T+~1min
O retrocesso catastrófico leva a CPU a 100% em toda a rede de borda simultaneamente.
- T+3min
Tráfego global começa a responder 502.
- T+~14min
Causa identificada como o módulo de firewall.
- T+27min
Módulo desativado globalmente; tráfego volta.
A causa raiz
A causa imediata foi a regex. A causa raiz foi o processo de publicação: uma mudança de regra ia de zero a cem por cento da rede em segundos, sem estágio intermediário e sem teto de consumo de CPU por regra. Uma mudança que atinge tudo ao mesmo tempo não tem como falhar pequeno.
Antes do incidente
O que você colocaria na pilha para conter o estrago?
O que mudou depois
- A publicação de regras passou a ser progressiva, com estágios e observação entre eles.
- Foi adicionado limite de CPU por regra, para que uma regra ruim falhe sozinha.
- Regexes passaram a ser analisadas em busca de padrões com risco de retrocesso exponencial antes da publicação.
Fonte: Cloudflare — *Details of the Cloudflare outage on July 2, 2019*, por John Graham-Cumming