What's the correct way to block non-Cloudflare traffic now that their IPs are trusted by default?

I read that as of v5.4.9, Cf's IPs are trusted by default, so how do I block traffic that doesn't come from them?

In .htaccess, I've tried this:
Apache config:
Require all denied
Require ip
and this:
Apache config:
Order Allow,Deny
Allow from
I've also tried both wrapped in a <RequireAny> tag.

Also tried the Access Control lists in the config manager GUI, even though you advise not to. It kills the whole site because every request gets a 403 response, but I can see in my browser's dev tools that the request is definitely going through Cloudflare. It's behaving as though Litespeed trusts Cloudflare, thus sets the remote address of the request to my real IP (based on the header Cloudflare sets) but then that real IP doesn't match the Cf IP ranges I've set, so the request is blocked.

If it's not as I suspect, then why is this simple Require ip rule failing? I've also tried it without the Require all denied which doesn't get denied through Cf, but nor is it denied when I force a direct request to the server from the command line using cURL, e.g.:
curl --resolve myhost.example:443: https://myhost.example/real-page --dump-header - | less
I get 200.

The normal rules are blocking either everything or nothing at all, so how do I limit traffic to only that which comes from Cloudflare?
@serpent_driver Thanks but I can't block traffic at the server level, that would mean other sites on the server are all forced to used Cloudflare as a proxy, which isn't going to happen. I know how to use firewalls and iptables/ufw work just fine for simple IP access lists.

This is something that LSWS should be able to handle.
@serpent_driver Please stop recommending tools that are massive overkill for a basic, Apache-compatible directive. I'm not converting an entire server to cPanel just to implement a single directive on one site.
I compared the environment of proxied and non-proxied requests with a line of PHP. It is as I suspected, Litespeed sets the REMOTE_ADDR env var to my real IP, and PROXY_REMOTE_ADDR to Cloudflare's origin. I didn't expect this as I hadn't set Use Client IP in Header in Litespeed's config manager, it doesn't specify a default in its help tooltip, and editing it selects No by default. Its default must be Trusted IP Only.

If I set it to "No" everything goes back to normal, but that means I'd have to maintain that list of trusted IPs myself rather than rely on Litespeed's internal version. Instead, I explicitly set that option to Trusted IP Only, then tried this:
Apache config:
It's supposed to have been supported since v5.4.2 but it didn't work, direct requests were allowed through. What worked was this:
Apache config:
# allow loopback addresses
RewriteCond %{REMOTE_ADDR} !^127\.
# this should work but lsws bug gives bad value in SERVER_ADDR
RewriteCond %{REMOTE_ADDR},%{SERVER_ADDR} !^([^,]++),\1$
# instead you have exclude by literal IP
RewriteCond %{REMOTE_ADDR} !=
RewriteRule ^ - [NS,R=403]
Uglier, but should do the job since it doesn't use (forgeable) HTTP headers.

I imagine that backwards-incompatible change to remote IP handling would have broken a number of sites' configurations, and Require env doesn't seem reliable, so it would be good if staff addressed those issues.
Last edited: