From 618dcfd851f4090edc57902d9b4f23ea2fe86fc9 Mon Sep 17 00:00:00 2001 From: Sergio Date: Wed, 16 Sep 2026 13:33:50 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=A8=20el=20cortafuegos=20baneaba=20a?= =?UTF-8?q?=20los=20usuarios=20del=20proxy=20=E2=80=94=20y=20squid=20nunca?= =?UTF-8?q?=20se=20cay=C3=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Preguntaron si el proxy estaba caído. NO lo estaba: el ente llevaba horas corriendo con ↻ 0 y contestando 407. Lo caído era el ACCESO — el cortafuegos de ayer baneaba a los autorizados. La prueba en una línea: **154.197.1.2, una IP que está en la ACL de squid (gente con contraseña), apareció en `@ban4`**, con el contador del ban en 38.246 paquetes tirados. LA CAUSA NO ES LA TASA, ES LA RÁFAGA: `limit rate over 300/minute burst 5 packets` tolera cinco conexiones por encima del promedio, y un navegador o un agente detrás de un proxy abre DECENAS de CONNECT en el mismo instante aunque su promedio sea bajísimo. Y como @ban4 es UN SOLO set consultado antes que todo, caer por el puerto del proxy te tira también el web y el git. ⚠ El tipo ya traía el campo `rafaga` (default 5) con un comentario que dice «para un servicio web va alto (100-200)». Otra vez leí el .ron de EJEMPLO y no el TIPO. Hecho, en orden de urgencia: flush de los sets (servicio restaurado en el acto) · los 21 IPs y 5 redes de la ACL de squid a `confiables` · `rafaga` por servicio según su clientela (ssh 5, git 20, web 100, proxy 200) · proxy a 1200/min con ban de 60 s, que es red de contención contra un flood y no control de uso. Control después: CERO autorizados en el set, 24 baneados (escáneres) y tráfico real pasando —`154.194.14.37 … CONNECT api.deepseek.com:443 sigma`, 298 K tunelados—. ⚠⚠ Y un fallo de método que casi lo tapa: **`nft -f` SUMA a la tabla existente**. Cargué el reglaset corregido encima del viejo y quedaron 30 reglas con las VIEJAS ADELANTE, así que los `confiables` nuevos no se evaluaban nunca. Por eso `cortafuegos apply-input` borra la tabla antes de cargar. La lección: un cortafuegos correcto y uno usable no son lo mismo, y la diferencia NO se ve al aplicarlo. El control que lo habría cazado es el que no corrí: una ráfaga de conexiones desde una IP que no esté en `confiables`. Co-Authored-By: Claude Opus 5 (1M context) --- docs/28-servidor-de-produccion.md | 45 ++++++++++++++++++++++++ scripts/servidor/cortafuegos-entrada.ron | 45 ++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/docs/28-servidor-de-produccion.md b/docs/28-servidor-de-produccion.md index 22e4e825..f1944be5 100644 --- a/docs/28-servidor-de-produccion.md +++ b/docs/28-servidor-de-produccion.md @@ -1890,6 +1890,51 @@ Su guarda sale **78 nombrando el fichero** si el reglaset no está, en vez de de filtrar creyendo que está protegida: *un cortafuegos ausente y uno vacío se ven igual desde afuera hasta que alguien prueba*. +### 6.33 🧨 EL CORTAFUEGOS BANEÓ A LOS USUARIOS DEL PROXY — y squid nunca se cayó *(2026-09-16)* + +El usuario preguntó si el proxy estaba caído. **No lo estaba**: el ente `squid` llevaba horas +`corriendo` con `↻ 0`, escuchando en `:1137` y contestando `407` a quien preguntara. Lo que estaba +caído era **el acceso**: el cortafuegos que puse ayer estaba baneando a los usuarios autorizados. + +La prueba, en una línea: **`154.197.1.2` —una IP que está en la ACL de squid, o sea gente con +contraseña— apareció en `@ban4`**. Y el contador del ban iba en **38.246 paquetes tirados**. + +#### La causa no es la tasa: es la RÁFAGA + + tcp dport 1137 ct state new add @ban4 { ip saddr timeout 300s limit rate over 300/minute burst 5 packets } drop + +`burst 5` significa «tolero cinco conexiones por encima del promedio». **Un navegador o un agente +detrás de un proxy abre decenas de CONNECT en el mismo instante**, aunque su promedio sea bajísimo: +seis de golpe y ya estás en el set. Y como **`@ban4` es UN SOLO set consultado antes que todo**, +caer por el puerto del proxy te tira también el web y el git. + +⚠ El tipo del cortafuegos ya traía el campo (`rafaga`, default 5) con un comentario que decía +«para un servicio web va alto (100-200)». Otra vez: **leí el `.ron` de ejemplo y no el tipo**. + +#### Lo que se hizo, en orden de urgencia + +1. **`nft flush set … ban4/ban6`** — servicio restaurado en el acto. +2. **Los usuarios del proxy a `confiables`**: la misma lista que la ACL de squid (21 IPs + 5 redes). + Un proxy que autentica no necesita que el kernel le cuente las conexiones a un usuario conocido; + lo que el ban tiene que parar son las fuentes DESCONOCIDAS. +3. **`rafaga` por servicio, según su clientela**: ssh 5 · git 20 · web 100 · **proxy 200**. Y el + proxy pasa a `1200/min` con ban de 60 s: red de contención contra un flood, no control de uso. +4. Control después: **cero autorizados en el set**, 24 baneados (escáneres, que es lo que se quiere), + y tráfico real pasando — `154.194.14.37 … CONNECT api.deepseek.com:443 sigma`, 298 K tunelados. + +⚠⚠ **Y un fallo de método que casi lo tapa: `nft -f` SUMA a la tabla existente.** Cargué el reglaset +corregido encima del viejo y quedaron **30 reglas**: las viejas ADELANTE, así que los `confiables` +nuevos no llegaban a evaluarse nunca. Se vio contando (`grep -c dport` daba 30 y no 15) y mirando +qué `saddr` salía primero. Por eso `cortafuegos apply-input` **borra la tabla antes de cargar** — +usar `nft -f` a pelo se saltea esa mitad. + +#### Lo que esto enseña del cortafuegos como herramienta + +Un cortafuegos correcto y un cortafuegos usable no son lo mismo, y la diferencia **no se ve al +aplicarlo**: las reglas cargan, el `nft -c` pasa, los sitios responden, y el daño aparece sólo cuando +un cliente REAL hace lo que los clientes reales hacen. El único control que lo habría cazado antes es +el que no corrí: **una ráfaga de conexiones desde una IP que NO esté en `confiables`**. + ## 7. Reusar los scripts que ya existen, y no escribir de nuevo Pedido explícito del usuario. El inventario de lo que ya hace el trabajo: diff --git a/scripts/servidor/cortafuegos-entrada.ron b/scripts/servidor/cortafuegos-entrada.ron index 1c674b43..257086d7 100644 --- a/scripts/servidor/cortafuegos-entrada.ron +++ b/scripts/servidor/cortafuegos-entrada.ron @@ -30,6 +30,27 @@ "204.168.193.248", // dev.gioser.net: el worker de la granja. "154.197.1.13", + + // ── LOS USUARIOS DEL PROXY, Y ESTO NO ES OPCIONAL (2026-09-16) ──────────────────────── + // Es la MISMA lista que la ACL de squid (`/etc/squid/allowed_ssh_users.acl`): gente + // autorizada, con contraseña, que el cortafuegos baneó igual. Medido: `154.197.1.2` —que + // está en esa ACL— apareció en `@ban4` y perdió el proxy ENTERO. + // + // La causa es la mecánica del ban, no la tasa: la regla es `limit rate over N/minute burst + // 5 packets`, y **el burst de 5 no lo aguanta ningún cliente real** — un navegador o un + // agente abre decenas de CONNECT a la vez. Y como `@ban4` es UN SOLO set consultado antes + // que todo, caer por el puerto del proxy te tira también el web y el git. + // + // Un proxy con autenticación no necesita que el kernel le cuente las conexiones a un + // usuario conocido: lo que el ban tiene que parar son las fuentes DESCONOCIDAS. + "154.197.1.2", "154.197.1.7", "186.94.250.208", + "190.206.193.88", "190.206.212.233", "190.206.214.18", "190.206.215.35", + "190.206.246.187", "190.206.249.243", "190.206.254.167", "190.206.58.77", + "190.52.108.181", "200.84.33.134", "200.84.43.251", "200.84.55.166", + "200.93.92.169", "201.208.13.192", "201.208.211.104", "201.208.25.223", + "201.209.132.56", "201.211.110.96", "181.225.47.111", + "186.167.0.0/16", "190.72.0.0/16", "190.74.0.0/16", "190.77.0.0/16", + "45.234.60.0/24", ], drop_estados_invalidos: true, icmp_echo_por_seg: 10, @@ -44,6 +65,9 @@ conexiones_max: 10, nuevas_por_min: 5, ban_timeout_seg: 600, + // 5 está bien acá: una sesión ssh no abre veinte conexiones de golpe, y el operador + // está en `confiables` de todos modos. + rafaga: 5, ), ( puerto: 2345, @@ -54,6 +78,8 @@ conexiones_max: 20, nuevas_por_min: 15, ban_timeout_seg: 600, + // un `git clone` abre varias a la vez. + rafaga: 20, ), ( puerto: 80, @@ -62,6 +88,7 @@ conexiones_max: 200, nuevas_por_min: 60, ban_timeout_seg: 600, + rafaga: 100, ), ( puerto: 443, @@ -69,7 +96,10 @@ descripcion: "https — los siete dominios mudados", conexiones_max: 200, nuevas_por_min: 120, - ban_timeout_seg: 600, + // ⚠ Una página con 30 recursos son 30 conexiones nuevas EN UN INSTANTE. Con la ráfaga + // por defecto (5) un navegador normal se banea solo — el mismo defecto que sacó del aire + // al proxy el 2026-09-16, un piso más abajo. + rafaga: 100, ), ( puerto: 1137, @@ -79,8 +109,17 @@ // CONNECT nuevo. Un límite pensado para ssh acá BANEA A UN USUARIO LEGÍTIMO, que es // peor que no tener regla — el abuso que esto para es un flood, no un navegador. conexiones_max: 300, - nuevas_por_min: 300, - ban_timeout_seg: 300, + // ⚠ 1200/min y ban CORTO: acá el ban es una red de contención contra un flood de una + // fuente DESCONOCIDA, no un control de uso. Los usuarios de verdad están en + // `confiables` y no llegan nunca a esta regla. Con 300/min y `burst 5` se baneaba solo + // un cliente normal. + nuevas_por_min: 1200, + ban_timeout_seg: 60, + // ⚠⚠ LA RÁFAGA ES LO QUE LO ROMPIÓ, no la tasa. `limit rate over N/minute burst 5` + // banea a quien abre 6 conexiones DE GOLPE aunque su promedio sea bajísimo, y un agente + // o un navegador detrás de un proxy abre decenas. Medido: `154.197.1.2` —autorizado, con + // contraseña— terminó en `@ban4` y perdió el proxy entero. + rafaga: 200, ), ], )