Odoo es accesible desde Internet abierto en nuestras cinco webs, y eso no es una excepción, sino lo normal: quien ofrece un catálogo, una tienda o un acceso de clientes tiene un servidor público. Basta una sola contraseña vulnerable, un archivo de configuración olvidado o un permiso demasiado generoso para que un servidor público se convierta en uno abierto.
Este artículo muestra cómo proteger Odoo 19 correctamente — no con una única medida, sino con varias capas que se complementan entre sí: cortafuegos y proxy inverso, nuestro módulo de código abierto Web RBL, autenticación de dos factores, política de contraseñas y permisos — y qué intentos de ataque detiene realmente cada una de ellas. Al final encontrará unas instrucciones paso a paso con las que se puede replicar cualquier instalación propia de Odoo.
Contenido de este artículo
- Defensa en profundidad: por qué una sola medida nunca basta
- Capa 1: cortafuegos y proxy inverso
- Capa 2: Web RBL — el puente hacia el cortafuegos
- Capa 3: proteger el propio Odoo (2FA, política de contraseñas, permisos)
- Capa 4: base de datos y operación
- La ruta de inicio de sesión en su conjunto
- Escenarios de ataque y su defensa
- Instrucciones paso a paso
- Preguntas frecuentes
Defensa en profundidad: por qué una sola medida nunca basta
Cada medida de seguridad por sí sola tiene un punto débil. Un cortafuegos no ve lo que ocurre en un formulario de inicio de sesión de Odoo. Una contraseña robusta no protege si ya ha sido robada en otro lugar. Una estructura de permisos no sirve de nada frente a un atacante que ni siquiera ha iniciado sesión todavía. El principio que cierra estas brechas se llama defensa en profundidad (defense in depth): varias capas independientes, cada una de las cuales, por sí sola, podría eludirse — pero no todas juntas.
En nuestro caso son cuatro capas, cada una con una función distinta:
- Cortafuegos / proxy inverso — mantiene alejado lo evidentemente malicioso antes de que llegue siquiera al servidor
- Web RBL — conecta ambos lados: Odoo aprende de su propio registro de aplicación lo que el cortafuegos no puede ver en absoluto, y se lo devuelve
- El propio Odoo — autenticación de dos factores, política de contraseñas, permisos, gestión de sesiones
- Base de datos & operación — copias de seguridad, protección del acceso a la administración, secretos fuera de cualquier registro
Las secciones siguientes repasan cada capa por separado.
Capa 1: cortafuegos y proxy inverso
El cortafuegos es la primera instancia que ve una solicitud y la única que puede mantener a un atacante alejado de cada servicio del servidor — no solo de la web, sino también del servidor de correo, del acceso VPN y de la propia interfaz de administración. Lo que conviene activar en este punto depende del fabricante, pero los elementos básicos son los mismos en OPNsense, pfSense, HAProxy, FortiGate, Sophos o Check Point:
| Función | Contra qué ayuda |
|---|---|
| Versión actual de TLS y métodos de cifrado restringidos | Escucha y manipulación de la conexión; los métodos obsoletos se consideran desde hace años rotos o débiles |
| Listas de reputación y de origen (RBL) | Redes de atacantes conocidas, nodos de salida de Tor, países enteros sin clientes propios — véase más abajo |
| Limitación de frecuencia por dirección | Tanteo de contraseñas y escáneres de directorios que lanzan decenas de solicitudes en segundos |
| Separación entre administración y tráfico de datos | La propia interfaz del cortafuegos no debe ser accesible desde la misma dirección que la web pública |
| IDS/IPS (detección/prevención de ataques) | Patrones de ataque conocidos a nivel de red, con independencia de qué aplicación se ejecute detrás |
| Actualizaciones de seguridad automáticas para el propio cortafuegos | Un cortafuegos sin parchear ya no es un cortafuegos, sino un objetivo adicional |
Listas RBL: la vía estándar por la que se distribuye la reputación
RBL significa Real-time Blackhole List, un término del mundo del correo: una dirección por línea, accesible por HTTP, recargada con regularidad. Prácticamente cualquier cortafuegos puede leer una lista así y construir reglas a partir de ella — OPNsense y pfSense como URL Table Alias, HAProxy como archivo ACL, FortiGate como External Block List, Palo Alto como External Dynamic List, y Cisco, Sophos, Juniper y MikroTik con nombres propios para el mismo principio.
Justo aquí interviene nuestro propio módulo — y justo aquí comienza la segunda capa.
Capa 2: Web RBL — el puente entre la aplicación y el cortafuegos
Un cortafuegos ve paquetes, no lógica de aplicación. No sabe que una solicitud a /xmlrpc/2/common es un intento de inicio de sesión, que veinte rutas distintas en catorce segundos son un escáner, ni que una dirección acaba de adivinar una contraseña con éxito. Todo eso solo lo sabe el propio Odoo. Web RBL, nuestro propio módulo de código abierto (AGPL-3), hace aprovechable ese conocimiento — para el propio Odoo y, distribuido como lista RBL, también para el cortafuegos situado delante.
Listas de amenazas comparadas de forma continua, cada una con su propio nivel.
Un breve resumen de lo que se describe en detalle en el artículo anterior:
- Detección de patrones en rutas: archivos
.env, directorios.git, archivos de configuración, sondas de WordPress y PHP, path traversal, ejecución de comandos a través de nuevas interfaces de IA - Defensa del inicio de sesión que cuenta a lo largo de los reinicios — a diferencia del contador propio de Odoo, que vive en la memoria
- Puntuación de cada dirección de 0 a 100, con justificación en lenguaje claro
- Configuraciones erróneas (QNAP, Autodiscover, Synology) se detectan y nunca se bloquean, porque un bloqueo no corrige el defecto, sino que solo lo oculta
- Listas de amenazas de terceros como Spamhaus, FireHOL y nodos de salida de Tor, comparadas de forma continua
- Lista de permitidos para direcciones que nunca deben bloquearse
Para este artículo son especialmente importantes dos características, porque están directamente relacionadas con el cortafuegos y con el inicio de sesión.
Una lista inerte es una lista en la que se puede confiar
La lista de permitidos — direcciones que nunca se bloquean, por ejemplo las conexiones de las propias sedes — cambia, por lo general, rara vez. Precisamente ese es su valor, no su defecto: cuando una lista tranquila apenas se mueve durante días, cualquier cambio infrecuente llama la atención de inmediato. La actualización automática diaria no existe porque vayan a cambiar muchas cosas, sino para que el cambio infrecuente no tenga que añadirse a mano — y justo ese es el punto en el que uno se olvida. Una de nuestras propias configuraciones erróneas del mes pasado se descubrió exactamente así: no por muchos eventos, sino por el único que nadie conocía, hasta que la API web QNAP de un cliente fue bloqueada por error. Desde entonces QNAP figura en la lista de configuraciones erróneas que nunca se bloquean, sino que solo se notifican.
El inicio de sesión es el lugar que un cortafuegos no ve
Un cortafuegos puede bloquear una dirección. No puede saber si un inicio de sesión ha tenido éxito, y mucho menos si procedía de una dirección que poco antes buscaba credenciales. Web RBL sí: una puntuación a partir de un umbral configurable prohíbe por completo el inicio de sesión, y un inicio de sesión correcto desde una dirección sospechosa se notifica — ese es el eslabón con la siguiente capa.
Capa 3: proteger el propio Odoo
Autenticación de dos factores: un segundo secreto que no es reutilizable
El mayor problema de las contraseñas no es su calidad, sino su reutilización. Una contraseña robada en otro servicio funciona igual de bien en el nuestro, mientras sea la misma. La autenticación de dos factores (2FA, también llamada TOTP) le opone un segundo secreto: un código de seis dígitos que cambia cada treinta segundos y se calcula a partir de un secreto que solo conoce el propio smartphone. Una contraseña robada ya no basta por sí sola.
Odoo 19 Community lo incorpora de serie — como módulo instalable Two-Factor Authentication (TOTP), complementado con una opción alternativa por correo electrónico. Cada usuario lo configura por sí mismo, mediante código QR, con cualquier aplicación de autenticación habitual:
La configuración: escanear el código QR, confirmar una vez el código de seis dígitos, listo.
Pero eso solo ayuda a quienes lo configuran por iniciativa propia — y la experiencia demuestra que, sin obligación, siguen siendo una minoría. Por eso Odoo dispone de una política de obligatoriedad: o solo para empleados (usuarios internos) o para todos, incluidos los usuarios del portal. Sin un segundo secreto configurado, nadie pasa ya del formulario de inicio de sesión sin confirmarlo, al menos, mediante un código por correo electrónico.
Política de contraseñas: una longitud mínima no es algo evidente
Sin un módulo adicional, Odoo Community no exige ninguna longitud mínima para las contraseñas — un usuario puede asignar una contraseña de tres caracteres si nadie se lo impide. El módulo propio Password Policy cierra precisamente esta brecha: una longitud mínima que se impone en el servidor, no solo se sugiere en el navegador. Quien quiera más — un plazo de caducidad obligatorio, un historial contra la reutilización — necesita para ello un módulo de la OCA o de terceros; la versión Community se mantiene deliberadamente ligera.
Permisos: solo quien lo necesita obtiene acceso
Odoo separa de serie tres niveles: usuarios del portal (solo el propio portal de clientes o proveedores), usuarios internos (el backend, con derechos por aplicación) y administradores (acceso sin restricciones, incluidos los ajustes técnicos). El error más frecuente no es una contraseña demasiado débil, sino un rol de administrador concedido con demasiada generosidad: quien solo debe crear facturas no necesita acceso a los ajustes del sistema.
Dos principios soportan la mayor parte de la carga:
Clave de API en lugar de contraseña: cada conexión externa (software de contabilidad, control horario, scripts propios) recibe su propia clave, revocable en cualquier momento, nunca la contraseña del usuario.
Ambas cosas se pueden comprobar en la misma vista en la que se configura también la autenticación de dos factores:
Una vista general, cuatro palancas: contraseña, segundo factor, claves de API, dispositivos conectados.
Sesiones y dispositivos: quién está conectado ahora
La misma vista muestra también desde qué dispositivos está conectada una cuenta en este momento — y permite cerrar la sesión de uno solo o de todos a la vez. Tras la pérdida de un portátil o ante la sospecha de una contraseña comprometida, es el paso eficaz más rápido: la sesión termina de inmediato, con independencia de que la contraseña ya se haya cambiado o no.
Capa 4: base de datos y operación
La cuarta capa es la menos visible y a la vez la más imperdonable, porque un fallo aquí puede echar por tierra todo lo construido antes.
/web/database/manager una interfaz con la que se pueden crear, respaldar, restaurar y eliminar bases de datos — protegida únicamente por una sola contraseña maestra. Esta interfaz debe ser accesible exclusivamente desde el interior o estar totalmente desactivada.
- Copias de seguridad periódicas y verificadas, almacenadas separadamente del propio servidor. Una copia de seguridad que nunca se ha restaurado es una suposición, no una copia de seguridad.
- Los secretos no pertenecen a ningún archivo de registro. Contraseñas, claves de API, datos de licencia — quien escribe extensiones propias debería tratarlos como a la propia contraseña maestra: no registrarlos en ninguna parte, ni siquiera «solo para depurar».
- Mantener los módulos actualizados, también y precisamente los de terceros. Los módulos adicionales libres (OCA y otros) van por naturaleza por detrás de las nuevas versiones de Odoo; antes de cada instalación conviene comprobar qué dependencias se instalan automáticamente.
La ruta de inicio de sesión en su conjunto
Las cuatro capas no actúan una tras otra en habitaciones separadas, sino sobre la misma solicitud, paso a paso. El ejemplo de un inicio de sesión lo ilustra mejor:
Cinco puntos en los que una solicitud maliciosa puede terminar antes de llegar a su verdadero objetivo — y uno solo en el que un usuario legítimo los supera todos.
Escenarios de ataque y su defensa
La siguiente tabla asigna patrones de ataque reales a las capas que realmente los detienen. Varios de ellos no son teoría, sino observaciones propias de diecisiete días de tráfico real en nuestras cinco webs.
| Escenario de ataque | Cómo se desarrolla | Qué lo detiene |
|---|---|---|
| Tanteo de contraseñas | Un script prueba cientos de combinaciones contra el formulario de inicio de sesión o XML-RPC | Limitación de frecuencia del cortafuegos, contador de Web RBL a lo largo de los reinicios, bloqueo tras diez intentos, bloqueo inmediato si se ignora el aviso de espera |
| Credenciales reutilizadas, robadas en otro lugar | El atacante ya conoce nombre de usuario y contraseña — de otro servicio hackeado | La autenticación de dos factores detiene el inicio de sesión a pesar de la contraseña correcta; Web RBL notifica además un inicio de sesión correcto desde una dirección sospechosa |
| Búsqueda de secretos olvidados | Solicitudes automatizadas de .env, .git, claves de acceso a la nube — en nuestro caso 57.721 solicitudes en diecisiete días solo de .env |
Web RBL bloquea en la primera coincidencia; el cortafuegos recibe después la dirección como entrada RBL para todos los demás servicios |
| Escáneres de directorios y rutas | Decenas de rutas inventadas en pocos segundos, en busca de aplicaciones olvidadas | Detección de comportamiento: muchas páginas de error, casi ningún acierto, en poco tiempo — con independencia de que la ruta coincida con un patrón conocido |
| Dispositivo propio mal configurado | Un cliente de sincronización o un programa de correo apunta por error a la dirección equivocada y llama a la puerta cada minuto | Detección como configuración errónea en lugar de ataque, ticket en lugar de bloqueo — el bloqueo no corregiría el defecto, solo lo prolongaría |
| Cosecha automatizada de datos obligatorios | Un recolector consulta páginas de aviso legal con grafías ajenas, a menudo como preparación de una oleada de reclamaciones | La ruta canónica siempre sigue accesible (necesario legalmente); las grafías ajenas se detectan y se notifican o se bloquean |
| Dispositivo perdido o robado | Un portátil o teléfono móvil con la sesión iniciada cae en manos ajenas | Vista de sesiones con cierre inmediato de todos los dispositivos, con independencia de la contraseña |
| Permiso interno demasiado amplio | Una cuenta de usuario con más derechos de los necesarios es comprometida o utilizada de forma abusiva | El mínimo privilegio necesario por aplicación limita desde el principio el daño a lo que la cuenta realmente necesita |
| Abuso de una interfaz externa | Una clave de API robada o un sistema de terceros comprometido accede mediante XML-RPC/JSON-RPC | Claves de API propias y revocables en lugar de la contraseña del usuario; Web RBL vigila también los inicios de sesión RPC fallidos |
| Rastreador de motor de búsqueda mal valorado | Un rastreador legítimo genera tanto tráfico que parece un atacante distribuido — en una de nuestras páginas fue más del setenta por ciento de todo el tráfico, causado por GPTBot | La lista de permitidos con los rangos de direcciones publicados de los motores de búsqueda conocidos evita un bloqueo erróneo que sacaría la propia web de la indexación |
| Módulo de terceros obsoleto con una vulnerabilidad conocida | Se hace pública una vulnerabilidad en un módulo adicional libre; la actualización llega semanas después | Antes de cada instalación, comprobar qué se instala automáticamente; las actualizaciones primero en una instancia de prueba, no a corazón abierto |
| Administración de bases de datos abierta | La interfaz de administración es accesible desde Internet abierto; una contraseña maestra adivinada o débil basta para eliminar o copiar bases de datos | La interfaz no se expone nunca públicamente, la contraseña maestra se mantiene larga, aleatoria y sin anotar en ninguna parte |
Paso a paso: proteger la propia instalación de Odoo
El orden siguiente es el que seguiríamos nosotros mismos — del mayor efecto al ajuste más fino.
1. Imponer la autenticación de dos factores
- Si aún no está instalado: abra Aplicaciones, busque «Two-Factor Authentication» e instálelo (con varias webs se recomienda además «Two-Factor Authentication by Mail» como opción alternativa).
- Abra Ajustes → Ajustes generales → Permisos.
- Active «Imponer la autenticación de dos factores».
- Elija la política: «Solo empleados» para usuarios internos, «Todos los usuarios» si también se quiere incluir a los usuarios del portal (clientes con acceso).
- Guarde. A partir del siguiente intento de inicio de sesión, Odoo exige a cada usuario sin segundo secreto configurado, como mínimo, el código por correo electrónico hasta que haya configurado la aplicación de autenticación.
2. Establecer una longitud mínima para las contraseñas
- Abra Aplicaciones, busque «Password Policy» e instálelo.
- Abra Ajustes → Ajustes generales → Permisos.
- Establezca «Longitud mínima de la contraseña» — doce caracteres son un valor inicial razonable.
- Guarde. La regla se aplica a partir de ahora a toda asignación o cambio de contraseña, sin efecto retroactivo sobre las contraseñas existentes.
3. Revisar los permisos
- Abra Ajustes → Usuarios & empresas → Usuarios.
- Abra cada usuario individualmente y revise la pestaña con los derechos de acceso por aplicación: ¿esta persona necesita realmente «Gerente» o «Administrador», o basta con «Usuario»?
- Revise con especial atención: ¿quién tiene acceso a «Ajustes» en sí? Debería ser un grupo muy reducido.
- En la pestaña «Seguridad de la cuenta» del usuario técnico correspondiente, cree para cada conexión externa (contabilidad, scripts propios, control horario) una clave de API propia, en lugar de transmitir la contraseña del usuario.
4. Instalar Web RBL y observar antes de activar el bloqueo
- Coloque el módulo de github.com/Alex0176/odoo-web-rbl en la ruta de addons e instálelo.
- Observe durante unos días: el menú Web RBL → Análisis muestra qué patrones se activan realmente.
- Solo después active
web_rbl.sperren_aktiv(Ajustes → Técnico → Parámetros del sistema) — a partir de aquí las sondas detectadas se rechazan de verdad. - Integre la lista de bloqueo en el cortafuegos como lista RBL, desde la dirección protegida con token indicada en el módulo (en OPNsense/pfSense como URL Table Alias, en HAProxy como archivo ACL).
5. Proteger el propio cortafuegos
- Haga que la interfaz de administración del cortafuegos sea accesible exclusivamente desde la red interna, nunca desde la misma dirección pública que la web.
- Active las actualizaciones de seguridad automáticas para el software del cortafuegos, siempre que el fabricante las ofrezca.
- Revise la configuración TLS: solo versiones de protocolo actuales, desactive los métodos de cifrado obsoletos.
- Si está disponible: integre una lista de reputación conocida (por ejemplo Spamhaus DROP) directamente en el cortafuegos — con independencia de Web RBL, pues así el cortafuegos ve también el tráfico hacia servicios que Odoo nunca alcanza.
6. Cerrar la administración de bases de datos
- Compruebe si
/web/database/manageres accesible desde fuera — si lo es, establezcalist_db = Falseen la configuración de Odoo o bloquee la ruta a nivel de cortafuegos. - Establezca la contraseña maestra de la administración de bases de datos larga y aleatoria, y no la anote en ningún sitio que pueda leer otra persona.
7. Verificar la copia de seguridad, no solo configurarla
- Configure una copia de seguridad automática y periódica, almacenada separadamente del servidor de Odoo.
- Restáurela realmente al menos una vez y compruebe que la recuperación funciona — una copia de seguridad sin verificar es una suposición.
Ninguno de estos pasos sustituye a otro. Quien aplica solo uno ha reforzado una puerta y ha dejado abiertas todas las demás — quien aplica los siete tiene una defensa que sigue resistiendo incluso cuando falla una capa individual.
Lo que esta arquitectura no sustituye
Ninguna de las medidas descritas hace superflua la diligencia. Un módulo que rechaza sondas de .env no hace inofensivo un archivo .env publicado por descuido. La autenticación de dos factores no protege frente a un usuario que le lee su código a quien le llama por teléfono. Y un cortafuegos no sustituye la decisión de quién necesita realmente qué permiso. La arquitectura de seguridad crea las condiciones para que un error aislado no se convierta de inmediato en un incidente — no libera a nadie de la diligencia.
Preguntas frecuentes
¿Basta una contraseña robusta para proteger Odoo 19?
No. Una contraseña puede ser robada en otro lugar, con independencia de su calidad, y funciona entonces en cualquier servicio que acepte la misma contraseña. Solo la combinación con autenticación de dos factores, un cortafuegos delante y una estructura de permisos sensata ofrece una protección que sigue resistiendo incluso tras el robo de una contraseña.
¿Cómo activo la autenticación de dos factores en Odoo 19?
Instale el módulo «Two-Factor Authentication (TOTP)» desde la gestión de Aplicaciones, active después la obligatoriedad en Ajustes → Ajustes generales → Permisos y elija entre «Solo empleados» y «Todos los usuarios». Cada usuario configura a continuación su propio segundo factor mediante código QR.
¿Qué es una lista RBL y por qué la necesita Odoo?
RBL (Real-time Blackhole List) es una lista de direcciones accesible por HTTP que prácticamente cualquier cortafuegos puede leer. Odoo no incluye por sí mismo ninguna lista de este tipo — nuestro módulo Web RBL cierra esa brecha detectando el tráfico de ataque en el propio registro de la aplicación y devolviéndolo como lista RBL al cortafuegos situado delante.
¿Está Odoo 19 Community suficientemente protegido sin módulos adicionales?
No del todo. Sin el módulo Password Policy no hay longitud mínima para las contraseñas, sin Two-Factor Authentication no hay segundo factor, y sin un módulo como Web RBL Odoo no detecta ni intentos de sondeo ni intentos repetidos de inicio de sesión a lo largo de un reinicio. Los cuatro pueden incorporarse gratuitamente.
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
La descripción completa de funciones, con todos los patrones, la puntuación y las listas de amenazas, se encuentra en el artículo anterior: Web RBL – lista de bloqueo para el tráfico de ataque en las propias webs.
Agradecemos preguntas, comentarios e informes de errores — preferiblemente como issue en GitHub.