<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hernan Valero</title>
    <description>The latest articles on DEV Community by Hernan Valero (@hernan_valero).</description>
    <link>https://dev.to/hernan_valero</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4206917%2F045638eb-0aae-4212-95af-1b194d887c81.png</url>
      <title>DEV Community: Hernan Valero</title>
      <link>https://dev.to/hernan_valero</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hernan_valero"/>
    <language>en</language>
    <item>
      <title>Le di memoria a Fail2Ban: la historia de ARE y la noche en que terminé baneándome a mí mismo</title>
      <dc:creator>Hernan Valero</dc:creator>
      <pubDate>Sun, 25 Oct 2026 17:34:37 +0000</pubDate>
      <link>https://dev.to/hernan_valero/le-di-memoria-a-fail2ban-la-historia-de-are-y-la-noche-en-que-termine-baneandome-a-mi-mismo-5ekk</link>
      <guid>https://dev.to/hernan_valero/le-di-memoria-a-fail2ban-la-historia-de-are-y-la-noche-en-que-termine-baneandome-a-mi-mismo-5ekk</guid>
      <description>&lt;p&gt;Fail2Ban hacía su trabajo, pero había situaciones en las que el resultado no me convencía. A veces bloqueaba lo que no debía y otras veces no parecía detectar lo que realmente me preocupaba.&lt;/p&gt;

&lt;p&gt;No quería sumar otra herramienta de seguridad a la lista. Quería resolver algo que, desde mi punto de vista, faltaba: que el servidor pudiera recordar el comportamiento de una IP y tomar decisiones teniendo en cuenta su historial, no solamente el último evento registrado.&lt;/p&gt;

&lt;p&gt;De esa idea nació ARE, &lt;em&gt;Abuse Reputation Engine&lt;/em&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🇬🇧 English version of this article: &lt;a href="https://dev.to/hernan_valero/i-gave-fail2ban-a-memory-the-story-of-are-and-the-night-i-ended-up-banning-myself-292f"&gt;https://dev.to/hernan_valero/i-gave-fail2ban-a-memory-the-story-of-are-and-the-night-i-ended-up-banning-myself-292f&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si preferís verlo antes que leerlo, 60-90s del escalado en vivo (WATCH → FILTER → TEMP_BAN):&lt;/p&gt;


&lt;div class="ltag_asciinema"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  No quería construir otro Fail2Ban
&lt;/h2&gt;

&lt;p&gt;Desde el principio tuve algo claro: no quería reinventar Fail2Ban ni escribir otro detector que hiciera prácticamente lo mismo.&lt;/p&gt;

&lt;p&gt;Fail2Ban ya cumplía una función útil. Analizaba registros, detectaba patrones de actividad sospechosa y podía aplicar sus propias sanciones. Lo que yo quería era aprovechar las detecciones y los informes de las herramientas que ya estaban funcionando en el servidor, no duplicar su trabajo.&lt;/p&gt;

&lt;p&gt;La idea detrás de ARE era reunir esas señales en un historial de reputación, relacionarlas con su categoría y gravedad, y dejar que el motor evaluara el conjunto antes de decidir cómo actuar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fail2Ban y los demás sensores aportan detecciones; ARE añade contexto, mantiene la reputación y toma decisiones según sus propias políticas.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No significa que Fail2Ban deje de aplicar sus reglas ni que todas las herramientas tengan exactamente la misma función. Significa que yo quería una capa adicional capaz de evaluar el comportamiento acumulado de una IP, en lugar de depender únicamente de decisiones tomadas por separado.&lt;/p&gt;

&lt;p&gt;Una detección aislada no siempre cuenta toda la historia. Pero cuando se combina con otros eventos y con lo que esa dirección ha venido haciendo a lo largo del tiempo, puede adquirir un significado distinto.&lt;/p&gt;

&lt;p&gt;No necesitaba otro detector compitiendo con los que ya tenía. Necesitaba una capa que pudiera aprovechar sus resultados, relacionarlos y tomar decisiones con una perspectiva más amplia.&lt;/p&gt;

&lt;h2&gt;
  
  
  El problema que quería resolver
&lt;/h2&gt;

&lt;p&gt;Las herramientas de seguridad que utilizamos habitualmente tienen una función concreta. Fail2Ban analiza eventos y aplica sanciones según las reglas configuradas. ModSecurity inspecciona peticiones HTTP y puede bloquear las que coinciden con determinadas reglas. Un firewall controla el tráfico según sus políticas.&lt;/p&gt;

&lt;p&gt;No tengo nada en contra de esas herramientas. Al contrario, forman parte de una buena defensa. El problema aparece cuando intentamos interpretar un comportamiento que no cabe fácilmente en una regla aislada.&lt;/p&gt;

&lt;p&gt;Un intento fallido de acceso puede ser un error legítimo. Una petición extraña puede ser un escáner. Una sucesión de intentos distribuidos en el tiempo puede revelar algo más preocupante que cualquiera de esos eventos por separado.&lt;/p&gt;

&lt;p&gt;¿Cómo distinguirlos?&lt;/p&gt;

&lt;p&gt;Me preocupaban dos escenarios. Por un lado, alguien que distribuye sus intentos para mantenerse por debajo de determinados umbrales. Por otro, un usuario legítimo que termina bloqueado porque una conexión inestable o una sucesión de peticiones normales se parece demasiado a un abuso.&lt;/p&gt;

&lt;p&gt;No pretendía resolver todos los problemas de seguridad con una sola herramienta. Quería añadir una pieza que ayudara a interpretar el contexto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La idea era sencilla: que una IP no empezara de cero cada vez que generaba un evento.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Así empezó a tomar forma ARE.&lt;/p&gt;

&lt;h2&gt;
  
  
  ARE: reputación en lugar de reacciones aisladas
&lt;/h2&gt;

&lt;p&gt;Desde el principio tuve claro que no quería introducir una infraestructura innecesariamente compleja. La idea era construir un motor que pudiera funcionar sobre un servidor Linux, apoyándose en herramientas conocidas y sin depender de un servicio externo.&lt;/p&gt;

&lt;p&gt;Bash, SQLite, IPSet y systemd. Componentes sencillos, accesibles y relativamente fáciles de inspeccionar.&lt;/p&gt;

&lt;p&gt;No necesitaba otro agente escrito en un lenguaje de moda ni una plataforma que obligara a mantener una infraestructura adicional. Necesitaba que la lógica de decisión fuera comprensible y que pudiera saber por qué el sistema había tomado una decisión determinada.&lt;/p&gt;

&lt;p&gt;El núcleo de ARE gira alrededor de varios principios.&lt;/p&gt;

&lt;h3&gt;
  
  
  No todos los eventos significan lo mismo
&lt;/h3&gt;

&lt;p&gt;Uno de los problemas que quería evitar era tratar todos los eventos sospechosos como si tuvieran la misma importancia.&lt;/p&gt;

&lt;p&gt;No es lo mismo detectar reconocimiento de puertos que registrar un intento de explotación. Tampoco es lo mismo una anomalía de protocolo que un intento de obtener credenciales.&lt;/p&gt;

&lt;p&gt;Por eso ARE organiza los eventos en nueve categorías: &lt;code&gt;RECON&lt;/code&gt;, &lt;code&gt;EXPLOIT&lt;/code&gt;, &lt;code&gt;CREDENTIAL&lt;/code&gt;, &lt;code&gt;PROTOCOL&lt;/code&gt;, &lt;code&gt;BOT&lt;/code&gt;, &lt;code&gt;ANOMALY&lt;/code&gt;, &lt;code&gt;MALWARE&lt;/code&gt;, &lt;code&gt;DOS&lt;/code&gt; y &lt;code&gt;SOCIAL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cada categoría contribuye a la reputación de acuerdo con su propia puntuación. De esta forma, una actividad habitual de exploración no pesa necesariamente lo mismo que una señal de explotación.&lt;/p&gt;

&lt;p&gt;Me interesaba conservar esa distinción. Si todo acaba convertido en un único número sin contexto, se pierde información que puede ser importante para decidir qué hacer.&lt;/p&gt;

&lt;h3&gt;
  
  
  El tiempo también importa
&lt;/h3&gt;

&lt;p&gt;La reputación no puede ser completamente estática. Una dirección IP puede cambiar de usuario, pertenecer a una conexión compartida o ser reutilizada. Mantener una sanción indefinidamente sin considerar el paso del tiempo puede terminar perjudicando a quien no tiene relación con los eventos originales.&lt;/p&gt;

&lt;p&gt;Pero tampoco quería que una IP recuperara su reputación de un momento a otro simplemente porque dejó de generar actividad durante unos minutos.&lt;/p&gt;

&lt;p&gt;ARE aplica una pérdida gradual de peso (&lt;em&gt;decay&lt;/em&gt;) a la reputación. El historial se conserva, mientras su influencia disminuye con el tiempo.&lt;/p&gt;

&lt;p&gt;La intención es encontrar un equilibrio: recordar lo suficiente como para detectar persistencia, sin convertir un comportamiento pasado en una condena eterna.&lt;/p&gt;

&lt;h3&gt;
  
  
  Primero observar, después restringir
&lt;/h3&gt;

&lt;p&gt;Otra decisión de diseño fue establecer una respuesta escalonada:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ALLOW → WATCH → FILTER → TEMP_BAN → BANNED&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;No todas las IP sospechosas deben terminar baneadas. El sistema puede pasar de permitir el tráfico a vigilarlo, filtrarlo y aplicar restricciones más severas a medida que aumenta la reputación.&lt;/p&gt;

&lt;p&gt;La persistencia importa, pero también importa la gravedad de lo observado. La secuencia representa los estados de decisión definidos por ARE; no significa que cualquier IP tenga que recorrer todas las etapas en ese orden.&lt;/p&gt;

&lt;h3&gt;
  
  
  La reputación no se reinicia porque una jaula libere una IP
&lt;/h3&gt;

&lt;p&gt;Esta es una parte importante de la idea original.&lt;/p&gt;

&lt;p&gt;Fail2Ban puede retirar un baneo cuando se cumple la política de una jaula. Eso significa que terminó esa sanción concreta; no demuestra por sí solo que todo el historial de la IP haya dejado de ser relevante.&lt;/p&gt;

&lt;p&gt;ARE está pensado para conservar y evaluar su propia reputación. La liberación de una jaula no debería confundirse automáticamente con una rehabilitación global de la dirección: el motor debe valorar el conjunto de señales que conoce y aplicar su propia política.&lt;/p&gt;

&lt;p&gt;En mi diseño, esta separación de responsabilidades importa mucho. Los sensores detectan y las herramientas existentes pueden actuar dentro de sus reglas; ARE aporta una evaluación más amplia del historial. La forma exacta en que se coordinan los bloqueos y las liberaciones depende de la integración configurada, y es un aspecto que debe comprobarse en cada despliegue.&lt;/p&gt;

&lt;p&gt;ARE también contempla compartir reputación entre servidores propios, utilizando categorías y puntuaciones como criterios de selección, sin depender de una plataforma de terceros.&lt;/p&gt;

&lt;p&gt;El objetivo no es sustituir todo lo que ya existe. Es añadir una capa de contexto y decisión a las herramientas que ya realizan la detección.&lt;/p&gt;

&lt;h2&gt;
  
  
  La prueba que decidí hacer en mi propio VPS
&lt;/h2&gt;

&lt;p&gt;Y una noche decidí ponerlo a prueba de una manera bastante directa: intentar que mi propio servidor se defendiera de mí. Una cosa es diseñar un sistema sobre el papel y otra comprobar cómo se comporta cuando recibe actividad real.&lt;/p&gt;

&lt;p&gt;ARE ya estaba funcionando en mi VPS de producción. Así que decidí realizar una prueba controlada desde una IP propia, sin involucrar a terceros y utilizando únicamente peticiones no destructivas.&lt;/p&gt;

&lt;p&gt;Hay un detalle importante: el servidor no estaba protegido por una única barrera.&lt;/p&gt;

&lt;p&gt;En el borde tenía Cloudflare, que presenta desafíos ante determinados tipos de tráfico. Después, ModSecurity, entre otras herramientas, inspeccionaba las peticiones que llegaban al servidor. Finalmente, en el origen estaba ARE, trabajando con los eventos que sus sensores registraban.&lt;/p&gt;

&lt;p&gt;Para evaluar ARE necesitaba que mi tráfico de prueba llegara al origen. Por eso utilicé una excepción controlada para mi propia IP en la capa perimetral.&lt;/p&gt;

&lt;p&gt;Una vez preparado el escenario, probé patrones habituales de reconocimiento y explotación: intentos de SQL injection, &lt;em&gt;local file inclusion&lt;/em&gt; (LFI), &lt;em&gt;path traversal&lt;/em&gt;, XSS e inyección de comandos. Todo de forma no destructiva, sin intentar modificar datos ni comprometer información.&lt;/p&gt;

&lt;p&gt;Era mi servidor, sí, pero también estaba en producción y tenía clientes reales. No tenía ningún sentido convertir una prueba de seguridad en un incidente que yo mismo hubiera provocado.&lt;/p&gt;

&lt;p&gt;ModSecurity comenzó a responder con códigos HTTP 403 ante las firmas que reconocía.&lt;/p&gt;

&lt;p&gt;Hasta ahí, todo estaba dentro de lo esperado.&lt;/p&gt;

&lt;p&gt;Entonces fui a revisar qué había registrado ARE.&lt;/p&gt;

&lt;h2&gt;
  
  
  Los números y el momento en que pensé que algo fallaba
&lt;/h2&gt;

&lt;p&gt;En la primera ronda, la reputación de mi IP aparecía así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exploit 9 · Credential 2 · Anomaly 7
Total 18 · Riesgo: LOW · Decisión: WATCH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La primera reacción que tuve fue mirar el resultado desde el otro lado: el navegador seguía recibiendo respuestas HTTP 200 en algunas peticiones.&lt;/p&gt;

&lt;p&gt;Mi interpretación inicial fue que ARE no estaba reaccionando.&lt;/p&gt;

&lt;p&gt;Pero había cometido un error bastante habitual cuando uno está probando su propio sistema: estaba esperando una respuesta inmediata de un proceso que trabaja por ciclos.&lt;/p&gt;

&lt;p&gt;Los sensores registran los eventos y ARE los procesa conforme a su ciclo de evaluación. Si consulto el estado antes de que ese ciclo termine, puedo estar viendo una situación que todavía no refleja toda la actividad que acabo de generar.&lt;/p&gt;

&lt;p&gt;Un código HTTP 200 tampoco demuestra, por sí solo, que una petición haya tenido éxito desde el punto de vista del ataque. Indica que el servidor respondió con ese código; para interpretar el resultado hay que mirar qué respondió y qué ocurrió después.&lt;/p&gt;

&lt;p&gt;Esperé, volví a comprobar el estado y lancé una segunda ronda, más intensa.&lt;/p&gt;

&lt;p&gt;Minutos después, los números habían cambiado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exploit 12 · Anomaly 13 · Total 27 · Riesgo: MEDIUM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La línea de decisión reflejaba la progresión:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WATCH (18, LOW)
    ↓
FILTER (27, MEDIUM)
    ↓
BAN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La IP terminó bloqueada.&lt;/p&gt;

&lt;p&gt;Y esa IP era la de mi propia conexión doméstica.&lt;/p&gt;

&lt;p&gt;Me había baneado a mí mismo.&lt;/p&gt;

&lt;p&gt;Tuve que recuperar el acceso mediante la consola fuera de banda de mi VPS. Precisamente para eso existe ese tipo de acceso: poder administrar una máquina cuando las vías de conexión habituales dejan de estar disponibles.&lt;/p&gt;

&lt;p&gt;No fue el resultado más cómodo de la noche, pero sí una de las comprobaciones más útiles que podía hacer. La política de bloqueo no se había quedado en una cifra o una alerta: había producido una consecuencia real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Qué aprendí de la prueba
&lt;/h2&gt;

&lt;p&gt;No voy a decir que una prueba de este tipo demuestra que un sistema de reputación está perfectamente calibrado. Sería exagerar lo que realmente comprobé.&lt;/p&gt;

&lt;p&gt;Lo que sí pude observar fue cómo ARE acumulaba las señales, cómo cambiaba la evaluación después de una nueva ronda de actividad y cómo terminaba aplicando una restricción efectiva.&lt;/p&gt;

&lt;p&gt;También me dejó varias lecciones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La primera: hay que distinguir entre un fallo y un retraso.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Mi impresión inicial de que ARE no reaccionaba se adelantó a los datos disponibles. El tiempo de procesamiento importaba. Antes de modificar la lógica del motor, tenía que comprobar si había terminado el ciclo de evaluación.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La segunda: sumar eventos no significa necesariamente sumar riesgo de manera indiscriminada.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;El reconocimiento básico no debe tratarse igual que una secuencia de señales de explotación. Si elevamos demasiado el peso de la actividad exploratoria, podemos terminar bloqueando tráfico legítimo. Si lo reducimos demasiado, podemos perder señales útiles. La calibración requiere observar resultados y revisar los umbrales, no limitarse a declarar que funcionan.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;La tercera: una herramienta puede hacer bien su trabajo sin tener toda la información.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ModSecurity bloqueó las peticiones que reconoció. ARE evaluó los eventos que recibió y terminó tomando su propia decisión. Son funciones distintas y complementarias.&lt;/p&gt;

&lt;p&gt;La seguridad por capas no consiste en instalar varias herramientas que hacen exactamente lo mismo, sino en combinar mecanismos que cubren partes diferentes del problema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Y la cuarta: un bloqueo real vale más que una línea bonita en un registro.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ver una puntuación aumentar es útil. Comprobar que la política termina aplicándose también lo es. Pero ambas cosas deben acompañarse de pruebas adicionales: falsos positivos, recuperación del acceso, persistencia de las sanciones y comportamiento ante IP compartidas o reutilizadas.&lt;/p&gt;

&lt;p&gt;Que el sistema me haya bloqueado durante esta prueba es una señal de que el mecanismo de respuesta funcionó en ese escenario. No es una garantía de que vaya a acertar siempre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dónde está ARE hoy
&lt;/h2&gt;

&lt;p&gt;ARE está en producción, en su rama 2.8.x, y también lo están utilizando algunos colegas.&lt;/p&gt;

&lt;p&gt;El proyecto cuenta con documentación sobre su arquitectura, su diseño y el ciclo de vida de los baneos. Su objetivo sigue siendo el mismo que me llevó a escribir las primeras líneas: incorporar una capa de reputación persistente a la seguridad del servidor, utilizando las señales que ya producen las herramientas existentes.&lt;/p&gt;

&lt;p&gt;No lo presento como un reemplazo de Fail2Ban ni de CrowdSec. Son proyectos con objetivos y mecanismos propios. ARE busca cubrir otro espacio: evaluar el comportamiento acumulado de una IP, mantener reputación por categorías y utilizar esa información para decidir cuándo observar, filtrar o bloquear.&lt;/p&gt;

&lt;p&gt;Todo ello con Bash, SQLite y herramientas que un administrador puede inspeccionar sin tener que desplegar una infraestructura adicional.&lt;/p&gt;

&lt;p&gt;¿Es la solución definitiva? No. Todavía hay decisiones de puntuación, decaimiento y respuesta que deben validarse en diferentes escenarios. Y una herramienta que interviene directamente en el acceso a un servidor siempre necesita políticas prudentes y una vía de recuperación.&lt;/p&gt;

&lt;p&gt;Pero el hecho de que pueda ejecutarlo en producción, observar su comportamiento y probarlo de manera controlada me permite avanzar sobre algo más que una idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué comparto esto
&lt;/h2&gt;

&lt;p&gt;ARE nació porque había algo en la forma de gestionar los baneos que no me convencía. No quería acumular herramientas ni repetir el trabajo que ya hacían las que tenía. Quería que las detecciones pudieran convertirse en decisiones basadas en un historial.&lt;/p&gt;

&lt;p&gt;Quería que una IP tuviera contexto. Que un evento no se interpretara siempre de manera aislada. Que el sistema pudiera distinguir entre una señal puntual y un comportamiento que se repite, sin convertir cada anomalía en una sentencia.&lt;/p&gt;

&lt;p&gt;Esa noche terminé recuperando el acceso a mi VPS por la consola fuera de banda porque ARE había bloqueado mi propia IP. No es una prueba definitiva de que el modelo sea correcto, pero sí una experiencia real que me permitió comprobar cómo respondía el sistema.&lt;/p&gt;

&lt;p&gt;Ahora me interesa contrastar ese enfoque con otros administradores y desarrolladores. No porque considere que ARE ya tiene todas las respuestas, sino porque quiero descubrir dónde funciona bien, dónde puede equivocarse y qué debería mejorar.&lt;/p&gt;

&lt;p&gt;Si trabajas con servidores Linux, sistemas de detección de intrusiones o mecanismos de reputación de IP, me gustaría conocer tu opinión sobre el modelo de puntuación por categorías, el decaimiento de la reputación y la política de baneos escalonados.&lt;/p&gt;

&lt;p&gt;¿Qué escenarios te preocuparía que este enfoque pasara por alto? ¿Dónde ves mayor riesgo de falsos positivos? ¿Cómo abordarías la reutilización de direcciones IP y la reputación compartida entre servidores?&lt;/p&gt;

&lt;p&gt;El código está disponible bajo licencia GPL-3.0:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repositorio de ARE:&lt;/strong&gt; &lt;a href="https://github.com/hvalero2001-commits/ARE" rel="noopener noreferrer"&gt;https://github.com/hvalero2001-commits/ARE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Toda crítica técnica fundamentada es bienvenida. Quiero seguir probando ARE en escenarios reales, revisar lo que ocurre y corregir lo que haga falta.&lt;/p&gt;

</description>
      <category>security</category>
      <category>linux</category>
      <category>opensource</category>
      <category>bash</category>
    </item>
    <item>
      <title>I gave Fail2Ban a memory: the story of ARE and the night I ended up banning myself</title>
      <dc:creator>Hernan Valero</dc:creator>
      <pubDate>Sun, 25 Oct 2026 17:07:08 +0000</pubDate>
      <link>https://dev.to/hernan_valero/i-gave-fail2ban-a-memory-the-story-of-are-and-the-night-i-ended-up-banning-myself-292f</link>
      <guid>https://dev.to/hernan_valero/i-gave-fail2ban-a-memory-the-story-of-are-and-the-night-i-ended-up-banning-myself-292f</guid>
      <description>&lt;p&gt;Fail2Ban did its job, but there were situations where the result didn't convince me. Sometimes it blocked what it shouldn't have, and other times it didn't seem to catch what actually worried me.&lt;/p&gt;

&lt;p&gt;I didn't want to add yet another security tool to the pile. I wanted to solve something that, from my point of view, was missing: that the server could remember an IP's behavior and make decisions taking its history into account, not just the last event recorded.&lt;/p&gt;

&lt;p&gt;Out of that idea ARE was born — &lt;em&gt;Abuse Reputation Engine&lt;/em&gt;.&lt;br&gt;
🇪🇸 Versión en español en este artículo: &lt;a href="https://dev.to/hernan_valero/le-di-memoria-a-fail2ban-la-historia-de-are-y-la-noche-en-que-termine-baneandome-a-mi-mismo-5ekk"&gt;https://dev.to/hernan_valero/le-di-memoria-a-fail2ban-la-historia-de-are-y-la-noche-en-que-termine-baneandome-a-mi-mismo-5ekk&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you'd rather watch than read: 60–90s of the live escalation (WATCH → FILTER → TEMP_BAN):&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_asciinema"&gt;
  
&lt;/div&gt;



&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  I didn't want to build another Fail2Ban
&lt;/h2&gt;

&lt;p&gt;From the start I was clear on one thing: I didn't want to reinvent Fail2Ban or write another detector that did practically the same thing.&lt;/p&gt;

&lt;p&gt;Fail2Ban already served a useful purpose. It parsed logs, detected patterns of suspicious activity, and could apply its own sanctions. What I wanted was to make use of the detections and reports from the tools already running on the server, not to duplicate their work.&lt;/p&gt;

&lt;p&gt;The idea behind ARE was to gather those signals into a reputation history, relate them to their category and severity, and let the engine evaluate the whole before deciding how to act.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fail2Ban and the other sensors provide detections; ARE adds context, maintains the reputation, and makes decisions according to its own policies.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It doesn't mean Fail2Ban stops applying its rules, or that every tool has exactly the same function. It means I wanted an additional layer able to evaluate an IP's accumulated behavior, instead of relying only on decisions made in isolation.&lt;/p&gt;

&lt;p&gt;An isolated detection doesn't always tell the whole story. But when it's combined with other events and with what that address has been doing over time, it can take on a different meaning.&lt;/p&gt;

&lt;p&gt;I didn't need another detector competing with the ones I already had. I needed a layer that could make use of their results, relate them, and make decisions from a broader perspective.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem I wanted to solve
&lt;/h2&gt;

&lt;p&gt;The security tools we use every day have a specific function. Fail2Ban parses events and applies sanctions according to the configured rules. ModSecurity inspects HTTP requests and can block the ones that match certain rules. A firewall controls traffic according to its policies.&lt;/p&gt;

&lt;p&gt;I have nothing against those tools. On the contrary, they're part of a good defense. The problem appears when we try to interpret a behavior that doesn't fit easily into an isolated rule.&lt;/p&gt;

&lt;p&gt;A failed access attempt can be a legitimate mistake. A strange request can be a scanner. A sequence of attempts spread out over time can reveal something more concerning than any of those events on its own.&lt;/p&gt;

&lt;p&gt;How do you tell them apart?&lt;/p&gt;

&lt;p&gt;Two scenarios worried me. On one hand, someone who spreads their attempts out to stay below certain thresholds. On the other, a legitimate user who ends up blocked because an unstable connection or a sequence of normal requests looks too much like abuse.&lt;/p&gt;

&lt;p&gt;I wasn't trying to solve every security problem with a single tool. I wanted to add a piece that would help interpret context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The idea was simple: that an IP wouldn't start from zero every time it generated an event.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's how ARE started to take shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  ARE: reputation instead of isolated reactions
&lt;/h2&gt;

&lt;p&gt;From the start I was clear that I didn't want to introduce unnecessarily complex infrastructure. The idea was to build an engine that could run on a Linux server, leaning on well-known tools and without depending on an external service.&lt;/p&gt;

&lt;p&gt;Bash, SQLite, IPSet, and systemd. Simple components, accessible and relatively easy to inspect.&lt;/p&gt;

&lt;p&gt;I didn't need another agent written in a trendy language, or a platform that forced me to maintain extra infrastructure. I needed the decision logic to be understandable, and to be able to know why the system made a particular decision.&lt;/p&gt;

&lt;p&gt;ARE's core revolves around a few principles.&lt;/p&gt;

&lt;h3&gt;
  
  
  Not all events mean the same thing
&lt;/h3&gt;

&lt;p&gt;One of the problems I wanted to avoid was treating every suspicious event as if it had the same importance.&lt;/p&gt;

&lt;p&gt;Detecting port reconnaissance is not the same as recording an exploitation attempt. Nor is a protocol anomaly the same as an attempt to obtain credentials.&lt;/p&gt;

&lt;p&gt;That's why ARE organizes events into nine categories: &lt;code&gt;RECON&lt;/code&gt;, &lt;code&gt;EXPLOIT&lt;/code&gt;, &lt;code&gt;CREDENTIAL&lt;/code&gt;, &lt;code&gt;PROTOCOL&lt;/code&gt;, &lt;code&gt;BOT&lt;/code&gt;, &lt;code&gt;ANOMALY&lt;/code&gt;, &lt;code&gt;MALWARE&lt;/code&gt;, &lt;code&gt;DOS&lt;/code&gt;, and &lt;code&gt;SOCIAL&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Each category contributes to the reputation according to its own score. This way, routine scanning activity doesn't necessarily weigh the same as an exploitation signal.&lt;/p&gt;

&lt;p&gt;I cared about keeping that distinction. If everything ends up turned into a single number with no context, you lose information that can be important when deciding what to do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time matters too
&lt;/h3&gt;

&lt;p&gt;Reputation can't be completely static. An IP address can change hands, belong to a shared connection, or be reused. Keeping a sanction indefinitely without considering the passage of time can end up harming someone who has nothing to do with the original events.&lt;/p&gt;

&lt;p&gt;But I also didn't want an IP to recover its reputation from one moment to the next simply because it stopped generating activity for a few minutes.&lt;/p&gt;

&lt;p&gt;ARE applies a gradual loss of weight (&lt;em&gt;decay&lt;/em&gt;) to the reputation. The history is kept, while its influence decreases over time.&lt;/p&gt;

&lt;p&gt;The intent is to strike a balance: to remember enough to detect persistence, without turning a past behavior into an eternal sentence.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observe first, restrict later
&lt;/h3&gt;

&lt;p&gt;Another design decision was to establish a staggered response:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ALLOW → WATCH → FILTER → TEMP_BAN → BANNED&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Not every suspicious IP has to end up banned. The system can go from allowing traffic to watching it, filtering it, and applying more severe restrictions as the reputation grows.&lt;/p&gt;

