Una CDN o un proxy termina la conexión y abre la suya hacia ti. Por eso tu servidor ve la dirección del proxy en cada petición, y eso rompe en silencio todo lo que dependa de saber quién pregunta.

Qué se rompe

  • La limitación de tasa: todos los visitantes son una sola dirección, así que o se limita a todos o a nadie.
  • Los bloqueos: fail2ban bloquea el proxy, y con él a todo el mundo.
  • Registros y analítica: una dirección para el mundo entero.
  • Reglas por país: el país del nodo de borde, no el del visitante.

Dile al servidor dónde está la dirección real

set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
# ... the rest of the provider's ranges
real_ip_header CF-Connecting-IP;
real_ip_recursive on;
Confía en esa cabecera solo cuando venga de los rangos del propio proxy. Confiar en ella desde cualquier sitio significa que cualquiera puede enviarla y decir que es la dirección que le apetezca, con lo que tu lista de bloqueos se convierte en un arma contra tus propios visitantes.

Y dónde está https

Si el proxy termina el TLS, tu servidor ve http a secas y puede decidir que hay que redirigir al visitante a https, que es justo donde ya está. Eso es un bucle de redirección.

# PHP, before the framework loads
if ((@$_SERVER["HTTP_X_FORWARDED_PROTO"] ?? "") === "https") {
    $_SERVER["HTTPS"] = "on";
}

Comprueba que ha funcionado

tail -5 /var/log/nginx/access.log

Direcciones reales y variadas significan que está bien. La misma dirección en todas las líneas significa que no.

Cuando funcione, cierra los puertos 80 y 443 a todo salvo a los rangos del proxy. Si no, cualquiera que descubra la dirección de tu origen podrá saltarse el proxy por completo.