Código fuente: github.com/Alex0176/odoo-web-rbl — AGPL-3, de uso libre.
Quien opera un servidor Odoo en Internet recibe visitas. No de vez en cuando, sino sin interrupción. Durante diecisiete días hemos registrado y analizado en nuestras cinco páginas web 731.297 solicitudes. 110.511 de ellas no eran visitantes, sino búsqueda automatizada de vulnerabilidades, credenciales de acceso y archivos de configuración.
Esta entrada describe Web RBL, un módulo de código abierto para Odoo 19 Community que detecta, puntúa, registra y rechaza este tráfico, y que publica la lista de bloqueo como lista RBL, es decir, en el formato que los firewalls y proxies inversos leen directamente. Todas las cifras proceden de la operación real.
Qué puede hacer el módulo: las funciones de un vistazo
| Función | Qué hace | Entrega |
|---|---|---|
| Detección de patrones | Detecta sondeos por ruta y extensión: .env, .git, archivos de configuración, claves de nube, instrucciones de compilación CI/CD, WordPress, PHP, path traversal, gestores de bases de datos, GraphQL, ejecución de comandos mediante /api/fs/exec e interfaces similares | bloquear |
| Tres niveles por patrón | bloquear, contar o notificar: configurable por patrón, sin código | por patrón |
| Umbrales | Cuántas coincidencias del mismo patrón antes de bloquear; para inicios de sesión, diez | 10 en el inicio de sesión |
| Defensa del inicio de sesión | Inicios de sesión fallidos a través del formulario y de XML-RPC/JSON-RPC, comprobaciones de sesión fallidas, accesos al gestor de bases de datos: en la base de datos, no en la memoria | activado |
| Detección de bots en el inicio de sesión | Quien ignora el aviso de espera tras diez intentos fallidos y sigue llamando es bloqueado de inmediato | bloquear |
| Detección de comportamiento | Direcciones que en cinco minutos generan veinte páginas inexistentes y apenas una página válida, es decir, que adivinan en lugar de leer | notificar |
| Puntuación 0–100 | ¿Qué probabilidad hay de que detrás de la dirección haya un atacante? A partir de la gravedad del patrón, el número de patrones distintos, días llamativos, dominios afectados y número de coincidencias, con justificación en lenguaje claro | activado |
| Bloqueo del inicio de sesión según la puntuación | A partir de una puntuación configurable, el inicio de sesión queda prohibido, mientras la página web sigue siendo legible | a partir de 40 |
| Sospecha de credenciales robadas | Un inicio de sesión correcto desde una dirección sospechosa se notifica y, si se desea, se asigna como tarea — una vez por dirección y día | activado |
| Listas de amenazas | Nodos de salida de Tor, Spamhaus DROP, FireHOL Level 1 y blocklist.de preconfigurados; cualquier otra lista RBL puede añadirse indicando su dirección, comparación diaria, un nivel propio para cada lista | notificar |
| Sin acceso al inicio de sesión | El cuarto nivel para listas y países: la web sigue siendo legible, pero el formulario de inicio de sesión y las interfaces quedan cerrados — la respuesta adecuada para Tor | Opción |
| País de origen | País por cada coincidencia y dirección mediante GeoLite2; el módulo mantiene la base de datos actualizada por sí mismo con una clave de licencia gratuita | mostrar |
| Reglas por país | Bloquear, sin acceso al inicio de sesión, notificar o expresamente libre — por país, deliberadamente sin valor predeterminado | ninguna |
| Configuraciones erróneas | QNAP, Synology, Exchange Autodiscover, ActiveSync y WebDAV/CalDAV/CardDAV se reconocen, nunca se bloquean y se incluyen en una lista de trabajo con el hallazgo y el dominio afectado | notificar |
| Ticket por dirección | De un hallazgo surge, si se desea, un ticket — exactamente uno por dirección; si está cerrado, se reabre en lugar de duplicarse | desactivado |
| Páginas obligatorias y recolectores | La ruta canónica del aviso legal siempre sigue accesible; el tanteo automatizado de grafías ajenas se detecta y, si se desea, se bloquea | notificar |
| Lista de permitidos | Direcciones y redes que nunca se bloquean; se rellena a diario desde el cortafuegos (extremos de VPN) y desde los rangos de direcciones publicados de Googlebot y Bingbot | activado |
| Asignación a clientes | Una coincidencia procedente de la red de un cliente se le asigna a él — a partir de la lista de permitidos, nunca adivinada a mano | activado |
| Dominio e identificador por coincidencia | Qué web se solicitó y con qué user agent — ambos datos faltan en el registro de accesos | activado |
| Análisis | Gráfico y tabla dinámica sobre todas las coincidencias: por patrón, día, dominio, país y dirección | activado |
| Señuelo | Las sondas reciben respuestas inventadas con un valor canario; quien lo consulta después, las ha leído | desactivado |
| Entrega de RBL | La lista de bloqueo como simple lista de direcciones o como JSON, en una dirección propia protegida con token — para HAProxy, OPNsense y cualquier cortafuegos que lea listas de URL | activado |
Todo lo que se entrega con notificar, desactivado u opción es así a propósito: quien active un bloqueo debe hacerlo porque ha observado durante unos días a quién afecta, no porque el valor predeterminado lo quisiera así.
El análisis: coincidencias por patrón durante siete días. La barra más alta es la búsqueda de archivos .env.
Listas RBL: una forma estandarizada de distribuir bloqueos
RBL significa Real-time Blackhole List. El término procede del mundo del correo, donde Spamhaus y otros publican desde los años noventa listas de direcciones de remitentes maliciosos. El principio es sencillísimo y precisamente por eso está tan extendido: una dirección por línea, accesible por HTTP, recargada con regularidad. Sin un formato que haya que analizar primero, sin una interfaz para la que se necesite una herramienta.
Prácticamente cualquier cortafuegos y cualquier proxy inverso puede leer una lista así y construir reglas a partir de ella. Cada fabricante lo llama de forma distinta, pero el mecanismo es el mismo en todas partes:
- OPNsense y pfSense — URL Table Alias: cargar la lista de direcciones por HTTP, usarla como alias en las reglas del cortafuegos, actualización cada hora o cada día
- HAProxy — archivos ACL y maps:
src -f sperrliste.txten una reglahttp-request deny, recargable mediante la API de tiempo de ejecución sin reinicio - nginx — módulo geo con archivo de direcciones incluido, o instrucciones
denyprocedentes de un archivoincludegenerado - Fortinet FortiGate — External Block List o Threat Feed: una URL de la que el cortafuegos obtiene una lista de IP y la utiliza en las políticas
- Palo Alto Networks — External Dynamic List (EDL): el mismo principio, como tipo de objeto propio en las políticas de seguridad
- Check Point — Custom Intelligence Feeds e IP Block Lists mediante una URL
- Cisco Secure Firewall (Firepower) — Security Intelligence Feeds con fuentes de listas propias
- Sophos Firewall — Third-Party Threat Feeds: listas de direcciones desde una URL como fuente para reglas de bloqueo
- Juniper SRX — Dynamic Address Entries a partir de feeds
- MikroTik RouterOS — Address Lists, rellenadas mediante script y
fetchdesde una URL - CrowdSec — listas propias como fuente para los bouncers en cualquier sistema compatible
Web RBL distribuye su lista de bloqueo exactamente en este formato. El cortafuegos descarta los paquetes antes de que lleguen al servidor web — y con ellos cualquier otro intento de la misma dirección, por ejemplo contra el servidor de correo o la pasarela VPN.
En ambos sentidos, pero en el lugar adecuado
El camino también funciona a la inversa: en Web RBL se puede registrar cualquier lista RBL — una URL, un nivel, listo. Los nodos de salida de Tor, Spamhaus DROP, FireHOL y blocklist.de vienen preconfigurados; se añaden otras con tres clics. El módulo descompone cada lista en rangos de direcciones y comprueba cada solicitud contra ellos, en unos pocos microsegundos.
Y sin embargo: es más razonable utilizar las listas de terceros en el cortafuegos situado delante. Por tres motivos. El cortafuegos ve todos los servicios, no solo HTTP — una dirección de la lista de Spamhaus debe fracasar también en el servidor de correo y en la VPN. Descarta a nivel de paquete, antes de que llegue a establecerse siquiera una conexión, y así no le cuesta nada al servidor de aplicaciones. Y es el lugar donde estas listas se mantienen de todos modos; una segunda copia en la aplicación es un segundo punto que puede quedarse obsoleto.
Entonces, ¿para qué sirven las listas en el módulo? Para lo que un cortafuegos no puede hacer. No conoce ningún formulario de inicio de sesión. Web RBL puede denegar a una dirección de la lista de Tor el acceso al inicio de sesión y aun así servir la web — quien quiera leer de forma anónima, debe poder hacerlo; quien quiera probar contraseñas de forma anónima, no. Y puede notificar como caso sospechoso un inicio de sesión correcto desde una dirección listada. Ambas cosas necesitan la lista allí donde tiene lugar el inicio de sesión.
Una valoración en lugar de intuición
Una dirección que ha preguntado una sola vez por /wp-login.php
es algo distinto de una que, en dos días, ha probado cinco
patrones diferentes en tres dominios. Web RBL lo convierte en una
puntuación de 0 a 100 — a partir de lo que ha visto
por sí mismo, sin servicios externos y sin consultas al exterior.
Una entrada: 99 coincidencias, puntuación 84 y la justificación en lenguaje claro — patrón más grave, cinco patrones graves distintos, dos días sospechosos, más de veinte coincidencias.
La puntuación decide dos cosas. A partir de un valor configurable, el inicio de sesión queda prohibido — la web sigue siendo legible, pero quien ya ha buscado credenciales no tiene la oportunidad de probar las que haya encontrado. Y un inicio de sesión correcto desde una dirección con puntuación se notifica: entonces alguien ya no ha estado adivinando, sino que sabía. O bien el usuario legítimo estaba de viaje, o bien se han extraviado las credenciales — el módulo no lo decide, se lo presenta a alguien que puede preguntar. La contraseña en sí no se toca en ningún momento.
La lista de bloqueo, filtrada por puntuación a partir de 40: número de coincidencias, días sospechosos, dominios afectados y última ruta por dirección.
Qué protege Web RBL — el efecto protector en detalle
1. Las credenciales siguen sin ser descubiertas
La mayor clase de ataque medida no busca vulnerabilidades en Odoo, sino secretos olvidados. A lo largo de diecisiete días:
- 57.721 solicitudes de archivos
.env— ahí se guardan contraseñas de bases de datos, claves de API y secretos de sesión - 5.535 solicitudes de archivos de configuración
- 4.388 solicitudes de credenciales en la nube:
credentials.json,service-account.json,firebase-adminsdk.json,rclone.conf,.git-credentials - 2.811 solicitudes de directorios
.git— quien encuentra uno descarga el código fuente completo con todo su historial - 1.907 solicitudes de instrucciones de compilación como
.github/workflows/deploy.ymlo.gitlab-ci.yml, en las que constan registros y nombres de claves
Lo decisivo no es el número de solicitudes, sino el número
de direcciones distintas: /credentials.json procedió
de 98 direcciones, /.git-credentials de 92. No se trata de
un único escáner, sino de un repertorio estándar que se ejecuta
simultáneamente en todo el mundo.
2. Los intentos de inicio de sesión caen en el vacío — de forma permanente
Odoo incorpora su propio freno contra el tanteo de contraseñas. Tiene tres límites, documentados en el propio código fuente de Odoo: el contador reside en la memoria del proceso de trabajo y se restablece con cada reinicio, solo retrasa en lugar de bloquear, y cuenta únicamente los intentos que llegan hasta la comprobación de la contraseña.
Web RBL actúa en los mismos puntos, pero escribe en la base de datos. De ello resulta:
- El estado sobrevive a cada reinicio y es válido para todos los procesos de trabajo
- Se registran ambas vías: el formulario de inicio de sesión
/web/loginy las interfaces/xmlrpc/2/commony/jsonrpc - También se registran los intentos que nunca llegan a la comprobación de la contraseña — por ejemplo, inicios de sesión sin un identificador de sesión válido
- Un acceso fallido al gestor de bases de datos también se contabiliza; es el intento de inicio de sesión más grave de todos
El umbral para los inicios de sesión está fijado en diez, y el motivo es una medición: de nueve inicios de sesión fallidos en diecisiete días, la mayoría procedía de clientes que configuraban ellos mismos el acceso en un otro dispositivo y escribían el dominio equivocado — en un caso el propio, solo que con un guion en lugar de un punto. Un bloqueo al primer intento fallido no habría afectado entonces a los atacantes, sino a clientes durante la configuración.
En cambio, quien sigue llamando a la puerta aunque el servidor ya haya respondido «espere un momento», es bloqueado de inmediato. Ese mensaje lo lee una persona y espera; quien lo ignora es un programa. Un patrón propio con umbral cero detecta precisamente este caso, y no puede afectar a ningún compañero: allí solo llega quien ya acumula diez intentos fallidos y después sigue insistiendo.
3. El ataque ya no le cuesta nada al servidor
Una sonda a una ruta como /@fs/../../.env era cara antes
del módulo: Odoo busca la página de error, la renderiza, tropieza
al construir la dirección con los segmentos de puntos y fracasa
entonces también con la página de error de la página de error. Dos
volcados de pila por sonda. Se midieron 28.401 errores de este tipo
en diecisiete días, además de 9.467 errores derivados.
Web RBL interviene en ir.http._match, es decir, antes de la
resolución de rutas. La respuesta se genera sin plantilla, sin acceso a la base de datos
más allá de la comprobación de bloqueo y sin línea de registro. La comprobación
frente a la lista de permitidos, las listas de amenazas y las reglas por país se ejecuta desde la
caché sobre rangos de direcciones ordenados — unos pocos
microsegundos, incluso con más de treinta mil rangos.
4. El cortafuegos expulsa al atacante antes de que llegue
La lista de bloqueo se publica como lista RBL que HAProxy y OPNsense leen directamente. Así, el atacante ya no llega siquiera al servidor web — ni a ningún otro servicio del mismo host. Un acceso detectado una vez como malicioso protege así retroactivamente a toda la máquina.
Tres niveles: bloquear, contar, notificar
No toda solicitud al vacío es un ataque. Por eso Web RBL distingue tres niveles, y el nivel puede cambiarse por patrón sin tocar el código.
| Nivel | La solicitud desencadenante | Consecuencia para la dirección |
|---|---|---|
| bloquear | se rechaza | bloqueada durante 24 horas; tras tres días sospechosos, de forma permanente |
| contar | pasa | solo se contabiliza, sin bloqueo |
| notificar | pasa | se contabiliza con un texto de hallazgo y nunca se bloquea |
Para las listas de amenazas y los países existe un cuarto nivel: sin acceso al inicio de sesión. La web sigue siendo legible, pero el formulario de inicio de sesión y las interfaces quedan cerrados. Es el término medio para todo lo que es sospechoso pero no tiene por qué ser malicioso — Tor, un rango de centro de datos, un país sin clientes.
Qué ataques se detectan
Todos los patrones se han contrastado con tráfico real. El número de direcciones distintas figura deliberadamente al lado — muestra si un patrón afecta a un único escáner o a una práctica generalizada.
| Clase de ataque | Solicitudes | Direcciones |
|---|---|---|
Extracción de .env | 57.721 | 223 |
| Sondas PHP | 12.237 | 256 |
| Path traversal con un objetivo valioso | 10.046 | 64 |
| Archivos de configuración | 5.535 | 114 |
| Claves de acceso a la nube | 4.388 | 152 |
| Sondas de WordPress | 3.366 | 385 |
Extracción de .git | 2.811 | 255 |
| Reconocimiento de Odoo (gestor de bases de datos, consulta de versión) | 2.500 | 213 |
Cadenas de herramientas de IA y ejecución de comandos (/mcp, /api/fs/exec) | 2.450 | 74 |
| Instrucciones de compilación (CI/CD) | 1.907 | 88 |
| Endpoints GraphQL | 1.878 | 71 |
Llama la atención la clase más reciente. /api/fs/exec
fue solicitado 369 veces desde 54 direcciones distintas — eso
no es un acceso de lectura, sino un intento de ejecutar comandos. Objetivos
así no existían hace dos años; proceden de las interfaces
de las nuevas herramientas de IA y de las colas de tareas. Quien oriente su defensa solo
hacia WordPress y PHP, no ve nada de esto. En la
puntuación, esta clase pesa en consecuencia mucho.
Listas de amenazas y país de origen
Cuatro listas, 32.851 rangos de direcciones, todas en «solo notificar». Cada lista adicional es una dirección y un nivel.
Una lista de terceros es una afirmación que otra persona
formula, por motivos que desconocemos, sobre tráfico que
nunca hemos visto. Puede ser errónea, estar obsoleta o estar pensada para
otro fin: blocklist.de recoge sobre todo
direcciones que han probado inicios de sesión SSH en otros lugares, y eso
dice poco sobre un servidor web. Por eso Web RBL mantiene las listas de terceros
separadas de la propia lista de bloqueo, y por eso el valor predeterminado es
notificar. Y la propia lista de permitidos siempre prevalece: un cliente que
conocemos pesa más que la valoración de un tercero.
El país de origen consta en cada coincidencia y en cada dirección. Para valorar es insustituible — un intento de inicio de sesión desde el propio país a las diez de la mañana es algo distinto de uno desde un país sin un solo cliente. Para bloquear en bloque sirve poco, y así lo dicen nuestras propias cifras: los atacantes de nuestra lista procedían sobre todo de rangos de nube en Bélgica, Finlandia y los Países Bajos. Un bloqueo de todo lo que queda fuera del área de habla alemana no les habría afectado — pero sí a nuestros propios empleados de vacaciones y a clientes de viaje de negocios.
Las reglas por país se entregan vacías, y la vista explica por qué.
Notificar las configuraciones erróneas en lugar de bloquear
El caso más frecuente en el tráfico real no es ni un ataque ni un visitante, sino un software defectuoso que confunde el servidor web con otra cosa:
- 1.367 accesos a la interfaz web de un NAS QNAP — un cliente de sincronización cuyo destino ya no es correcto. Un único puerto llamó 962 veces.
- 65 consultas de Autodiscover — un Outlook que toma el dominio web por su Exchange
Estas direcciones nunca se bloquean. Un bloqueo no corrige el defecto, lo oculta — y afecta a quien tiene el dispositivo ya mal configurado. En su lugar se crea una entrada con un texto de hallazgo y los dominios afectados, de la que, si se desea, surge automáticamente un ticket: exactamente uno por dirección, y si se cierra y la dirección vuelve a llamar la atención, se reabre el mismo ticket en lugar de crearse uno segundo.
Se detectan QNAP, Synology, Exchange Autodiscover, ActiveSync
y clientes WebDAV, CalDAV y CardDAV. Los patrones indican
nombres de archivo y directorios exactos, nunca meras extensiones:
en el mismo directorio /cgi-bin/ se encuentran las inofensivas
llamadas de sincronización justo al lado de sondas clásicas como
printenv.pl.
La lista de permitidos: direcciones que nunca se bloquean
El precio de un error no es el mismo para todas las direcciones. En un escáner de un centro de datos, una falsa alarma no cuesta nada. En el extremo de un túnel entre sedes, cuesta la sede.
Por eso existe una segunda lista, que precede a la primera: direcciones y redes que nunca se bloquean. No silencia nada — quien figura en ella sigue siendo comprobado y contabilizado, solo desaparece la consecuencia. Esa es la diferencia con una excepción en el cortafuegos: aquella deja ciego, esta solo vuelve paciente.
Se rellena a diario desde dos fuentes: desde el propio cortafuegos con todos los extremos de VPN, para que un túnel recién configurado no dependa de que alguien se acuerde de la lista de bloqueo — y desde los rangos de direcciones publicados por Google y Microsoft para sus rastreadores. Solo así se puede distinguir un Googlebot auténtico de un escáner que se hace pasar por tal. Los motores de búsqueda nunca deben bloquearse; quien los bloquea, saca su web de la indexación sin vuelta atrás.
Rige además una regla más importante que la comparación: una respuesta vacía nunca borra. Si la fuente no responde, responde vacío o de forma incomprensible, la lista permanece sin cambios. Una lista de permitidos que se vacía a sí misma ante una avería se lleva por delante, en el peor momento imaginable, todos los túneles.
Si una entrada de la lista de permitidos lleva asociado un cliente, cada coincidencia procedente de su red se le asigna a él. Así, una configuración errónea tiene de inmediato un interlocutor, sin que nadie tenga que buscar direcciones.
Datos obligatorios y recolectores automatizados de datos
El aviso legal no es una página cualquiera. Debe seguir siendo accesible para las personas, pues un bloqueo sobre ella crea precisamente la infracción que busca un recolector. Al mismo tiempo es la página en la que figuran nombre y dirección — y por tanto el objetivo de la cosecha automatizada.
En la oleada austriaca de reclamaciones por Google Fonts incrustadas, los registros mostraron que los escritos no procedían de visitas aisladas, sino de un barrido automatizado: distintos hosts sin relación entre sí con una diferencia de milisegundos.
Web RBL lo resuelve mediante degradación en lugar de excepción. La
ruta canónica /impressum no coincide con ningún patrón y
sigue siempre accesible. Las grafías ajenas como
/impressum.php — que no pueden
existir en una página de Odoo — se notifican, y quien no
quiera tolerar la cosecha automatizada, cambia un parámetro.
sitemap y robots quedan exceptuados
y, por principio, no son bloqueables: no contienen
datos personales, y obtenerlos es la tarea de cualquier
rastreador de motores de búsqueda.
Dominio e identificador: lo que falta en el registro de accesos
El registro de accesos de werkzeug no anota ni el host solicitado ni el identificador de quien llama. Odoo recibe ambos, por supuesto — sin el host no podría, con varias webs, elegir la correcta. Pero después ya no se puede consultar.
Web RBL conserva ambos datos en cada coincidencia. Eso responde a dos preguntas que de otro modo no pueden responderse: qué web apunta una configuración errónea — y con ello, a qué cliente pertenece el dominio — y si una dirección visita una página o todas. Varios dominios sin relación entre sí desde la misma dirección son el signo distintivo del barrido, y elevan la puntuación.
Cuánto importa el identificador lo mostró un análisis en una
de nuestras webs: más del setenta por ciento de todo el tráfico
correspondía allí a un único agente, repartido entre más de
cien direcciones. Sin el identificador habría parecido un
scraper distribuido. Era GPTBot, el rastreador de OpenAI
— que preguntaba una y otra vez por robots.txt y
se comportaba de forma totalmente correcta.
Los aspectos de seguridad en detalle
1. La detección del proxy — el punto más peligroso de todos
Si Odoo funciona detrás de un proxy inverso y proxy_mode
está mal configurado, el módulo ve en cada solicitud la misma dirección:
la del proxy. Un bloqueo dejaría fuera a todos los visitantes
a la vez.
Por eso Web RBL comprueba antes de cada bloqueo si la determinación de la dirección
es fiable. Exige proxy_mode junto con
una cabecera de reenvío, se niega a trabajar si llega una
redirección sin proxy_mode y se niega
igualmente si hay más de un proxy intermedio. En caso de duda, no se
bloquea.
2. Nunca las redes propias
Los rangos de direcciones privados, loopback, link-local y CGNAT están excluidos de forma fija. No pueden, bajo ninguna circunstancia, acabar en la lista, ni siquiera a mano. Lo mismo vale para las listas de terceros: los rangos privados y reservados, así como las redes absurdamente grandes, se descartan al importarlas.
3. Un fallo propio no debe arrastrar consigo la web
Toda la comprobación se ejecuta dentro de una salvaguarda que captura cualquier error. Lo que aquí falle se registra, y la solicitud continúa sin cambios. Un módulo de protección que, ante un fallo propio, arrastra consigo la web es peor que ninguno. Además, todas las consultas en la ruta de la solicitud se ejecutan sin el idioma del navegador del visitante y sin ordenar por campos traducidos — un visitante con un idioma no instalado no debe hacer fracasar la comprobación.
4. Observar antes de bloquear
Tras la instalación, el bloqueo de direcciones listadas en solicitudes normales está desactivado. Las sondas se rechazan y se contabilizan, todo lo demás pasa. Así se puede observar durante unos días quién acaba realmente en la lista antes de que alguien quede excluido. Lo mismo vale para la detección de comportamiento, las listas de amenazas y las reglas por país: primero notificar, bloquear tras verificar.
5. Patrones estrechos en lugar de redes amplias
Un visitante mal identificado es más caro que una sonda pasada por alto.
Por eso cada patrón lleva su nivel, y este puede
cambiarse por patrón. Una extensión de archivo por sí sola rara vez basta: en
.php hay 14.012 sondas reales frente a un puñado de
enlaces antiguos; en .asp la proporción es la inversa. Estas
decisiones deben medirse, no estimarse.
6. Una liberación manual se mantiene
Quien libera una dirección tenía un motivo. Una nueva coincidencia no anula tácitamente esa decisión.
7. La lista está protegida, pero no es un secreto
El endpoint exige un token y, sin un token válido, responde
con 404, no con 403 — así ni siquiera se
confirma la existencia de la dirección. La comparación se ejecuta
en tiempo constante. La lista en sí no contiene nada confidencial: se
compone de direcciones que han llamado a nuestra puerta por iniciativa propia.
8. Ningún secreto en el registro
En los inicios de sesión fallidos se anota el nombre de usuario intentado, nunca la contraseña. En el gestor de bases de datos, de los valores transmitidos no se lee absolutamente nada: allí figura en primera posición la contraseña maestra, y una entrada en una lista de bloqueo acaba en cada copia de seguridad de la base de datos. La clave de licencia de GeoLite2 figura solo en el parámetro del sistema y en ninguna línea de registro.
9. El señuelo no revela nada aprovechable
Opcionalmente, Web RBL responde a las sondas con contenido inventado que contiene un valor canario inequívoco. Quien consulta ese valor después ha leído la respuesta falsificada y ha actuado en consecuencia — una falsa alarma queda así excluida. Los señuelos no contienen datos aprovechables, ni rutas reales, ni credenciales válidas. Esta función se entrega desactivada, porque cambia el comportamiento de forma visible hacia el exterior.
Lo que el módulo no puede hacer
No sustituye a un cortafuegos ni a un Web Application Firewall. Detecta patrones de sondeo conocidos en las rutas, inicios de sesión fallidos y comportamientos sospechosos — no ataques a formularios ni intentos de inyección en parámetros.
Además, solo ve lo que vuelve por HTTP. Lo que un atacante haga con accesos robados a la base de datos o al buzón de correo, permanece invisible — y precisamente por eso los valores canario son rutas y no credenciales.
Y no sustituye a la diligencia: un módulo que rechaza
sondas de .env no hace inofensivo un archivo .env
servido por descuido.
Disponibilidad
Web RBL está disponible públicamente bajo la AGPL-3 y funciona en producción en nuestras cinco webs:
github.com/Alex0176/odoo-web-rbl
El módulo requiere Odoo 19 Community y no tiene
dependencias aparte de base y web. La
conexión con tickets es opcional y no requiere ningún sistema de
tickets concreto; sin él, simplemente no ocurre nada. El
país de origen necesita la base de datos gratuita GeoLite2 de MaxMind;
si falta, el campo queda vacío y todo lo demás funciona
sin cambios.
Para profundizar: cómo encaja Web RBL en una arquitectura de seguridad completa -- junto con cortafuegos, autenticación de dos factores y permisos, con instrucciones paso a paso: Cómo combinar correctamente la arquitectura de seguridad de Odoo 19.
Agradecemos preguntas, comentarios e informes de errores — preferiblemente como issue en GitHub.