Configuring mod_remoteip with Apache and Cloudflare
By. Jacob
Edited: 2022-09-29 10:19
When you enable Cloudflare for your domain your server will no longer see the IP addresses of your visitors, but rather the Cloudflare proxy endpoints. The visitors IP addresses is still available in the CF-Connecting-IP HTTP request header, but the address in PHP's REMOTE_ADDR will contain the IP address of a Cloudflare endpoint.
Note. CF-Connecting-IP is specific to Cloudflare, and other CDN's may use their own header.
To fix this you can either enable mod_remoteip or you can work around it in your PHP code. But, since request headers can be easily spoofed, you will also need to make sure the request came from Cloudflare so the header can be trusted – this can be done by checking that the IP address belongs to Cloudflare.
Before you move on, keep in mind that doing this on the web server level using mod_remoteip is only one way to do it. You could easily do the same thing by checking the CF-Connecting-IP header in your CMS' code.
Now, configuring mod_remoteip to work with Cloudflare is fairly straightforward, just follow these below steps. E.g.:
1. Enable the mod_remoteip module in the Apache HTTP server:
sudo a2enmod mod_remoteip
2. add a /etc/apache2/conf-available/remoteip.conf file with this content:
RemoteIPHeader CF-Connecting-IP
# IPV4
RemoteIPTrustedProxy 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 104.16.0.0/13 104.24.0.0/14 108.162.192.0/18 131.0.72.0/22 141.101.64.0/18 162.158.0.0/15 172.64.0.0/13 173.245.48.0/20 188.114.96.0/20 190.93.240.0/20 197.234.240.0/22 198.41.128.0/17
# IPV6
RemoteIPTrustedProxy 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 2a06:98c0::/29 2c0f:f248::/32
Note. Check this url for an updated list of IPs: https://www.cloudflare.com/ips/
Each RemoteIPTrustedProxy directive can contain multiple IPs separated by space, I only added two separate RemoteIPTrustedProxy's to make it more readable.
3. Enable the remoteip.conf configuration file:
sudo a2enconf remoteip.conf
4. Reload or Restart Apache to make the changes go live:
sudo systemctl reload apache2
5. (optional) Change the log format in /etc/apache2/apache2.conf to use %a instead of %h:
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
Note. The %a directive is basically the users IP address, while %h is the host name. If the HostnameLookups is set to Off (default) for your Apache configuration, this is not needed, since %h logs the IP instead of the host name if this is off.
Enabling this is bad for the internet as a whole, since it will trigger at least a single host nameserver lookup for each client request.
What happened to mod_cloudflare?
The mod_cloudflare module is no longer maintained, but although it might still work, it is recommended you move to using mod_remoteip. In fact, I did not even notice it until recently, despite it being more than two years since it was announced.
In practice this means that mod_cloudflare might not be updated with the IP addresses of Cloudflare's CDN endpoints, potentially resulting in inaccurate IP address information on your users.
mod_cloudflare vs mod_remoteip
Both mod_remoteip and mod_cloudflare work in the same way, so it should be fairly simple to shift to mod_remoteip when you are ready. Just remember to actually disable mod_cloudflare and verify that things are working:
If you use mod_remoteip, you will need to manually whitelist Cloudflare's IP addresses. This is done so that people will not be able to spoof their IP addresses simply by changing the value of the CF-Connecting-IP header – only your CDN should be allowed to set this header.
Tell us what you think: