1 puntos por GN⁺ 2024-03-31 | 1 comentarios | Compartir por WhatsApp
  • TablePlus está observando el estado de sus servidores pese a intentos de DDoS que llevan varias semanas, sin bloquear IP ni activar el modo “Under Attack” de Cloudflare
  • En los últimos 30 días hubo cerca de 6 millones de intentos de descarga del archivo de instalación, y solo en los últimos 5 días fueron 800,126; el archivo pesa alrededor de 200 MB por descarga
  • Incluso durante el ataque, el uso de CPU del servidor se mantuvo mayormente en 0–1%, y su configuración permite que unos 8 servicios de API y bases de datos procesen miles de millones de solicitudes al mes sin caché
  • El backend se agrupa como servicios monolíticos por app, y se despliega en nuevos VPS como un único binario, sin Docker, Kubernetes ni entornos de ejecución
  • Una configuración simple con frameworks de Go/Rust, indexación de bases de datos, separación de la base de datos de logs, proxy inverso con Nginx, CDN/R2 de Cloudflare y throttling para el envío de correos reduce el costo del ataque y la complejidad operativa

Intentos de DDoS que llevan varias semanas

  • Alguien ha estado enviando cientos de millones de solicitudes a los servidores de TablePlus durante varias semanas e intentando descargar millones de veces el archivo de instalación
  • Los intentos de descarga del archivo de instalación llegaron a 800,126 en los últimos 5 días y a cerca de 6 millones en los últimos 30 días
    • El archivo de instalación pesa alrededor de 200 MB por descarga
  • Según las llamadas a la API de los últimos 30 días, la mayor parte del tráfico proviene de la UE, especialmente de Germany y United Kingdom
    • Esta cifra no incluye las solicitudes de descarga ni el tráfico de CDN
  • Al momento de escribir el artículo, el ataque seguía en curso

Respuesta real: una arquitectura que resiste en lugar de bloquear

  • No se bloquearon las direcciones IP de los atacantes
  • Aunque se usa Cloudflare, no se activó el modo “Under Attack”
  • Incluso durante el ataque, la CPU del servidor estuvo casi inactiva, mayormente en torno a 0–1%
  • Como el servicio puede procesar miles de millones de solicitudes al mes sin problemas y el costo no es una gran carga, casi no se tomaron medidas adicionales

Diseño de backend simple

  • El diseño de las apps de TablePlus apunta a la simplicidad, y sus servicios de backend también se mantienen con una configuración mínima siempre que sea posible
  • No se usan servicios de renderizado de terceros como Vercel o Netlify, ya que durante un ataque pueden generar cuellos de botella o facturas inesperadas
  • Consideran que usar un servidor web propio permite evitar esas limitaciones
  • En el pasado, un monolito podía convertirse en cuello de botella por VPS y procesadores débiles, pero los VPS actuales ofrecen CPU multinúcleo, mucha RAM y SSD rápidos
    • Los SSD rápidos y la RAM mejoran mucho el rendimiento de la base de datos
    • Si se implementa correctamente, incluso un servicio monolítico en una sola instancia puede procesar miles de millones de solicitudes al mes

Operación de monolitos por app

  • Para cada app se integran en un solo servicio las API, el sitio web, el correo electrónico, los pagos y demás componentes necesarios
  • El despliegue se completa con un archivo de configuración, una compilación y el despliegue
  • Al migrar un servicio a otro proveedor cloud o desplegarlo de nuevo, el proceso puede hacerse rápidamente
  • Al tener pocas dependencias, es más fácil depurar e identificar cuellos de botella
    • Incluso si ocurre un error, solo hay que revisar uno o unos pocos servicios
  • Algunos ejemplos de frameworks monolíticos disponibles son:
    • Golang: Echo, Gin
    • PHP: Laravel
    • Ruby: Rails
    • Rust: Actix, Rocket, Warp

Principios de configuración para miles de millones de solicitudes al mes

  • Elegir un framework web de alto rendimiento; TablePlus prefiere Golang y Rust
  • A medida que crece el conjunto de datos, configurar índices en la base de datos para reducir el tiempo de consulta
  • Separar la base de datos principal de la base de datos de logs y uso para proteger el rendimiento del negocio principal
    • La base de datos principal se usa para datos que no cambian o cuyo tamaño no crece con el tiempo
    • La base de datos de logs y uso se usa para datos que siguen creciendo con el tiempo
  • Colocar un proxy inverso delante de las API principales para procesar y distribuir solicitudes
    • Ayuda cuando se necesitan varios servidores
    • TablePlus usa Nginx
  • Poner todo detrás de Cloudflare y configurar adecuadamente la caché, Argo y SSL completo entre Cloudflare y el servidor
  • Usar una CDN con protección contra DDoS
    • TablePlus prefiere Cloudflare R2 y CDN frente a Amazon CloudFront + S3 para reducir costos y obtener protección
  • Si se alojan archivos grandes de descarga en un VPS sin CDN ni caché, el ancho de banda se consume rápidamente
    • TablePlus usa la CDN de Cloudflare con ancho de banda ilimitado
    • Si se activa Argo en el mismo dominio, el tráfico de la CDN de Cloudflare puede pasar por Argo, y como el ancho de banda de Argo no es gratuito, los costos pueden aumentar
  • Las solicitudes que requieren que el servidor envíe correos, como recuperación de contraseña, protegen el servicio de correo mediante throttling

Método de despliegue: ejecutar binarios sin contenedores

  • TablePlus mantiene el proceso de despliegue lo más simple posible, sin Docker, Kubernetes, contenedores ni configuración de entornos de ejecución separados
  • La unidad de despliegue es un binario
    • Se copia al servidor Linux y se ejecuta como proceso
    • Se maneja de forma similar a ejecutar la app de TablePlus en macOS
  • Linux Systemctl puede encargarse de monitorear el proceso y reiniciarlo si ocurre un error crítico
  • Se ejecuta de forma nativa para no desperdiciar CPU/RAM en capas intermedias como VM, virtualización o administradores de infraestructura de terceros
  • Se eligieron Go y Rust porque son lenguajes de alto rendimiento y pueden generar archivos binarios para despliegue

Funciones de protección que conviene activar al usar Vercel

  • Para situaciones como esta, Vercel ofrece funciones para proteger el sitio: Spend Management y Attack Challenge Mode
    • Spend Management: permite configurar límites de gasto soft o hard
    • Attack Challenge Mode: es similar al modo “Under Attack” de Cloudflare
  • Si se usa Vercel, es necesario activar esas funciones