&lt;p&gt;Persistence matters, but so does the severity of what's observed. The sequence represents the decision states defined by ARE; it doesn't mean that any given IP has to go through every stage in that order.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reputation doesn't reset because a jail releases an IP
&lt;/h3&gt;

&lt;p&gt;This is an important part of the original idea.&lt;/p&gt;

&lt;p&gt;Fail2Ban can lift a ban when a jail's policy is met. That means that specific sanction ended; it doesn't by itself prove that the IP's whole history has stopped being relevant.&lt;/p&gt;

&lt;p&gt;ARE is meant to keep and evaluate its own reputation. A jail release shouldn't automatically be confused with a global rehabilitation of the address: the engine should weigh the whole set of signals it knows about and apply its own policy.&lt;/p&gt;

&lt;p&gt;In my design, this separation of responsibilities matters a lot. The sensors detect, and the existing tools can act within their rules; ARE provides a broader evaluation of the history. The exact way blocks and releases are coordinated depends on the configured integration, and it's an aspect that has to be checked in each deployment.&lt;/p&gt;

&lt;p&gt;ARE also allows for sharing reputation between your own servers, using categories and scores as selection criteria, without depending on a third-party platform.&lt;/p&gt;

&lt;p&gt;The goal is not to replace everything that already exists. It's to add a layer of context and decision on top of the tools that already do the detection.&lt;/p&gt;

&lt;h2&gt;
  
  
  The test I decided to run on my own VPS
&lt;/h2&gt;

&lt;p&gt;And one night I decided to put it to the test in a fairly direct way: trying to get my own server to defend itself against me. Designing a system on paper is one thing; checking how it behaves when it receives real activity is another.&lt;/p&gt;

&lt;p&gt;ARE was already running on my production VPS. So I decided to run a controlled test from an IP of my own, without involving any third parties and using only non-destructive requests.&lt;/p&gt;

&lt;p&gt;There's an important detail: the server wasn't protected by a single barrier.&lt;/p&gt;

&lt;p&gt;At the edge I had Cloudflare, which presents challenges to certain kinds of traffic. Behind that, ModSecurity, among other tools, inspected the requests that reached the server. Finally, at the origin was ARE, working with the events its sensors recorded.&lt;/p&gt;

&lt;p&gt;To evaluate ARE I needed my test traffic to reach the origin. So I used a controlled exception for my own IP at the perimeter layer.&lt;/p&gt;

&lt;p&gt;Once the scenario was set up, I tried the usual reconnaissance and exploitation patterns: SQL injection attempts, &lt;em&gt;local file inclusion&lt;/em&gt; (LFI), &lt;em&gt;path traversal&lt;/em&gt;, XSS, and command injection. All of it non-destructive, without trying to modify data or compromise information.&lt;/p&gt;

&lt;p&gt;It was my server, yes, but it was also in production and had real customers. There was no sense in turning a security test into an incident I had caused myself.&lt;/p&gt;

&lt;p&gt;ModSecurity started responding with HTTP 403 codes to the signatures it recognized.&lt;/p&gt;

&lt;p&gt;So far, everything was within expectations.&lt;/p&gt;

&lt;p&gt;Then I went to check what ARE had recorded.&lt;/p&gt;

&lt;h2&gt;
  
  
  The numbers, and the moment I thought something was failing
&lt;/h2&gt;

&lt;p&gt;In the first round, my IP's reputation looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exploit 9 · Credential 2 · Anomaly 7
Total 18 · Risk: LOW · Decision: WATCH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My first reaction was to look at the result from the other side: the browser was still receiving HTTP 200 responses on some requests.&lt;/p&gt;

&lt;p&gt;My initial interpretation was that ARE wasn't reacting.&lt;/p&gt;

&lt;p&gt;But I had made a fairly common mistake when you're testing your own system: I was expecting an immediate response from a process that works in cycles.&lt;/p&gt;

&lt;p&gt;The sensors record the events and ARE processes them according to its evaluation cycle. If I check the state before that cycle finishes, I may be seeing a situation that doesn't yet reflect all the activity I just generated.&lt;/p&gt;

&lt;p&gt;An HTTP 200 code doesn't prove, on its own, that a request succeeded from an attack's point of view either. It indicates that the server responded with that code; to interpret the result you have to look at what it responded and what happened next.&lt;/p&gt;

&lt;p&gt;I waited, checked the state again, and launched a second, more intense round.&lt;/p&gt;

&lt;p&gt;Minutes later, the numbers had changed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Exploit 12 · Anomaly 13 · Total 27 · Risk: MEDIUM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The decision timeline reflected the progression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WATCH (18, LOW)
    ↓
FILTER (27, MEDIUM)
    ↓
BAN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The IP ended up blocked.&lt;/p&gt;

&lt;p&gt;And that IP was my own home connection.&lt;/p&gt;

&lt;p&gt;I had banned myself.&lt;/p&gt;

&lt;p&gt;I had to recover access through my VPS's out-of-band console. That's exactly what that kind of access is for: being able to administer a machine when the usual connection paths are no longer available.&lt;/p&gt;

&lt;p&gt;It wasn't the most comfortable outcome of the night, but it was one of the most useful checks I could run. The blocking policy hadn't stopped at a figure or an alert: it had produced a real consequence.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned from the test
&lt;/h2&gt;

&lt;p&gt;I'm not going to say that a test like this proves a reputation system is perfectly calibrated. That would be overstating what I actually verified.&lt;/p&gt;

&lt;p&gt;What I could observe was how ARE accumulated the signals, how the evaluation changed after a new round of activity, and how it ended up applying an effective restriction.&lt;/p&gt;

&lt;p&gt;It also left me with a few lessons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First: you have to tell a failure apart from a delay.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My initial impression that ARE wasn't reacting got ahead of the available data. The processing time mattered. Before changing the engine's logic, I had to check whether the evaluation cycle had finished.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second: adding events doesn't necessarily mean adding risk indiscriminately.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Basic reconnaissance shouldn't be treated the same as a sequence of exploitation signals. If we raise the weight of exploratory activity too much, we can end up blocking legitimate traffic. If we lower it too much, we can miss useful signals. Calibration requires observing results and reviewing the thresholds, not just declaring that they work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third: a tool can do its job well without having all the information.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ModSecurity blocked the requests it recognized. ARE evaluated the events it received and ended up making its own decision. They're distinct and complementary functions.&lt;/p&gt;

&lt;p&gt;Layered security isn't about installing several tools that do exactly the same thing, but about combining mechanisms that cover different parts of the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And fourth: a real block is worth more than a nice line in a log.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Seeing a score go up is useful. Confirming that the policy actually gets applied is useful too. But both have to be accompanied by further testing: false positives, access recovery, persistence of sanctions, and behavior with shared or reused IPs.&lt;/p&gt;

&lt;p&gt;That the system blocked me during this test is a sign that the response mechanism worked in that scenario. It's not a guarantee that it will always get it right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where ARE is today
&lt;/h2&gt;

&lt;p&gt;ARE is in production, on its 2.8.x branch, and some colleagues are using it too.&lt;/p&gt;

&lt;p&gt;The project has documentation on its architecture, its design, and the ban lifecycle. Its goal is still the same one that led me to write the first lines: to add a persistent reputation layer to server security, using the signals the existing tools already produce.&lt;/p&gt;

&lt;p&gt;I don't present it as a replacement for Fail2Ban or CrowdSec. Those are projects with their own goals and mechanisms. ARE aims to cover a different space: evaluating an IP's accumulated behavior, keeping reputation by category, and using that information to decide when to watch, filter, or block.&lt;/p&gt;

&lt;p&gt;All of it with Bash, SQLite, and tools an administrator can inspect without having to deploy additional infrastructure.&lt;/p&gt;

&lt;p&gt;Is it the definitive solution? No. There are still scoring, decay, and response decisions that need to be validated in different scenarios. And a tool that intervenes directly in access to a server always needs prudent policies and a recovery path.&lt;/p&gt;

&lt;p&gt;But the fact that I can run it in production, observe its behavior, and test it in a controlled way lets me move forward on something more than an idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I'm sharing this
&lt;/h2&gt;

&lt;p&gt;ARE was born because there was something about the way bans were handled that didn't convince me. I didn't want to pile up tools or repeat the work the ones I had were already doing. I wanted detections to be able to turn into decisions based on a history.&lt;/p&gt;

&lt;p&gt;I wanted an IP to have context. For an event not to always be interpreted in isolation. For the system to be able to tell a one-off signal from a repeating behavior, without turning every anomaly into a sentence.&lt;/p&gt;

&lt;p&gt;That night I ended up recovering access to my VPS through the out-of-band console because ARE had blocked my own IP. It's not definitive proof that the model is correct, but it is a real experience that let me check how the system responded.&lt;/p&gt;

&lt;p&gt;Now I'm interested in contrasting that approach with other administrators and developers. Not because I think ARE already has all the answers, but because I want to find out where it works well, where it can go wrong, and what I should improve.&lt;/p&gt;

&lt;p&gt;If you work with Linux servers, intrusion detection systems, or IP reputation mechanisms, I'd like to hear your opinion on the per-category scoring model, reputation decay, and the staggered ban policy.&lt;/p&gt;

&lt;p&gt;What situations would worry you that this approach might miss? Where do you see the greatest risk of false positives? How would you handle IP address reuse and reputation shared between servers?&lt;/p&gt;

&lt;p&gt;The code is available under the GPL-3.0 license:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ARE repository:&lt;/strong&gt; &lt;a href="https://github.com/hvalero2001-commits/ARE" rel="noopener noreferrer"&gt;https://github.com/hvalero2001-commits/ARE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any well-founded technical criticism is welcome. I want to keep testing ARE in real scenarios, review what happens, and fix whatever needs fixing.&lt;/p&gt;

</description>
      <category>security</category>
      <category>linux</category>
      <category>opensource</category>
      <category>bash</category>
    </item>
  </channel>
</rss>
