Por que a TablePlus não tomou nenhuma medida contra semanas de tentativas de ataque DDoS
(tableplus.com)- A TablePlus vem observando o estado dos servidores apesar de semanas de tentativas de DDoS, sem bloquear IPs nem ativar o modo “Under Attack” do Cloudflare
- Nos últimos 30 dias, houve cerca de 6 milhões de tentativas de download dos arquivos de instalação; só nos últimos 5 dias foram 800.126, e cada arquivo tem cerca de 200 MB por download
- Mesmo durante o ataque, o uso de CPU dos servidores ficou na maior parte do tempo em 0–1%, e a infraestrutura foi montada para que cerca de 8 serviços de API e bancos de dados consigam processar bilhões de requisições por mês sem cache
- O backend é agrupado em serviços monolíticos por aplicativo, usando implantação de um único binário em um novo VPS, sem Docker, Kubernetes nem ambiente de runtime
- Uma configuração simples com frameworks Go/Rust, indexação de banco de dados, separação do banco de logs, proxy reverso com Nginx, Cloudflare CDN/R2 e throttling no envio de e-mails reduz o custo do ataque e a complexidade operacional
Semanas de tentativas de DDoS
- Alguém enviou centenas de milhões de requisições aos servidores da TablePlus ao longo de várias semanas e tentou baixar os arquivos de instalação milhões de vezes
- As tentativas de download dos arquivos de instalação chegaram a 800.126 nos últimos 5 dias e a cerca de 6 milhões nos últimos 30 dias
- O tamanho do arquivo de instalação é de cerca de 200 MB por download
- Com base nas chamadas de API dos últimos 30 dias, a maior parte do tráfego veio da UE, especialmente da Germany e do United Kingdom
- Esse número não inclui requisições de download nem tráfego de CDN
- No momento da redação do texto, o ataque ainda continua
Resposta prática: uma arquitetura feita para aguentar, não para bloquear
- Não bloqueiam os endereços IP dos atacantes
- Usam Cloudflare, mas não ativam o modo “Under Attack”
- Mesmo durante o ataque, a CPU dos servidores permaneceu quase ociosa, na maior parte do tempo em 0–1%
- Como o serviço consegue processar bilhões de requisições por mês sem problemas e sem grande impacto de custo, quase nenhuma medida extra foi necessária
Design simples de backend
- O design do app TablePlus busca simplicidade, e os serviços de backend também são mantidos com a configuração mínima possível
- Não usam serviços de renderização de terceiros como Vercel ou Netlify, porque eles podem virar gargalo durante um ataque ou gerar cobranças inesperadas
- A visão deles é que usar o próprio servidor web evita essas limitações
- No passado, monólitos podiam virar gargalo por causa de VPSs e processadores fracos, mas os VPSs atuais oferecem CPUs multicore, muita RAM e SSDs rápidos
- SSDs rápidos e muita RAM aumentam bastante o desempenho do banco de dados
- Se for bem implementado, um serviço monolítico em instância única também pode processar bilhões de requisições por mês
Como operam monólitos por aplicativo
- Integram em um único serviço tudo o que cada app precisa: API, site, e-mail, pagamentos etc.
- A implantação termina com um arquivo de configuração, build e deploy
- Ao migrar o serviço para outro provedor de nuvem ou fazer uma nova implantação, o processo pode ser concluído rapidamente
- Como há poucas dependências, fica mais fácil depurar e identificar gargalos
- Mesmo quando ocorre um erro, geralmente há apenas um ou poucos serviços para verificar
- Exemplos de frameworks monolíticos possíveis:
- Golang: Echo, Gin
- PHP: Laravel
- Ruby: Rails
- Rust: Actix, Rocket, Warp
Princípios de configuração para bilhões de requisições por mês
- Escolhem frameworks web de alto desempenho, e a TablePlus prefere Golang e Rust
- À medida que o conjunto de dados cresce, criam índices no banco de dados para reduzir o tempo de consulta
- Para proteger o desempenho do negócio principal, separam o banco de dados principal do banco de logs e uso
- O banco principal é para dados que não mudam ou cujo tamanho não cresce com o tempo
- O banco de logs/uso é para dados que continuam crescendo com o passar do tempo
- Na frente das APIs principais, colocam um proxy reverso para tratar e distribuir as requisições
- Isso ajuda quando são necessários vários servidores
- A TablePlus usa Nginx
- Colocam tudo atrás do Cloudflare e configuram adequadamente cache, Argo e full SSL entre o Cloudflare e o servidor
- Usam um CDN com proteção contra DDoS
- A TablePlus prefere Cloudflare R2 e CDN em vez de Amazon CloudFront + S3, tanto para reduzir custos quanto para proteção
- Manter arquivos grandes para download em um VPS sem CDN nem cache consome a largura de banda rapidamente
- A TablePlus usa o Cloudflare CDN com largura de banda ilimitada
- Se o Argo estiver ativado no mesmo domínio, o tráfego do Cloudflare CDN pode passar pelo Argo, e como a largura de banda do Argo não é gratuita, o custo pode aumentar bastante
- Em requisições que exigem envio de e-mail pelo servidor, como recuperação de senha, usam throttling para proteger o mailer
Forma de implantação: executar binários sem contêineres
- A TablePlus mantém o processo de implantação o mais simples possível, sem Docker, Kubernetes, contêineres nem configuração separada de ambiente de runtime
- A unidade de implantação é o binário
- Ele é copiado para um servidor Linux e executado como processo
- É tratado de forma parecida com a execução do app TablePlus no macOS
- O Linux Systemctl pode monitorar o processo e reiniciá-lo em caso de erro fatal
- Executam de forma nativa para não desperdiçar CPU/RAM com camadas intermediárias como VM, virtualização ou gerenciadores de infraestrutura de terceiros
- Escolhem Go e Rust porque são linguagens de alto desempenho e conseguem gerar arquivos binários para implantação
Proteções a ativar ao usar Vercel
- Para proteger sites em situações assim, a Vercel oferece Spend Management e Attack Challenge Mode
- Spend Management: permite definir limite de gasto soft ou hard
- Attack Challenge Mode: é semelhante ao modo “Under Attack” do Cloudflare
- Se você usa Vercel, é necessário deixar esses recursos ativados
1 comentários
Opiniões do Hacker News
Este texto parece autoelogio demais. “1 bilhão de requisições por mês” dá só algumas centenas de requisições por segundo, algo trivial, e é difícil até chamar isso de DDoS
Além disso, o site fica atrás da Cloudflare, que é uma CDN, então entendo menos ainda por que isso seria visto como algo impressionante do ponto de vista de desempenho
Por exemplo, não há um cenário razoável em que um arquivo de 200 MB não seja servido a partir do cache da CDN. Não é algo para se orgulhar dizer que o servidor da aplicação não lê 200 MB do disco e copia para o cliente a cada download; fazer isso seria um projeto obviamente ruim
Se o arquivo de 200 MB mencionado for o download do app cliente TablePlus em https://tableplus.com/download, a versão para Windows tem 183 MB e de fato está em cache na Cloudflare
# curl -v https://files.tableplus.com/windows/5.9.2/TablePlusSetup.exec > /dev/null< cache-control: max-age=691200< cf-cache-status: HIT< age: 2980Isso não é o tipo de coisa que, em uma empresa FAANG, normalmente se consideraria que exigiria mais de mil desenvolvedores? Não sei como dá para chamar só de autoelogio algo que até grandes empresas regularmente não conseguem fazer
É difícil olhar apenas como algumas centenas de requisições por segundo. A densidade das requisições não é uniforme ao longo do tempo e pode subir com frequência até 20 vezes a média
4 TB por mês, na verdade, não é difícil de não considerar um ataque DDoS? Se fossem 4 TB por hora, daria para chamar de DDoS, mas 4 TB por mês são só 1,5 MB por segundo
6 milhões de requisições por mês também são apenas 2 requisições por segundo. Nessa escala, o fato de operar como um serviço monolítico não parece muito relevante, especialmente considerando que a Cloudflare provavelmente atende a maior parte das requisições pelo cache da CDN
A esmagadora maioria da web são sites WordPress em hospedagem multi-inquilino de 5 a 20 dólares por mês, e, em organizações maiores, muitas vezes Drupal. Sem cache instalado e conectados diretamente ao banco de dados, a maioria dos sites da internet pode cair com apenas 4 requisições por segundo
Pode parecer loucura, mas essa é a realidade. Antigamente, na Cloudflare, gerenciei proteção contra DDoS, WAF, firewall e projetos de segurança para clientes, e vi com frequência sites de clientes caírem só com web scraping ou taxas de requisições HTTP muito pequenas e baixas
Números grandes ficam nas manchetes, mas o que a maioria das pessoas sente na prática são números pequenos
Um ataque de negação de serviço pode ser feito com apenas alguns KB por hora. Se você atingir um endpoint de API pesado do serviço-alvo, isso por si só pode derrubar o serviço; “Distributed” só significa que várias máquinas estão atacando ao mesmo tempo
DDoS não exige necessariamente uma vazão enorme. Só que o que aparece nas notícias geralmente são os ataques grandes
O objetivo desse tipo de ataque pode ser queimar a cota de banda do servidor de origem ou tornar o custo de banda insustentável. Dá para fazer isso muito barato com uma única máquina de ataque ou poucas delas. A maioria dos datacenters e provedores de hospedagem tem limite de banda ou cobra após certa quantidade, e empresas atacadas muitas vezes só percebem depois de receber uma fatura que não conseguem pagar
Tenho um site de download de um jogo com uns 50 jogadores no total. Ninguém usa, e pessoas reais provavelmente baixam o jogo algumas vezes por mês
Só que um único arquivo zip de 2 GB gerou 5 TB de tráfego no mês passado, e isso continua há anos. Isso não é DDoS, é só um bot/crawler mal configurado que segue todos os links e não consegue cancelar o download
Parece ser algo como 1 TB por dia, mas ainda assim continua sendo muito pequeno
Acho que depende de quão irregular é o tráfego
Isto é apenas um site estático de marketing para um app desktop. Não há fórum de discussão, e o feedback é tratado via issues no GitHub
É bem estranho se gabar de como é simples fazer deploy de um site estático de marketing e de como arquivos estáticos aguentam centenas de milhares de downloads por dia. E quem faz a mitigação aqui é a Cloudflare, não eles. Isso se esse tráfego minúsculo sequer precisar de mitigação
Se eu sofresse um “ataque” desses, acho que nem perceberia até receber o e-mail mensal da Cloudflare dizendo “X TB transferidos, quase 100% de economia de banda”
O app em si eu gosto e recomendo
Isso parece menos um ataque DDoS e mais, pela descrição, cerca de 8 TB por mês de tráfego adicional que se aproxima de um “abuso de serviço irritante e sem sentido”
Não há problema em ignorar esse tipo de abuso enquanto ele não causar custo ou esgotamento de recursos, mas histórias como “descobrimos que 80% da capacidade da frota de autoscaling não fazia nada útil” são deprimentemente comuns, então é preciso pelo menos ficar de olho
A parte mais irritante desse tipo de abuso costuma ser os logs. A maior parte dos logs fica preenchida pelos mesmos hosts repetindo as mesmas ações inúteis. Se o armazenamento de logs for barato e abundante, não é um grande problema, mas ter uma forma de classificar automaticamente certo tráfego como abuso e suprimir o processamento rotineiro é definitivamente uma boa ideia
Só que não é tão fácil quanto parece. Perdi a conta de quantas vezes adicionei lógica de classificação para capturar abusos óbvios e idiotas em servidores SMTP de entrada, e toda vez ela acabava pegando também cenários limítrofes que eram válidos
Se você passa tempo demais em uma sequência de tocas de coelho, fica fácil não conseguir fazer o trabalho de verdade. Por isso, às vezes é melhor terceirizar; ou, se isso também for trabalhoso ou caro demais, simplesmente ignorar o abuso mesmo sendo irritante
Na DigitalOcean, por exemplo, no s-4vcpu-8gb-intel, você paga 30 dólares pelos 3 TB excedentes acima dos 5 TB incluídos, e na Linode o excedente de 3 TB custa 15 dólares. Então acho que o texto tem um ponto
Isto não é um “ataque” digno de nota. Um único script bash disparado sem controle na máquina de alguém já conseguiria fazer isso
“50 milhões de requisições por mês no Reino Unido” dá, em média, menos de 20 requisições por segundo. Eu esperaria que um único servidor Go desse conta de 250 vezes esse volume de requisições sem grandes otimizações
O conselho em si não é necessariamente ruim, mas esses números não servem como prova do conselho. Para um serviço de API HTTP em Go, eu esperaria que um VPS pequeno a médio lidasse com 5 mil requisições por segundo sem otimização, mesmo com algum trabalho de banco de dados e formatação JSON. É um número baseado na experiência de ter implantado dezenas de serviços parecidos em um lugar que recebia bilhões de requisições por dia e, nos picos, passava de 500 mil requisições por segundo
É bom que isso não esteja causando dano, mas me deixa um pouco inquieto tomar isso como conselho, porque falta muita coisa
Preferir distribuir binários em vez de Docker é ok, mas o que fazer com o host onde esse binário roda? Um dos motivos para usar contêineres é empacotar as configurações de reforço de segurança junto com a implantação, para ter certeza de que, quando for preciso escalar depois, as configurações de segurança serão iguais entre os nós
O monólito mencionado aqui pode ser colocado em um único VPS, e isso é bom e barato. Mas, se ele travar ou se o hardware falhar por qualquer motivo, pode haver um tempo de indisponibilidade considerável
Outra preocupação é que, ao juntar tudo em um monólito, você perde a defesa em profundidade da pilha da aplicação. Se alguém invadir a aplicação pelo frontend, pode ir direto até o armazenamento de dados do backend. É por isso que muita gente coloca o armazenamento de dados atrás de serviços web internos e o isola com grupos de segurança em uma rede privada separada do frontend, limitando a superfície de ataque ao nível das ações que podem ser executadas pelo navegador
Não existe mundo em que aumentar a superfície de ataque melhore a segurança
Se você acha que instalar Docker deixa o host seguro, está enganado. Como você vai configurar hosts adicionais quando escalar?
Ao usar Docker, não basta proteger os contêineres; o host também precisa estar seguro, inclusive o serviço que executa os contêineres. Ao escalar e implantar hosts adicionais, eles precisam estar igualmente seguros
Se você usa infraestrutura como código e configuração como código, não há diferença essencial entre implantar um binário por trás da configuração do sistema ou implantar Docker
Existem ferramentas para tornar uma configuração “bare metal” reproduzível em algum grau. Por exemplo, NixOS, Ansible e builds de imagens Amazon AMI
Nunca entendi bem a expressão “invadir a aplicação pelo frontend”. Injeção de SQL mexe diretamente no armazenamento de dados sem execução remota de código, e XSS afeta outros usuários lateralmente
Então como exatamente alguém sai do frontend e chega livremente a todo o backend? As pessoas estão rodando um interpretador JavaScript com acesso a shell dentro de serviços de API em Go e chamando
evalem entradas de usuário? Tecnicamente, isso me parece muito forçadoNo fim, isso não é segurança por obscuridade? Algo como tornar tudo tão complexo que, se nem nós entendermos, os outros também não vão entender?
O importante não é criar mais paredes, e sim fazer com que as paredes não possam ser derrubadas. Interfaces reduzem desempenho e aumentam complexidade
Pessoalmente, essa expressão me incomoda. “1 bilhão de requisições por mês” dá aproximadamente 370 requisições por segundo. É um nível que um único servidor bem configurado consegue atender e, com certeza, menos de 10 servidores bastariam
Um único script bash malicioso também consegue gerar esse volume de tráfego
Talvez eu esteja sem senso de realidade, mas dezenas de bilhões de requisições por mês não parecem grande coisa. Isso é considerado um grande ataque DDoS?
Gostei da parte: “para cada app, criar um serviço monolítico fácil de implantar e manter. Nada de Docker, nada de Kubernetes, nada de dependências, nada de ambiente de runtime; apenas um arquivo binário que pode ser implantado em qualquer VPS recém-criado”
Não uso TablePlus diretamente. Se isso é sobre o site de marketing, é óbvio que Kubernetes não é necessário
Se é sobre a aplicação, acho estranho dizer que não há dependências. Ela não armazena dados nem gera logs?
Essa é uma vantagem realmente excelente do Golang. Você sobe um VPS, aplica padrões razoáveis, compila de forma cruzada e executa o binário
Comparado a deploys em Python, Node e PHP, há muito menos complexidade desnecessária
Seria ótimo se executar e manter um servidor de banco de dados vivo também pudesse ser tão simples
Pelo título, eu esperava algo mais no estilo swole doge. Concordo com boa parte dos conselhos, mas estar atrás da Cloudflare está longe de ser “nada”
Dependendo da distribuição do tráfego, talvez um VPS sozinho sem Cloudflare também tivesse aguentado bem, e a escala nem parece tão grande assim. Teria sido interessante ver estatísticas mais detalhadas, como requisições por segundo e quanto a Cloudflare bloqueou antes de chegar à origem
Um DDoS de camada 7 vindo da Rússia contra empresas suecas que eu conheço foi grande o bastante para derrubar grandes provedores por problemas de capacidade. Isso incluiu Verizon, Azure Frontdoor, Cloudflare e balanceadores de carga do GCP. Contra uma escala dessas, essa estratégia definitivamente não funcionaria