O desafio de organizar – sozinho – um evento Capture the Flag

Quando eu retomei o blog, há cerca de 2 meses, estava obcecado com a ideia de retomar os Mega Desafios. Mas não podia ser qualquer coisa. Tinha que ser algo grandioso. Algo que desse o que falar, que – de fato – apresentasse aos participantes um nível de entretenimento, estímulo, disputa e desafio que não apenas fosse lembrado, mas que também gerasse aquele gostinho de “quero mais”.

É, eu talvez tenha levantado demais a barra. Ficou realmente difícil conceber um desafio que atendesse a todos os meus anseios. Mas, então, como que uma luz, veio a ideia: E se eu aplicasse o conceito CTF (Capture the Flag) para a criação de um evento com foco em redes e afins? Desta forma, eu poderia criar não apenas um, mas uma série de desafios. E, não apenas isso, mas também criar um ambiente competitivo, interativo e divertido para quem (ousasse) participar 🙂 . E foi nessa direção que eu caminhei, sem saber o que me esperava.

Eu já tinha ouvido histórias de quem se aventurou por estas bandas. Relatos bem documentados dos apuros passados. Das horas mal dormidas. Das falhas por falta de infra. Enfim, várias histórias de terror. Mas, mesmo assim, decidi seguir em frente e, pelo menos, tentar.

O primeiro desafio era escolher a plataforma mais alinhada com o que eu gostaria de oferecer. As plataformas mais populares – como a CTFd – são relativamente fáceis de utilizar, mas oferecem poucas opções em termos dos tipos de desafios – por exemplo, o tipo King of the Hill – um dos tipos mais legais – raramente é suportado. Eu queria uma opção que oferecesse tudo. Sim, porque já diz o ditado: “O que é um peido para quem já está cagado?” 🙂

Depois de pesquisar bastante, acabei optando pela plataforma criada pelo pessoal do Facebook (FBCTF). Ela virou opensource em 2016 mas caiu no esquecimento cerca de 2 anos depois – o projeto acabou sendo arquivado no GitHub. Ainda assim, achei que valia a pena tentar. Logo de cara, a instalação  mostrou-se um desafio enorme. Segui as instruções à risca, mas só conseguia ver erros e mais erros. Nada funcionava. Pesquisei em diversas fontes e não conseguia resolver o problema. No fim, optei por fazer a compilação do fonte na unha – o que levou uma eternidade – mas funcionou.  Os problemas estavam apenas começando, no entanto.

O grande desafio de montar uma estrutura CTF – fui descobrir depois – é a questão de escalabilidade. Jogos CTF são altamente interativos, gerando um número absurdamente alto de interações cliente-servidor. Este é um dos problemas relatados em praticamente TODAS as plataformas CTF. Funcionam bem, sim. Desde que o número de participantes não ultrapasse 30, 40 ou 50 (dependendo da plataforma). São números muito baixos. Perde a graça gastar tanto tempo e energia montando uma estrutura para atender apenas 30 a 50 participantes. Queria algo que escalasse para mais de 200, facilmente. Nos meus testes iniciais, meu setup mal aguentava 30 conexões simultâneas. Por mais memória e CPU que eu adicionasse a VM, com mais de 30 acessos simultâneos a plataforma começava a gerar erros. E – novamente – pelo que pesquisei, este é um problema crônico em todas as plataformas mais conhecidas.

Pesquisando mais sobre o tema buscando uma forma de endereçar o problema, percebi que os organizadores dos grandes eventos CTF optaram pela abordagem de quebra em microservices, ou seja, o desmembramento de um serviço monolítico (ex: uma única VM rodando o sistema operacional, banco de dados, PHP, java, etc) em vários serviços independentes, rodando em containers. Parecia um bom caminho para seguir, então comecei o processo de desmembramento (na unha) e parti para os testes. Percebi que se eu separasse apenas o serviço de banco de dados, a melhora já era significativa. Para simplificar minha vida, optei por esta abordagem: Separação do serviço de banco de dados em uma VM dedicada e os serviços Web (NGINX) e PHP/HHVM – os serviços mais exigidos durante uma competição  – em um pool de VMs com balanceamento de carga. Comecei com 1 VM para o banco de dados e 2 para os outros serviços. Percebi que conseguia agora receber 50 competidores sem nenhum dano ao sistema. Como a replicação das VMs era muito simples de ser feita, no teste final deixei apenas 1 servidor de banco de dados e 6 (!) VMs balanceadas para lidar com o restante dos serviços. Resultado: Nos testes de stress que realizei utilizando Apache JMeter, consegui alcançar a marca de 500 logins simultâneos e mais de 4 GB de dados trocados com a plataforma 100% operacional.

A topologia que adotei segue abaixo. As VMs mais exigidas (NGINX e HHVM) foram separadas em 2 servidores físicos distintos: 3 rodando em meu servidor ProxMox e 3 rodando no (adivinhem?) EVE-NG. O mais interessante é que, em termos de performance, as VMs no EVE parecem estar melhor.

Para teste de stress, eu adotei a ferramenta Apache JMeter. Ela permite gerar uma carga HTTP elevada simulando um alto número de conexões simultâneas. No teste abaixo, foram geradas 300 interações HTTP simultâneas pelo período de 5 minutos.

A situação inicial (pré-teste) no Big-IP pode ser observada acima. Estatísticas zeradas. Os 3 primeiros pool members são as VMs criadas no EVE, e os 3 últimos as VMs criadas no ProxMox. O método de balanceamento escolhido foi o Fastest L7, que privilegia o envio de mais conexões aos pool members que estão processando requisições L7 com melhor performance.

O teste tem início. A ferramenta JMeter (abaixo) inicia uma interação volumétrica com o serviço (usando o endereço publicado na Internet) e alcança o pico de 300 requisições simultâneas, que permanece por 5 minutos:

O impacto registrado no servidor MySQL (banco de dados) – figura abaixo – mostra que o serviço claramente não era o gargalo. Uma única VM consegue suportar um grande número de requisições sem maiores problemas (os testes com JMeter estão gerando interações com Login, que necessitam de acesso ao banco)

Agora, se observarmos uma das VMs NGINX / HHVM, podemos notar o estrago. A utilização da CPU está praticamente em 100% (mesmo com 4 vCPUs). Ainda assim, pelo fato da carga estar distribuída entre 6 nodes, o acesso à aplicação segue funcionando – algo impossível com apenas 1 VM, no cenário testado.

Ao fim do teste, olhando as estatísticas no BIG-IP, é possivel verificar que as 3 VMs no EVE acabaram processando um número maior de conexões (observe abaixo a coluna Connections > Total), o que implica assumir que a performance das VMs no EVE é superior às criadas no ProxMox – algo que me surpreendeu.

Além da definição da topologia, a configuração dos serviços também foi um desafio à parte. Foi preciso fazer um “fine tuning” do banco de dados (aumentar o número máximo de conexões e ajuste de memória e buffers, por exemplo) e dos serviços NGINX e HHVM, para que eles conseguissem alcançar o máximo de utilização sem queda sensível de performance. A plataforma agora está rodando muito bem e está bem estável, mas do início do projeto até aqui foi exatamente 1 mês trabalhando nas minhas horas vagas (e algumas noites adentro). A criação da infra de uma competição CTF talvez seja uma das formas mais eficientes de você colocar em prática uma série conceitos como escalabilidade, microservices, containers, automação, resiliência, balanceamento de carga, sem falar da parte de programação em si (por exemplo, eu acabei fazendo inúmeras alterações no fonte do FBCTF para deixá-lo do jeito que eu precisava). Estou aprendendo muito com o processo. E me divertindo também, claro 🙂

O teste real da plataforma só vai ocorrer quando usuários começarem a acessá-la, claro. O teste inicial ocorre neste Domingo, com um grupo de 50 usuários. Era para ter ocorrido Domingo passado, mas eu ainda não havia concluído os ajustes, então tive que adiar. Se a plataforma passar pelo teste de Domingo, partiremos para a competição de fato, em Agosto, onde abrirei 100 vagas. A participação, então, poderá ser feita individualmente ou em times de até 4 participantes.

Além de criar e testar toda a infra, existe depois a parte de criar os desafios e adicioná-los à plataforma. E isso não é simples, especialmente se os desafios são elaborados. No teste deste Domingo, o evento terá uma duração máxima de 2 horas, e teremos cerca de 20 desafios variando de perguntas e respostas até desafios práticos de troubleshooting de rede (o participante terá de resolver desafios lógicos para obter acesso a uma VPN e, então, uma vez conectado à VPN deverá identificar e corrigir problemas em uma rede para então conseguir acesso a um servidor e registrar o nome de seu time nele).

Em tudo dando certo, o evento final (em Agosto) terá uma gama muito maior de desafios e a duração do evento será de 24 horas. Mas, primeiro, vamos ver como o BETA vai se sair.

Boa sorte aos bravos que competirão neste Domingo!

E aguardem novidades à respeito do CTF realizado pelo Blog CCNA! Vem mais por aí 🙂

Abs

Marco



Comente usando o Facebook!

Deixe uma resposta