¿Cómo bloquear un rango de IP?

Hola, estoy intentando bloquear temporalmente una subred /16 abusiva que está saturando un foro de Discourse con solicitudes. Intenté esto…

…pero todavía estoy viendo una gran cantidad de nuevas solicitudes del mismo rango en /var/discourse/shared/standalone/log/var-log/nginx/access.log.

Dado que estos están configurados en Discourse, estoy bastante seguro de que las IPs son bloqueadas por Discourse, no por NGINX, por lo que aparecerán en los registros de NGINX. Es Discourse quien las bloquea, no nginx. Si deseas bloquearlas para que no aparezcan en los registros de NGINX, podrías bloquearlas con tu firewall.

1 me gusta

Gracias Jay, tienes razón en que todavía aparecería en los registros de Nginx si se bloquea a nivel de aplicación. Sin embargo, el bloqueo a nivel de aplicación tampoco está haciendo lo que esperaría. Intenté conectarme a través de una VPN y luego agregué mi propia dirección IP a la lista de "IPs filtradas", pero aún así me permitió navegar por el foro. Creo que debe llamarse "IPs filtradas" y no "IPs bloqueadas" porque tal vez solo impide que esas IPs registren una cuenta.

Necesito que la aplicación Discourse deniegue el acceso a las páginas solicitadas para las solicitudes que provienen de esas direcciones, y especialmente que no renderice esas páginas, ya que todas esas solicitudes están agotando la CPU.

¿Ve Discourse que vienes de una de las IPs prohibidas si vas a ver el registro del usuario desde /admin/users? (Si estás detrás de un proxy como Cloudflare, entonces Discourse puede estar viendo la IP de tu proxy y no la IP del usuario).

Sí, cuando me conecto a la VPN y luego miro la última IP de mi cuenta de usuario en Discourse, muestra la IP que me dio mi VPN. Sin embargo, cuando abro una ventana de navegador de incógnito e intento registrar una nueva cuenta, no lo permite:

No se permiten nuevos registros desde tu dirección IP.

Así que parece que las “IP filtradas” son solo para el registro, no para prohibir completamente el acceso al sitio web.

Y para complicar aún más las cosas, ufw en el servidor host aparentemente no bloquea las cosas como se esperaba dentro de Docker:

1 me gusta

No estoy seguro de dónde documentamos esto, pero ha surgido un par de veces recientemente.

“IPs filtradas” bloquea registros e inicios de sesión desde IPs bloqueadas que coinciden, pero no sesiones existentes.

No estoy seguro de dónde (si es que) documentamos esto.

3 Me gusta

Gracias por confirmar.

Entonces, ¿cuál sería el método más fácil para denegar solicitudes de una IP o un rango de IPs? Encontré esto, pero parece ser lo opuesto a lo que necesito. (lista blanca en lugar de lista negra) y jugar con la configuración de Nginx dentro del contenedor se siente como un trabajo de hackeo total:

Creo que hacerlo con UFW o IPTABLES. Eso lo elimina antes de que Discourse intervenga. Siempre me da un terror vago meter mano en los firewalls por miedo a bloquearme, pero si te diriges solo al puerto 443 no corres ningún peligro.

Digital Ocean tiene algunas pistas: UFW Essentials: Common Firewall Rules and Commands for Linux Security | DigitalOcean. Simplemente busca ejemplos en Google.

Exactamente mi miedo también. Pero lo habilité en el host y, sin embargo, todavía no está bloqueando el rango de IP problemático. Al parecer, necesita un conjunto complicado de reglas para que aplique las reglas de denegación a los contenedores de Docker.

Oh. Sí. Eso es totalmente cierto. Terminé bloqueando el acceso de mis servidores web basados en Docker a la base de datos postgres basada en Docker (probablemente no sea uno de tus problemas).

Aquí tienes otra idea: Geo Blocking plugin

Gracias, yo también estaba mirando eso, pero ¿no parece permitir el bloqueo de rangos de IP numéricos, solo países enteros?

No lo he instalado últimamente, pero estoy bastante seguro de que sí.

