Apache - blocking direct requests that bypass Cloudflare when using mod_remoteip

Hi there,

This might be an unusual one. I’ve figures out how to block Apache requests that come direct, rather than via Cloudflare. I’ve also figured out how to restore the visitor’s original IP address in the Apache access logs. What I can’t figure out, is how to do both of these things at the same time.

Example, restoring visitors IP address in the Apache access log:

  1. Enable mod_remoteip

  2. Add “RemoteIPHeader X-Forwarded-For” to the Apache configuration

  3. Change the Apache log format, substituting %h for %a

Example, blocking direct requests that bypass Cloudflare:

  1. Modify Apache configuration for a particular site:

<Directory /var/html/website/public>
Order deny,allow
Deny from all
Allow from 173.245.48.0/20

More Cloudflare IP ranges go here

Both of the examples above work OK, but don’t play nice together. This is because the “Allow from” in the second example is no longer being matched, because Apache is back to having the user’s original IP address, rather than Cloudflare’s IP address.

I’m hoping there is a simple way of bringing both solutions together. Could anyone advise?

Many thanks

Sorry, I wasn’t able to see how to edit my original post. The second example should read:

<Directory /var/html/website/public>
Order deny,allow
Deny from all
Allow from 173.245.48.0/20
# More Cloudflare IP ranges go here
</Directory>
  1. Use RemoteIPHeader CF-Connecting-IP, as X-Forwarded-For can be spoofed by Workers.
  2. You should have a firewall in front of Apache that only allows traffic from Cloudflare IP addresses; don’t rely on Apache for that.

Thanks for your reply. Good catch on CF-Connecting-IP - I followed the documentation on the Cloudflare website but when re-visiting it did mention to use CF-Connecting-IP rather than X-Forwarded-For. I have updated.

Regarding the firewall in front of Apache, we currently have some other virtualhosts which are not yet using Cloudflare, so as far as I know we don’t have a way of denying traffic that comes from outside of Cloudflare in a global manner without stopping our other virtualhosts from working.

You could use RemoteIPTrustedProxy or RemoteIPTrustedProxyList (which you should be using anyway); that will at least prevent direct connections from spoofing IP addresses. Other than that, there isn’t really anything truly safe that you can do within Apache. I know in Nginx, the old IP address gets stored in a variable, but I’m not seeing anything like that in Apache’s docs.

Thanks @Zenexer

I’ve come up with a solution based on your suggestion. Currently we are using a shared IP address for all of our virtualhosts. What I can do is get another IP address - one for virtualhosts that use Cloudflare, and another for the virtualhosts that don’t. I can then deny direct access to the Cloudflare integrated sites via the firewall, using the secondary IP address. This will leave our non-Cloudflare virtualhosts untouched for the time being.

1 Like

That sounds like a good approach. Just remind that you’ll need to explicitly bind to the correct IP addresses, otherwise people could still bypass it by using the alternative IP address. I’m more accustomed to Nginx than Apache, so I don’t know the correct directives off the top of my head, but it shouldn’t be too hard to figure out.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.