La capacidad de descartar paquetes de manera rápida es muy importante para resistir los ataques DDoS.
La eliminación de paquetes que afectan a nuestros servidores, tan simple como suena, se puede hacer en varias capas. Cada técnica tiene sus ventajas y limitaciones. En esta publicación de blog, analizaremos todas las técnicas que hemos probado hasta ahora.
Para ilustrar el rendimiento relativo de los métodos, mostraremos algunas cifras. Los parámetros son sintéticos, de manera que hay que tomar las cifras con cautela. Usaremos uno de nuestros servidores Intel, con una tarjeta de red de 10 Gbps. Los detalles de hardware no son demasiado importantes, ya que las pruebas están preparadas para mostrar las limitaciones del sistema operativo, no del hardware.
Nuestra configuración de pruebas se prepara de la siguiente manera:
Transmitimos una gran cantidad de paquetes pequeños del protocolo de datagramas del usuario (UDP) y se alcanzan 14Mpps (millones de paquetes por segundo).
Este tráfico se dirige hacia una sola CPU en un servidor de destino.
Medimos la cantidad de paquetes que administra el núcleo en esa CPU.
No estamos tratando de maximizar la velocidad de la aplicación del espacio del usuario, ni la tasa de transferencia efectiva de los paquetes, sino que tratamos de mostrar específicamente los cuellos de botella del núcleo.
El tráfico sintético está preparado para poner el máximo esfuerzo en el seguimiento de conexiones (conntrack). Utiliza el IP de origen aleatorio y los campos de puerto. Tcpdump lo mostrará de la siguiente manera:
$ ss -A raw,packet_raw -l -p|cat\nNetid State Recv-Q Send-Q Local Address:Port\np_raw UNCONN 525157 0 *:vlan100 users:(("tcpdump",pid=23683,fd=3))
\n
La evaluación comparativa siempre es difícil. Al preparar las pruebas, aprendimos que tener sockets activos sin procesar arruina el rendimiento. Es obvio en retrospectiva, pero suele pasarse por alto. Antes de ejecutar cualquier prueba, asegúrese de no tener ningún proceso tcpdump obsoleto en ejecución. Esta es la manera de comprobarlo, mostrando un proceso activo defectuoso:
\n
echo 1 | sudo tee /sys/devices/system/cpu/intel_pstate/no_turbo
\n
Por último, desactivaremos la función Intel Turbo Boost en el equipo:
\n \n \n \n \n
echo 1 | sudo tee /sys/devices/system/cpu/intel_pstate/no_turbo
Si bien Turbo Boost mejora el rendimiento en al menos un 20%, también empeora considerablemente la desviación estándar en nuestras pruebas. Con Turbo activado, tuvimos una desviación de ±1,5% en nuestras cifras. Con Turbo desactivado, la desviación se reduce a un 0,25%, cifra que resulta controlable.
s = socket.socket(AF_INET, SOCK_DGRAM)\ns.bind(("0.0.0.0", 1234))\nwhile True:\n s.recvmmsg([...])
\n
Comencemos con la idea de enviar paquetes a una aplicación e ignorarlos en el código del espacio de usuario. Para la configuración de prueba, verifiquemos que nuestro iptables no afecte al rendimiento:
Esta configuración permite que el núcleo reciba un escaso 175kpps de la cola de recepción de hardware, medido por ethtooly utilizando nuestra sencilla herramientammwatch:
El hardware técnicamente quita 14Mpps del cable, pero es imposible pasarlo todo a una sola cola RX administrada por un solo núcleo de CPU que realiza el trabajo del núcleo. mpstat confima esto:
Como se puede observar, el código de la aplicación no es un cuello de botella, utiliza 27% del sistema + 2% de espacio de usuario en CPU #1, mientras que la red SOFTIRQ en CPU #2 utiliza el 100% de los recursos.
Por cierto, el uso de recvmmsg(2) es importante. En estos días posteriores a Spectre, las llamadas del sistema se encarecieron más y, de hecho, ejecutamos el núcleo 4.14 con KPTI y retpolines:
Diseñamos específicamente la prueba, mediante la elección de IP y puertos de origen aleatorios, para poner el acento en la capa de conntrack. Esto se puede verificar al observar la cantidad de entradas de conntrack, que durante la prueba alcanzan el máximo:
Esto instantáneamente aumenta el rendimiento de recepción de la aplicación a 333kpps. ¡Bravo!
PS. Con SO_BUSY_POLL podemos aumentar las cifras a 470k pps, pero trataremos este tema en otro momento.
\n
$ ./bpf-drop\npackets=0 bytes=0
\n
Paso 3. Eliminación del BPF en unsocket
Si vamos aún más allá, ¿por qué enviar paquetes a la aplicación de espacio de usuario? Si bien esta técnica es poco común, podemos adjuntar un filtro BPF clásico a un socketSOCK_DGRAM con setsockopt( SO_ATTACH_FILTER ) y programar el filtro para descartar paquetes en el espacio del núcleo.
Con las eliminaciones en el BPF (tanto el clásico como el eBPF extendido tienen un rendimiento similar) procesamos aproximadamente 512 kpps. Todos ellos se eliminan en el filtro BPF mientras están todavía en el modo de interrupción de software, lo que genera un ahorro de la CPU necesaria para activar la aplicación del espacio de usuario.
Paso 4. ELIMINACIÓN de iptables después del enrutamiento
\n
$ mmwatch 'iptables -L -v -n -x | head'\n\nChain INPUT (policy DROP 0 packets, 0 bytes)\n pkts bytes target prot opt in out source destination\n605.9k/s 26.7m/s DROP udp -- * * 0.0.0.0/0 198.18.0.12 udp dpt:1234
\n
Como paso siguiente, simplemente podemos eliminar paquetes en la cadena de ENTRADA de firewall de iptables mediante la adición de una regla como la siguiente:
Este es un salto bastante significativo en el rendimiento, no lo entiendo del todo. O bien nuestra capa de enrutamiento es inusualmente compleja o hay un error en nuestra configuración de servidor.
En cualquier caso, la tabla de iptables “sin formato” es definitivamente mucho más rápida.
Paso 6. ELIMINACIÓN de nftables antes de CONNTRACK
En estos días, iptables es parte del pasado. La novedad es nftables. Mire estevideo para obtener una explicación técnica de por qué nftables es superior. Nftables promete más velocidad que la anterior iptables por muchas razones, entre ellas hay un rumor de que retpolines (también conocida como: sin ejecución especulativa para saltos indirectos) perjudica bastante a iptables.
Como el objetivo de este artículo no es comparar la velocidad de nftables con la de iptables, solo probaremos la eliminación más rápida que encontré:
\n
tc qdisc add dev vlan100 ingress\ntc filter add dev vlan100 parent ffff: prio 4 protocol ip u32 match ip protocol 17 0xff match ip dport 1234 0xffff match ip dst 198.18.0.0/24 flowid 1:1 action drop\ntc filter add dev vlan100 parent ffff: protocol ipv6 u32 match ip6 dport 1234 0xffff match ip6 dst fd00::/64 flowid 1:1 action drop
\n
Los contadores se pueden ver con este comando:
\n
$ mmwatch 'tc -s filter show dev vlan100 ingress'\nfilter parent ffff: protocol ip pref 4 u32 \nfilter parent ffff: protocol ip pref 4 u32 fh 800: ht divisor 1 \nfilter parent ffff: protocol ip pref 4 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 (rule hit 1.8m/s success 1.8m/s)\n match 00110000/00ff0000 at 8 (success 1.8m/s ) \n match 000004d2/0000ffff at 20 (success 1.8m/s ) \n match c612000c/ffffffff at 16 (success 1.8m/s ) \n action order 1: gact action drop\n random type none pass val 0\n index 1 ref 1 bind 1 installed 1.0/s sec\n Action statistics:\n Sent 79.7m/s bytes 1.8m/s pkt (dropped 1.8m/s, overlimits 0 requeues 0) \n backlog 0b 0p requeues 0
\n
El enlace “ingress” (entrada) de nftables se conecta aproximadamente a 1.53mpps. Esto es ligeramente más lento que iptables en la capa de PREENRUTAMIENTO. Esto resulta desconcertante, teóricamente la “entrada” ocurre antes del PREENRUTAMIENTO, por lo tanto, debería ser más veloz.
En nuestra prueba, nftables fue un poco más lento que iptables, pero no demasiado. Nftables es aún mejor :P
Paso 7. ELIMINACIÓN de controlador de entrada de tc (control de tráfico)
El hecho sorprendente es que un enlace de entrada de tc (control de tráfico) ocurra incluso antes del PREENRUTAMIENTO. tc hace los posible por seleccionar paquetes en función de criterios básicos y, de hecho, los elimina. La sintaxis es bastante torpe, por lo que se recomienda utilizar este script para configurarla. Necesitamos una coincidencia de tc un poco más compleja, esta es la línea de comandos:
Podemos verificarla:
Un enlace de entrada de tc que coincide con u32 nos permite eliminar 1.8mpps en una sola CPU. ¡Esto es genial!
Pero podemos ir aún más rápido...
\n
ip link set dev ext0 xdp obj xdp-drop-ebpf.o
\n
Paso 8. XDP_DROP
Por último, el arma fundamental es XDP - eXpress Data Path. Con XDP podemos ejecutar el código eBPF en el contexto de un controlador de red. Lo más importante, es que esto es anterior a la asignación de memoriaskbuff, lo que permite grandes velocidades.
\n
if (h_proto == htons(ETH_P_IP)) {\n if (iph->protocol == IPPROTO_UDP\n && (htonl(iph->daddr) & 0xFFFFFF00) == 0xC6120000 // 198.18.0.0/24\n && udph->dest == htons(1234)) {\n return XDP_DROP;\n }\n}
\n
Por lo general, los proyectos XDP tienen dos partes:
\n
$ ip link show dev ext0\n4: ext0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdp qdisc fq state UP mode DEFAULT group default qlen 1000\n link/ether 24:8a:07:8a:59:8e brd ff:ff:ff:ff:ff:ff\n prog/xdp id 5 tag aedc195cc0471f51 jited
\n
el código eBPF cargado en el contexto del núcleo
el cargador de espacio de usuario, que carga el código en la tarjeta de red correcta y lo administra
El código fuente para el programa eBPF de XDP cargado está disponible aquí. El programa analiza los paquetes de IP y busca las características deseadas: Transporte IP, protocolo UDP, subred de destino deseada y puerto de destino:
El programa XDP debe compilarse con un clang moderno que pueda emitir código de bytes BPF. Después de esto podemos cargar y verificar el programa XDP en ejecución:
\n \n \n \n \n
Y ver los números en las estadísticas de la tarjeta de red ethtool-S:
¡Guau! Con XDP podemos eliminar 10 millones de paquetes por segundo en una sola CPU.
Repetimos esto para IPv4 e IPv6 y preparamos este gráfico:
En términos generales, en nuestra configuración IPv6 tenía un rendimiento ligeramente menor. Recuerde que los paquetes IPv6 son ligeramente más grandes, por lo tanto, es inevitable cierta diferencia de rendimiento.
\n \n \n \n \n
Linux tiene varios enlaces que se pueden utilizar para filtrar paquetes, cada uno con diferente rendimiento y características fáciles de usar.
A los fines de DDoS, puede ser totalmente razonable simplemente recibir los paquetes en la aplicación y procesarlos en el espacio de usuario. Las aplicaciones correctamente ajustadas pueden obtener cifras bastante aceptables.
Para los ataques DDoS con IP de origen aleatorio /falsificado, podría valer la pena desactivar conntrack para ganar algo de velocidad. Sin embargo, tenga cuidado, conntrack es muy útil para combatir ciertos ataques.
En otras circunstancias, puede tener sentido integrar el firewall de Linux en la canalización de mitigación de DDoS. En tales casos, recuerde poner las mitigaciones en una capa “-t raw PREROUTING”, ya que es significativamente más rápida que la tabla “filtro”.
Para cargas de trabajo aún más exigentes, siempre contamos con XDP. Y vaya si es potente. Este es el mismo gráfico que se mostró anteriormente, pero ahora incluye XDP:
Aquí en Cloudflare usamos... casi todas estas técnicas. Algunos de los trucos del espacio de usuario están integrados con nuestras aplicaciones. La capa iptables está administrada por nuestra canalización Gatebot DDoS. Por último, estamos trabajando en el reemplazo de nuestra propia solución de descarga del núcleo con XDP.
¿Quiere ayudarnos a eliminar más paquetes? ¡Estamos contratando personal para cubrir varios cargos, que incluyen personal encargado de eliminar paquetes, ingenieros de sistemas y más!
"],"published_at":[0,"2018-07-06T14:00:00.000+01:00"],"updated_at":[0,"2024-10-10T00:33:14.779Z"],"feature_image":[0,"https://cf-assets.www.cloudflare.com/zkvhlag99gkb/2AaLqkJOn4yMNV7GNOhWxy/7f2dfba0311ce439865f1f9063c264d0/how-to-drop-10-million-packets.png"],"tags":[1,[[0,{"id":[0,"64g1G2mvZyb6PjJsisO09T"],"name":[0,"DDoS"],"slug":[0,"ddos"]}],[0,{"id":[0,"4LtMoX5pkj38ujzMRVhgvC"],"name":[0,"Mitigation"],"slug":[0,"mitigation"]}],[0,{"id":[0,"6QVJOBzgKXUO9xAPEpqxvK"],"name":[0,"Reliability"],"slug":[0,"reliability"]}],[0,{"id":[0,"5kIxDMJCg3PXQxVINDL0Cw"],"name":[0,"Ataques"],"slug":[0,"attacks"]}],[0,{"id":[0,"6Mp7ouACN2rT3YjL1xaXJx"],"name":[0,"Seguridad"],"slug":[0,"security"]}]]],"relatedTags":[0],"authors":[1,[[0,{"name":[0,"Marek Majkowski"],"slug":[0,"marek-majkowski"],"bio":[0,null],"profile_image":[0,"https://cf-assets.www.cloudflare.com/zkvhlag99gkb/1JuU5qavgwVeqR8BAUrd6U/3a0d0445d41c9a3c42011046efe9c37b/marek-majkowski.jpeg"],"location":[0,null],"website":[0,null],"twitter":[0,"@majek04"],"facebook":[0,null]}]]],"meta_description":[0,null],"primary_author":[0,{}],"localeList":[0,{"name":[0,"How to drop 10 million packets per second Config"],"enUS":[0,"English for Locale"],"zhCN":[0,"Translated for Locale"],"zhHansCN":[0,"No Page for Locale"],"zhTW":[0,"No Page for Locale"],"frFR":[0,"Translated for Locale"],"deDE":[0,"Translated for Locale"],"itIT":[0,"No Page for Locale"],"jaJP":[0,"No Page for Locale"],"koKR":[0,"Translated for Locale"],"ptBR":[0,"No Page for Locale"],"esLA":[0,"No Page for Locale"],"esES":[0,"Translated for Locale"],"enAU":[0,"No Page for Locale"],"enCA":[0,"No Page for Locale"],"enIN":[0,"No Page for Locale"],"enGB":[0,"No Page for Locale"],"idID":[0,"No Page for Locale"],"ruRU":[0,"No Page for Locale"],"svSE":[0,"No Page for Locale"],"viVN":[0,"No Page for Locale"],"plPL":[0,"No Page for Locale"],"arAR":[0,"No Page for Locale"],"nlNL":[0,"No Page for Locale"],"thTH":[0,"No Page for Locale"],"trTR":[0,"No Page for Locale"],"heIL":[0,"No Page for Locale"],"lvLV":[0,"No Page for Locale"],"etEE":[0,"No Page for Locale"],"ltLT":[0,"No Page for Locale"]}],"url":[0,"https://blog.cloudflare.com/how-to-drop-10-million-packets"],"metadata":[0,{"title":[0],"description":[0],"imgPreview":[0,""]}]}],"locale":[0,"es-es"],"translations":[0,{"posts.by":[0,"De:"],"footer.gdpr":[0,"RGPD"],"lang_blurb1":[0,"Esta publicación también está disponible en {lang1}."],"lang_blurb2":[0,"Esta publicación también está disponible en {lang1} y {lang2}."],"lang_blurb3":[0,"Esta publicación también está disponible en {lang1}, {lang2} y {lang3}."],"footer.press":[0,"Prensa"],"header.title":[0,"Blog de Cloudflare"],"search.clear":[0,"Borrar"],"search.filter":[0,"Filtrar"],"search.source":[0,"Fuente"],"footer.careers":[0,"Empleo"],"footer.company":[0,"Empresa"],"footer.support":[0,"Asistencia"],"footer.the_net":[0,"theNET"],"search.filters":[0,"Filtros"],"footer.our_team":[0,"Nuestro equipo"],"footer.webinars":[0,"Seminarios web"],"page.more_posts":[0,"Más publicaciones"],"posts.time_read":[0,"{time} min de lectura"],"search.language":[0,"Idioma"],"footer.community":[0,"Comunidad"],"footer.resources":[0,"Recursos"],"footer.solutions":[0,"Soluciones"],"footer.trademark":[0,"Marca"],"header.subscribe":[0,"Suscribirse"],"footer.compliance":[0,"Conformidad"],"footer.free_plans":[0,"Planes gratuitos"],"footer.impact_ESG":[0,"Impact/ESG"],"posts.follow_on_X":[0,"Síguenos en X"],"footer.help_center":[0,"Centro de ayuda"],"footer.network_map":[0,"Mapa de red"],"header.please_wait":[0,"Un momento..."],"page.related_posts":[0,"Publicaciones relacionadas"],"search.result_stat":[0,"Resultados {search_range} de {search_total} para {search_keyword}"],"footer.case_studies":[0,"Casos prácticos"],"footer.connect_2024":[0,"Connect 2024"],"footer.terms_of_use":[0,"Condiciones de uso"],"footer.white_papers":[0,"Notas técnicas"],"footer.cloudflare_tv":[0,"Cloudflare TV"],"footer.community_hub":[0,"Foro de comunidad"],"footer.compare_plans":[0,"Comparar planes"],"footer.contact_sales":[0,"Comunícate con el departamento de ventas"],"header.contact_sales":[0,"Comunícate con el departamento de ventas"],"header.email_address":[0,"Dirección de correo electrónico"],"page.error.not_found":[0,"Página no encontrada"],"footer.developer_docs":[0,"Documentación para desarrolladores"],"footer.privacy_policy":[0,"Política de privacidad"],"footer.request_a_demo":[0,"Solicita una demostración"],"page.continue_reading":[0,"Seguir leyendo"],"footer.analysts_report":[0,"Informes de analistas"],"footer.for_enterprises":[0,"Para empresas"],"footer.getting_started":[0,"Primeros pasos"],"footer.learning_center":[0,"Centro de aprendizaje"],"footer.project_galileo":[0,"Proyecto Galileo"],"pagination.newer_posts":[0,"Publicaciones más recientes"],"pagination.older_posts":[0,"Publicaciones anteriores"],"posts.social_buttons.x":[0,"Comenta en X"],"search.icon_aria_label":[0,"Buscar"],"search.source_location":[0,"Origen/Ubicación"],"footer.about_cloudflare":[0,"Acerca de Cloudflare"],"footer.athenian_project":[0,"Proyecto Athenian"],"footer.become_a_partner":[0,"Ser socio"],"footer.cloudflare_radar":[0,"Cloudflare Radar"],"footer.network_services":[0,"Servicios de red"],"footer.trust_and_safety":[0,"Confianza y seguridad"],"header.get_started_free":[0,"Empieza ya de forma gratuita"],"page.search.placeholder":[0,"Buscar en Cloudflare"],"footer.cloudflare_status":[0,"Estado de Cloudflare"],"footer.cookie_preference":[0,"Preferencias de cookies"],"header.valid_email_error":[0,"Debe ser un correo electrónico válido."],"search.result_stat_empty":[0,"Resultados {search_range} de {search_total}"],"footer.connectivity_cloud":[0,"Conectividad cloud"],"footer.developer_services":[0,"Servicios para desarrolladores"],"footer.investor_relations":[0,"Relaciones con inversores"],"page.not_found.error_code":[0,"Código de error: 404"],"search.autocomplete_title":[0,"Inserta una consulta. Pulsa Intro para enviarla."],"footer.logos_and_press_kit":[0,"Logotipos y dossier de prensa"],"footer.application_services":[0,"Servicios para aplicaciones"],"footer.get_a_recommendation":[0,"Sugerencias"],"posts.social_buttons.reddit":[0,"Comenta en Reddit"],"footer.sse_and_sase_services":[0,"Servicios SSE y SASE"],"page.not_found.outdated_link":[0,"Puede que tengas un enlace obsoleto o que hayas escrito la dirección incorrectamente."],"footer.report_security_issues":[0,"Informar sobre problemas de seguridad"],"page.error.error_message_page":[0,"Lamentablemente, no podemos encontrar la página que buscas."],"header.subscribe_notifications":[0,"Suscríbete para recibir notificaciones de nuevas publicaciones:"],"footer.cloudflare_for_campaigns":[0,"Cloudflare for Campaigns"],"header.subscription_confimation":[0,"Suscripción confirmada. ¡Gracias por suscribirte!"],"posts.social_buttons.hackernews":[0,"Debatir en Hacker News"],"footer.diversity_equity_inclusion":[0,"Diversidad, equidad e inclusión"],"footer.critical_infrastructure_defense_project":[0,"Proyecto de protección de infraestructuras críticas"]}]}" ssr="" client="load" opts="{"name":"PostCard","value":true}" await-children="">
A veces, a nivel interno, a nuestro equipo de mitigación de DDoS se lo llama “packet droppers” (eliminadores de paquetes). Cuando otros equipos desarrollan productos interesantes para hacer cosas inteligentes con el tráfico que pasa a través de nuestra red, ...
En los últimos dos días, hemos visto un gran aumento en un extraño vector de ataque de amplificación, que usa el protocolo Memcached, originado del puerto UDP 11211....
¡Esta semana cumplimos 7 años! Se ha vuelto una tradición para nosotros anunciar una serie de productos cada día de esta semana, así como nuevas e importantes ventajas para nuestros clientes. Comenzamos con la mitigación ilimitada, de la que me siento especialmente orgulloso...