1 comentarios

 
GN⁺ 2024-03-31
Opiniones en Hacker News
  • Este artículo se siente demasiado como autobombo. “1,000 millones de solicitudes al mes” son apenas unos cientos de solicitudes por segundo, algo trivial, y difícilmente se puede llamar DDoS
    Además, el sitio está detrás de Cloudflare, que es un CDN, así que desde el punto de vista del rendimiento se entiende todavía menos por qué habría que verlo como algo impresionante
    Por ejemplo, no hay una situación razonable en la que un archivo de 200 MB no se sirva cacheado desde el CDN. No es algo de lo que presumir que el servidor de la aplicación no lea 200 MB del disco y los copie al cliente en cada descarga; hacerlo sería un diseño evidentemente pésimo

    • Si el archivo de 200 MB del que hablan es la descarga de la app cliente de TablePlus en https://tableplus.com/download, la versión para Windows pesa 183 MB y, de hecho, está cacheada en 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: 2980

    • ¿No es este el tipo de cosa que en una empresa FAANG normalmente se consideraría que requiere más de 1,000 desarrolladores? No sé cómo se puede decir que es puro autobombo cuando se trata de algo que incluso las grandes empresas no logran hacer de forma regular

    • No se puede verlo solo como unos cientos de solicitudes por segundo. La densidad de solicitudes no es uniforme en el tiempo, y con frecuencia puede subir hasta 20 veces el promedio

  • 4 TB al mes en realidad difícilmente puede considerarse un ataque DDoS, ¿no? Si fueran 4 TB por hora, sí se podría llamar DDoS, pero 4 TB al mes son apenas 1.5 MB por segundo
    6 millones de solicitudes al mes también son solo 2 solicitudes por segundo. A esta escala, el hecho de operar como un servicio monolítico no parece importar demasiado, sobre todo si se considera que Cloudflare atiende la mayoría de las solicitudes desde la caché del CDN

    • La inmensa mayoría de la web son sitios WordPress alojados en hosting multiusuario de 5 a 20 dólares al mes, y en organizaciones más grandes muchas veces es Drupal. No tienen caché instalada y se conectan directamente a la base de datos, así que la mayoría de los sitios de internet pueden caerse con apenas 4 solicitudes por segundo

      Suena a locura, pero así es la realidad. Antes gestioné en Cloudflare defensa contra DDoS, WAF, firewall y proyectos de seguridad para clientes, y vi con frecuencia cómo sitios de clientes se caían solo por web scraping o por tasas de solicitudes HTTP muy pequeñas y triviales

      Los números grandes se llevan los titulares, pero lo que la mayoría de la gente realmente experimenta son números pequeños

    • Un ataque de denegación de servicio puede ser posible con apenas unos KB por hora. Si se golpea un endpoint de API pesado del servicio objetivo, eso por sí solo puede tumbar el servicio, y “Distributed” solo significa que varias máquinas atacan al mismo tiempo

      Un DDoS no necesariamente requiere un caudal enorme. Solo que los que salen en las noticias suelen ser ataques grandes

      El objetivo de estos ataques puede ser consumir la cuota de ancho de banda del servidor de origen o hacer que los costos de ancho de banda se vuelvan impagables. Se puede hacer muy barato incluso con una sola máquina atacante o con unas pocas. La mayoría de los datacenters y proveedores de hosting tienen límites de ancho de banda o cobran después de cierta cantidad, y demasiadas veces la empresa atacada se da cuenta recién cuando recibe una factura que no puede pagar

    • Tengo un sitio web de descargas de un juego con unos 50 jugadores en total. Nadie lo usa, y probablemente una persona real descargue el juego solo unas cuantas veces al mes
      Pero un solo archivo zip de 2 GB generó 5 TB de tráfico el mes pasado, y esto lleva años pasando. Esto no es un DDoS, sino simplemente bots/crawlers mal configurados que siguen todos los enlaces y no logran cancelar las descargas

    • Parece que es alrededor de 1 TB al día, pero aun así sigue siendo muy poco

    • Supongo que depende de qué tan irregular sea el tráfico

  • Esto no es más que un sitio estático de marketing para una app de escritorio. No tiene foro de discusión y el feedback se gestiona con issues de GitHub
    Es bastante extraño presumir de lo simple que es desplegar un sitio estático y de que aguanta cientos de millones de descargas diarias de archivos estáticos. Además, quien hace la mitigación aquí es Cloudflare, no ellos. Eso si es que un tráfico tan pequeño necesita mitigación

    Si yo recibiera un “ataque” así, probablemente ni me habría dado cuenta hasta recibir el correo mensual de Cloudflare que dice “X TB transferidos, casi 100% de ahorro de ancho de banda”

    La app en sí me gusta y la recomendaría

    • A mí también me gusta la app, pero este artículo suena como si le hubieran pedido a ChatGPT que hiciera un texto de marketing peculiar. En conjunto no tiene mucho sentido, y menos aún para alguien que haya pasado por un ataque DDoS real
    • Me gustaría ver más gente “presumiendo de lo simple que es el despliegue”. Cuanto más entienda la gente que su infraestructura excesivamente compleja no es lo óptimo, mejor
  • Esto, por la descripción, parece más bien unos 8 TB mensuales de tráfico adicional por “abuso del servicio molesto e inútil”, más que un ataque DDoS
    Mientras ese abuso no genere costos ni problemas de agotamiento de recursos, está bien ignorarlo, pero historias como “resultó que el 80% de la capacidad de la flota con autoescalado no estaba haciendo nada útil” son deprimentemente comunes, así que como mínimo conviene vigilarlo

    La parte más molesta de este tipo de abuso suelen ser los logs. La mayor parte de los logs termina llena de los mismos hosts repitiendo exactamente las mismas acciones inútiles. Si el almacenamiento de logs es barato y abundante, no es un gran problema, pero tener una forma de clasificar automáticamente cierto tráfico como abuso y suprimir su procesamiento cotidiano sin duda es una buena idea

    Aunque no es tan fácil como suena. Perdí la cuenta de cuántas veces añadí lógica de clasificación a servidores SMTP entrantes para detectar abuso evidente y tonto, y cada vez terminaba atrapando también escenarios limítrofes pero válidos

    Si uno pasa demasiado tiempo en una cadena de madrigueras de conejo, es fácil dejar de hacer el trabajo real. Por eso a veces conviene subcontratarlo, o, si eso también es demasiado engorroso o caro, simplemente ignorar el abuso aunque sea molesto

    • En AWS, 8 TB de tráfico saliente cuestan 595 dólares incluso considerando 1 TB mensual gratis, mientras que en Hetzner empiezan por menos de 10 dólares
      En DigitalOcean, por ejemplo, se pagan 30 dólares por los 3 TB excedentes sobre los 5 TB incluidos en s-4vcpu-8gb-intel, y en Linode el excedente de 3 TB cuesta 15 dólares. Así que creo que el artículo sí tiene un punto
    • Si lo sigues ignorando, estás incentivando que hagan cosas más sospechosas. Esa actitud convirtió gran parte de internet actual casi en un pantano
  • Este no es un “ataque” digno de atención. Bastaría con un solo script de bash desbocado en la máquina de alguien
    “50 millones de solicitudes al mes desde el Reino Unido” ni siquiera llega a un promedio de 20 solicitudes por segundo. Esperaría que un único servidor Go manejara 250 veces ese volumen de solicitudes sin grandes optimizaciones

    El consejo en sí no es necesariamente malo, pero esos números no son prueba de que el consejo sea válido. Para un servicio de API HTTP en Go, esperaría que en un VPS pequeño a mediano procese 5 mil solicitudes por segundo sin optimización, incluso con algo de trabajo de base de datos y formateo JSON. Es una cifra basada en mi experiencia desplegando decenas de servicios similares en un lugar que recibía miles de millones de solicitudes al día y que en picos superaba las 500 mil solicitudes por segundo

    • Si ese tráfico llega a la API como solicitudes repetidas y todas vienen de ubicaciones que no parecen sospechosas, antes de pensar en un DDoS habría que considerar si por error se metió un bucle infinito de reintentos en el código del cliente
  • Está bien que esto no cause daño, pero me inquieta un poco tomarlo como consejo porque le faltan muchas piezas
    Está bien preferir distribuir binarios en lugar de Docker, pero ¿qué pasa con el host donde corre ese binario? Una de las razones para usar contenedores es empaquetar la configuración de endurecimiento de seguridad junto con el despliegue, para tener la certeza de que, cuando más adelante haga falta escalar, la configuración de seguridad sea la misma entre nodos

    El monolito del que se habla aquí puede subirse a un solo VPS, y eso está bien y además es barato. Pero si se cae o el hardware falla por cualquier motivo, puede haber un downtime bastante grande

    Otra cosa que me preocupa es que, si se mete todo en un monolito, se pierde la defensa en profundidad del stack de la aplicación. Si alguien compromete la app a través del frontend, puede llegar directo al almacén de datos del backend. Por eso mucha gente pone el almacén de datos detrás de un servicio web interno y lo bloquea con grupos de seguridad en una red privada separada del frontend, limitando la superficie de ataque a las acciones que se pueden realizar desde el navegador

    • No existe un mundo en el que aumentar la superficie de ataque mejore la seguridad

    • Si crees que instalar Docker deja asegurado el host, estás equivocado. ¿Cómo vas a configurar los hosts adicionales cuando escales?

      Con Docker, no solo el contenedor debe ser seguro, también el host, es decir, el servicio que ejecuta los contenedores. Y cuando escales y despliegues más hosts, tienen que ser igual de seguros

      Si usas infraestructura como código y configuración como código, en esencia no hay diferencia entre desplegar un binario después de configurar el sistema o desplegar Docker

    • Hay herramientas para hacer que una configuración “bare metal” sea relativamente reproducible. Por ejemplo, NixOS, Ansible y la creación de imágenes AMI de Amazon

    • Nunca entiendo del todo eso de “comprometer la app a través del frontend”. Una inyección SQL toca directamente el almacén de datos sin ejecución remota de código, y un XSS afecta horizontalmente a otros usuarios
      Entonces, ¿cómo se llega libremente desde el frontend hasta todo el backend? ¿La gente está ejecutando dentro de un servicio API en Go un intérprete de JavaScript con acceso a shell y llamando a eval sobre input del usuario? Técnicamente me suena demasiado forzado

    • Al final, ¿no es seguridad por oscuridad? ¿La idea es hacerlo tan complicado que, si nosotros no lo entendemos, los demás tampoco lo entenderán?

      Lo importante no es poner más muros, sino hacer que los muros no se puedan romper. Las interfaces reducen el rendimiento y aumentan la complejidad

  • Personalmente, esa expresión me molesta. “1 mil millones de solicitudes al mes” son aproximadamente 370 solicitudes por segundo. Es un nivel que un solo servidor bien configurado puede manejar, y definitivamente bastarían menos de 10
    Un único script de bash malicioso también podría generar ese volumen de tráfico

    • Gracias a los microservicios, necesitamos 45 nodos de Kubernetes para manejar 1000 solicitudes por segundo
    • Eso si las solicitudes están distribuidas uniformemente en el tiempo. Pero en un ataque, las solicitudes pueden dispararse de golpe y luego aplanarse, y aun así sumar 1 mil millones de solicitudes al mes sobre una base de 30 días
    • Ni siquiera hace falta un servidor bien configurado; después de que entre en acción el JVM JIT, un solo core podría hacerlo
  • No sé si perdí el sentido de la escala, pero decenas de miles de millones de solicitudes al mes no suenan como gran cosa. ¿Eso se considera un gran ataque DDoS?

    • Depende de quién pague el costo. Si haces hosting propio no es un problema, pero en serverless incluso ese nivel suele salir caro, sobre todo si es tráfico sin valor
    • Para una API razonablemente diseñada, 300 a 400 solicitudes de API por segundo no son una carga pesada. 300 a 400 solicitudes de archivos estáticos por segundo son menos que peanuts
    • Correcto. 1 mil millones de solicitudes al mes promedian 380 solicitudes por segundo, así que no es tan alto
    • Depende de varios factores. Normalmente la infraestructura se aprovisiona para el uso esperado, y el exceso de margen es desperdicio
  • Me gustó la parte de “crear un servicio monolítico para cada app que sea fácil de desplegar y mantener. Sin Docker, sin Kubernetes, sin dependencias, sin entorno de runtime; solo un archivo binario que se puede desplegar en cualquier VPS recién creado”

    • No uso TablePlus directamente. Si esto habla de un sitio web de marketing, es obvio que no hace falta Kubernetes
      Si habla de la aplicación, me resulta raro lo de no tener dependencias. ¿No almacena datos ni genera logs?

    • Esta es una ventaja realmente excelente de Golang. Levantas un VPS, aplicas valores predeterminados razonables, compilas cruzado y ejecutas el binario

      Comparado con desplegar Python, Node o PHP, hay mucha menos complejidad innecesaria

      Ojalá ejecutar y mantener vivo un servidor de base de datos pudiera ser igual de simple

  • Por el título esperaba algo más acorde con swole doge. Estoy de acuerdo con gran parte de los consejos, pero estar detrás de Cloudflare no es para nada lo mismo que no tener nada
    Según la distribución del tráfico, tal vez solo con un VPS, sin Cloudflare, también habría aguantado bien, y la escala tampoco parece tan grande. Habría sido interesante ver estadísticas más detalladas, como solicitudes por segundo y cuánto bloqueó Cloudflare antes de que llegara al origen

    Un DDoS de capa 7 originado en Rusia contra empresas suecas que conozco fue tan grande que hizo caer a proveedores importantes por problemas de capacidad. Incluidos Verizon, Azure Frontdoor, Cloudflare y el balanceador de carga de GCP. Contra una escala así, esta estrategia jamás funcionaría