Del `access.log`, sin ambigüedad. La IP del usuario (`45.234.61.160`, autenticada como `sergio`, 2709 peticiones) tuvo tres silencios: **93,2 min (11:59:37 → 13:32:49 UTC)**, 50,1 min (10:44:58 → 11:35:06) y 10,0 min (11:45:06 → 11:55:05). Los tres son el `timeout` de 10 minutos del ban disparándose una y otra vez: cada vez que volvía, su primera ráfaga lo baneaba de nuevo. El corte grande terminó exactamente cuando vacié los sets. 🧨 Y LA EXENCIÓN QUE TENÍA NO SERVÍA: la ACL histórica de squid exime `45.234.60.0/24` y él entra desde `45.234.61.160` — **una red de al lado**. Parecía cubierto y no lo estaba. La pertenencia se MIDE (`ip in red`), no se deduce del parecido del prefijo. DECISIÓN DE FONDO: en un servicio que YA AUTORIZA no va límite por tasa. El uso de esta caja es INTENSIVO —varias sesiones de agente en paralelo, cada una abriendo túneles a la vez— y un límite calibrado para «una persona normal navegando» no protege de nada: el atacante ajusta su ritmo, el usuario no puede trabajar más despacio. Squid ya pide usuario y contraseña y tiene su ACL. El ban del puerto queda apagado (60000/min, ráfaga 1000) y contra un flood queda el tope GLOBAL `syn_nuevas_por_seg`, que no distingue usuarios ni banea a nadie por ser rápido. Control tras aplicar: su túnel pasando —`45.234.61.160 … CONNECT api.anthropic.com:443 sergio`— y `45.234.61.160 ∈ 45.234.60.0/23` comprobado con aritmética de redes, no a ojo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
140 lines
8.0 KiB
Plaintext
140 lines
8.0 KiB
Plaintext
(
|
|
// Política de ENTRADA de la caja `takana` (2.29.29.217) — SDD 28 §6.32.
|
|
// Formato: `PoliticaEntrada` del cortafuegos de tawasuyu (shared/cortafuegos/SDD-ENTRADA.md).
|
|
//
|
|
// cortafuegos generate-input --policy scripts/servidor/cortafuegos-entrada.ron
|
|
// cortafuegos check-input --policy … (valida con `nft -c`)
|
|
// cortafuegos apply-input --policy … --yes (root; deniega TODO lo no listado)
|
|
//
|
|
// ⚠️ APLICAR ESTO SIN RED DE SEGURIDAD PUEDE DEJARTE FUERA: la caja NO tiene consola serie
|
|
// (hcloud), así que una regla mal puesta sólo se arregla por `hcloud server enable-rescue`.
|
|
// Se aplica con interruptor de hombre muerto: aplicar → comprobar desde fuera → confirmar, y
|
|
// si nadie confirma, un `nft flush ruleset` programado devuelve la máquina a como estaba.
|
|
//
|
|
// Esto es lo que REEMPLAZA a fail2ban, que no se mudó de gioser: el ban por IP lo hace el
|
|
// kernel con sets dinámicos, sin daemon que lea logs. Necesita `CONFIG_NF_TABLES` — el kernel
|
|
// de la caja no lo traía y por eso hubo que reconstruirlo (§6.30/§6.31).
|
|
// ── QUIÉN NUNCA SE BANEA ────────────────────────────────────────────────────────────────
|
|
// ⚠️ MEDIDO EL 2026-09-15, Y EL TIPO YA LO AVISABA: sin esto, el primer baneado fui yo. El
|
|
// `nuevas_por_min: 5` de administración es lo correcto contra internet y es exactamente lo que
|
|
// te deja afuera cuando el que abre seis sesiones por minuto sos vos — cada comando remoto es
|
|
// una conexión nueva. Y como el set `@ban4` es UNO SOLO para todos los servicios, caer en él
|
|
// por el puerto de ssh te tira TAMBIÉN el https, el proxy y el git: el `ip saddr @ban4 drop`
|
|
// está antes que todo. La caja quedó inaccesible en segundos y la devolvió el interruptor de
|
|
// hombre muerto.
|
|
//
|
|
// `confiables` acepta ANTES de la lógica de tasa, así que estas fuentes no pueden entrar al set.
|
|
confiables: [
|
|
// gioser: el hub que administra, cosecha y respalda esta caja. Se va a borrar cuando la
|
|
// mudanza termine, y entonces esta línea sale con él.
|
|
"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",
|
|
// ⚠ `45.234.61.0/24` TAMBIÉN, y esto es lo que causó el corte del 16-09: el usuario entra
|
|
// desde `45.234.61.160` —autenticado como `sergio`, 2709 peticiones— y la ACL de squid sólo
|
|
// exime al `.60.0/24`. Una IP de al lado no es la misma red: estuvo **93 minutos sin proxy**
|
|
// (11:59→13:32 UTC) más dos cortes previos de 50 y 10 minutos, que son el `timeout` de 10
|
|
// minutos del ban disparándose una y otra vez.
|
|
"45.234.61.0/24",
|
|
],
|
|
drop_estados_invalidos: true,
|
|
icmp_echo_por_seg: 10,
|
|
syn_nuevas_por_seg: 200,
|
|
servicios: [
|
|
(
|
|
puerto: 22022,
|
|
proto: Tcp,
|
|
descripcion: "ssh de ADMINISTRACIÓN — el único acceso a la caja",
|
|
// Apretado a propósito: por acá no entra nadie más que el operador, y es el puerto
|
|
// que fail2ban cuidaba en gioser.
|
|
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,
|
|
proto: Tcp,
|
|
descripcion: "ssh del gitea (git clone/push)",
|
|
// Más holgado que el de administración: un `git clone` abre varias conexiones y los
|
|
// clones legítimos vienen a ráfagas.
|
|
conexiones_max: 20,
|
|
nuevas_por_min: 15,
|
|
ban_timeout_seg: 600,
|
|
// un `git clone` abre varias a la vez.
|
|
rafaga: 20,
|
|
),
|
|
(
|
|
puerto: 80,
|
|
proto: Tcp,
|
|
descripcion: "http — caddy (redirección y ACME)",
|
|
conexiones_max: 200,
|
|
nuevas_por_min: 60,
|
|
ban_timeout_seg: 600,
|
|
rafaga: 100,
|
|
),
|
|
(
|
|
puerto: 443,
|
|
proto: Tcp,
|
|
descripcion: "https — los siete dominios mudados",
|
|
conexiones_max: 200,
|
|
nuevas_por_min: 120,
|
|
// ⚠ 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,
|
|
proto: Tcp,
|
|
descripcion: "squid — el proxy de salida, con usuarios reales detrás",
|
|
// ⚠️ EL MÁS HOLGADO DE TODOS, Y NO ES DESCUIDO: cada pestaña de un navegador es un
|
|
// 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,
|
|
// ⚠ 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.
|
|
ban_timeout_seg: 60,
|
|
// ⚠⚠ EL BAN POR TASA EN ESTE PUERTO ESTÁ EFECTIVAMENTE APAGADO, y es una decisión:
|
|
//
|
|
// · El servicio ya AUTORIZA: squid pide usuario y contraseña y tiene su propia ACL.
|
|
// Un ban por tasa no agrega seguridad, agrega falsos positivos.
|
|
// · El uso real de esta caja es INTENSIVO —varias sesiones de agente en paralelo, cada
|
|
// una abriendo túneles a la vez—, y un límite calibrado para «una persona normal
|
|
// navegando» no le sirve a nadie acá. Medido el 16-09: con 300/min y `burst 5`, el
|
|
// usuario principal perdió el proxy 93 minutos seguidos.
|
|
// · Lo que SÍ queda contra un flood es el `syn_nuevas_por_seg` global de arriba, que
|
|
// no distingue usuarios y no puede banear a nadie por ser rápido.
|
|
//
|
|
// El tipo exige > 0, así que se apaga con números que ningún cliente real alcanza.
|
|
nuevas_por_min: 60000,
|
|
rafaga: 1000,
|
|
),
|
|
],
|
|
)
|