(énfasis añadido)

Pero entonces encontré esto:

Así que creo que eso significa que puedes poner la red que quieras allí.

1 me gusta
/var/discourse/launcher enter app
apt install nano
nano /etc/nginx/conf.d/discourse.conf

Y en el bloque server { añade:

## 2025-10-27
deny 12.34.0.0/16;

Luego guarda y

nginx -t
service nginx reload

No entiendo muy bien por qué sigo viendo accesos desde 12.34.x.x en el access.log de Nginx, pero parece que está funcionando porque el uso de la CPU ha vuelto a la normalidad. Un proceso increíblemente complicado en mi opinión, pero suficiente por ahora para que el sitio vuelva a funcionar.

Sí, pero actualmente solo aceptará números AS y no notación CIDR como 1.2.3.0/24.

1 me gusta

¿Funcionó? Creo que necesitas hacer

sv restart nginx

Pero si no obtuviste un error, me equivoco.

¿Nginx todavía los ve? ¿Muestra que los está sirviendo? ¿Ves eso en el production.log de Rails?

Ah. Quizás debería haber prestado más atención a esa página de Wikipedia sobre números AS.

Creo que ambos son alias antiguos que ahora están mapeados a comandos de systemd, así que systemctl restart nginx sería lo más apropiado.
EDIT: Parece que systemctl no funciona dentro de Docker. Aquí hay algunas explicaciones sobre las diferencias:

Sí, en el access.log todavía aparecen como:

[28/Oct/2025:00:29:27 +0000] "myforum.com" 12.34.56.78 "GET /permalink/12345 HTTP/1.1" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36" "-" 403 691 "-" - 0.000 "-" "-" "-" "-" "-" "-" "-" "-"

Parece que ahora están atacando principalmente permalinks (migrados de una antigua plataforma de foros). ¿Hay algún tipo de laguna con los permalinks que le permite evitar la regla deny? Aún no he revisado el production.log.

En general, diría que la falta de una GUI para inspeccionar los logs de acceso y la ausencia de una lista de bloqueo de IP a nivel de aplicación son limitaciones bastante significativas de Discourse. Es una ocurrencia infrecuente, pero cuando te golpea uno de estos ataques de bots/scrapers/crawlers, solo quieres identificar la fuente y mitigarla inmediatamente, sin perder el tiempo en un montón de archivos de configuración y comandos arcanos, especialmente a niveles profundos dentro de un contenedor Docker con toda la extraña abstracción que ocurre allí. La antigua plataforma de foros de la que migré mostraba una lista simple de los usuarios o IPs con el mayor número de solicitudes durante una ventana de tiempo ajustable, e incluso podía filtrarse por los usuarios y/o IPs que ocupaban la mayor cantidad de tiempo de CPU. De esa manera, podía identificar rápidamente la dirección u rango ofensivo, y luego había una interfaz de apuntar y hacer clic para agregarla a una lista de bloqueo, y lanzaba un 404 para las solicitudes de esas IPs.

Si tienes una regla deny, las cosas todavía se registran en nginx. Y funciona correctamente, porque hay un 403 ahí, lo que significa que se denegó el acceso al cliente.

Estas solicitudes no se reenvían a Discourse. Si deseas saber si tu bloqueo está funcionando correctamente, deberías

  • mirar en el production.log de Discourse en su lugar
  • mirar en los registros de nginx pero ignorar cualquier entrada que tenga un 403 en el campo del código de respuesta HTTP.
3 Me gusta

¿Este tema está resuelto ahora? ¿Hay una publicación de @rgj o @pfaffman que pueda elegir como solución? ¡Parece que colaboraron en esta!

:handshake:

Hola, diría que este problema no se puede resolver en este momento por métodos “normales”. La interfaz de administración de “IP filtradas” no hace lo que la mayoría de los usuarios esperarían, y el método que realmente funciona implica manipular el contenedor docker de Discourse, por lo que es más como una solución improvisada que una solución, al menos en mi opinión. Sería genial si esto tuviera un poco más de atención: