Docker, Nginx y fail2ban: por qué tu aplicación registra IPs internas y no banea nada
Un hilo en r/selfhosted resuelve un clásico: Jellyfin en un contenedor detrás de un proxy inverso solo ve direcciones del rango interno de Docker, así que fail2ban no tiene nada que filtrar.
Un usuario de r/selfhosted ha cerrado un hilo con una respuesta que sirve para media docena de servicios: si tienes una aplicación corriendo en un contenedor detrás de un proxy inverso y fail2ban no banea a nadie, lo más probable es que la aplicación no reconozca al proxy y esté registrando direcciones internas en lugar de la IP del cliente. Su caso era Jellyfin en Docker con Nginx en el host, y lo que lo arregló fue añadir la dirección del gateway de Docker a la lista de proxies conocidos dentro de Jellyfin.
El síntoma
La configuración era razonablemente dura: Jellyfin en un contenedor, Nginx en la máquina anfitriona delante, y ganas de meter fail2ban para cortar por IP a quien acumule intentos fallidos de login. El problema aparecía al mirar los logs de Jellyfin: toda la actividad llegaba con una dirección del rango 172.16.0.0/12, la red interna de Docker. Nginx tampoco salvaba la situación, porque no tenía autenticación propia configurada, así que sus registros no contenían intentos de login que rastrear.
Sin la IP real del cliente en ningún log, no hay filtro de fail2ban que funcione. La pregunta del autor era si aquello se podía corregir o si había montado mal la infraestructura desde el principio.
La corrección
La aplicación solo lee la cabecera de reenvío del proxy si la petición viene de una dirección que tiene declarada como proxy de confianza. Con Docker de por medio, el tráfico entra por el gateway de la red del contenedor, de modo que ese gateway es el que hay que dar de alta en esa lista. Hasta que no se hace, Jellyfin ignora la cabecera, no resuelve la IP original y escribe en el log la del salto anterior.
El detalle importa más allá de Jellyfin. Es el mismo patrón en cualquier servicio que corras en contenedor detrás de un reverse proxy: si no declaras el proxy como de confianza, la aplicación no tiene forma de saber que la IP que le llega no es la del cliente.
A partir de ahí queda una decisión de operación. Puedes montar el filtro de fail2ban sobre los logs de la aplicación, una vez que ya muestran la IP real, o sobre los logs del proxy, siempre que este escriba la cabecera con el origen. Lo segundo suele ser más uniforme cuando tienes varios servicios detrás del mismo Nginx, pero exige revisar que nada en la cadena de proxies elimine o sobrescriba esa cabecera por el camino.
El hilo no trae nada más: ni versiones concretas, ni configuración completa, ni pruebas de carga. Es un usuario contando qué le funcionó.

