Configuring Cloudflare’s CF-Connecting-IP Header

Since when Cloudflare proxy is enabled, requests to the web server will come from Cloudflare servers, and not directly from users, you need to configure the CF-Connecting-IP header, which transmits the user’s real IP address. After configuration, it will be displayed as before in logs and requests.

If Apache2, then activate the remoteip module:

a2enmod remoteip
systemctl restart apache2

Let’s open the required configuration file:

nano /etc/apache2/conf-enabled/remoteip.conf
or
nano /etc/apache2/sites-available/ixnfo.com.conf

And we will add:

RemoteIPHeader CF-Connecting-IP
# cloudflare.com/ips
RemoteIPTrustedProxy 173.245.48.0/20
RemoteIPTrustedProxy 103.21.244.0/22
RemoteIPTrustedProxy 103.22.200.0/22
RemoteIPTrustedProxy 103.31.4.0/22
RemoteIPTrustedProxy 141.101.64.0/18
RemoteIPTrustedProxy 108.162.192.0/18
RemoteIPTrustedProxy 190.93.240.0/20
RemoteIPTrustedProxy 188.114.96.0/20
RemoteIPTrustedProxy 197.234.240.0/22
RemoteIPTrustedProxy 198.41.128.0/17
RemoteIPTrustedProxy 162.158.0.0/15
RemoteIPTrustedProxy 104.16.0.0/13
RemoteIPTrustedProxy 104.24.0.0/14
RemoteIPTrustedProxy 172.64.0.0/13
RemoteIPTrustedProxy 131.0.72.0/22
RemoteIPTrustedProxy 2400:cb00::/32
RemoteIPTrustedProxy 2606:4700::/32
RemoteIPTrustedProxy 2803:f800::/32
RemoteIPTrustedProxy 2405:b500::/32
RemoteIPTrustedProxy 2405:8100::/32
RemoteIPTrustedProxy 2a06:98c0::/29
RemoteIPTrustedProxy 2c0f:f248::/32

Let’s check the configuration and restart apache2:

apache2ctl configtest
systemctl restart apache2

If the web server is nginx, then add to the site configuration:

real_ip_header CF-Connecting-IP;
# cloudflare.com/ips
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;

Let’s check the configuration and restart nginx:

nginx -t
service nginx restart

Done, CF-Connecting-IP header is configured.

You can also write a script that updates Cloudflare’s IP addresses, but in practice, they rarely change; the last change date is visible on the page listing them.
For example, a script can retrieve them from the official links www.cloudflare.com/ips-v4 and www.cloudflare.com/ips-v6, save them to a file, and run nginx -s reload to apply the changes.

You can also optionally restrict ports 80 and 443 to Cloudflare networks only. This prevents direct requests to the “Origin IP” server IP address or domain if someone already knows the server’s IP address and has it registered in their local DNS or hosts file. This is because, for example, some services store DNS record change history.

Example script:

#!/bin/bash
for ip in $(curl -s https://www.cloudflare.com/ips-v4); do
    iptables -A INPUT -p tcp -m multiport --dports 80,443 -s $ip -j ACCEPT
done

for ip in $(curl -s https://www.cloudflare.com/ips-v6); do
    ip6tables -A INPUT -p tcp -m multiport --dports 80,443 -s $ip -j ACCEPT
done

#iptables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP
#ip6tables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP
#iptables -nvL
#ip6tables -nvL

Or manually:

iptables -A INPUT -s 173.245.48.0/20 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 103.21.244.0/22 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 103.22.200.0/22 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 103.31.4.0/22 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 141.101.64.0/18 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 108.162.192.0/18 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 190.93.240.0/20 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 188.114.96.0/20 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 197.234.240.0/22 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 198.41.128.0/17 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 162.158.0.0/15 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 104.16.0.0/13 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 104.24.0.0/14 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 172.64.0.0/13 -p tcp -m multiport --dports 80,443 -j ACCEPT
iptables -A INPUT -s 131.0.72.0/22 -p tcp -m multiport --dports 80,443 -j ACCEPT

ip6tables -A INPUT -s 2400:cb00::/32 -p tcp -m multiport --dports 80,443 -j ACCEPT
ip6tables -A INPUT -s 2606:4700::/32 -p tcp -m multiport --dports 80,443 -j ACCEPT
ip6tables -A INPUT -s 2803:f800::/32 -p tcp -m multiport --dports 80,443 -j ACCEPT
ip6tables -A INPUT -s 2405:b500::/32 -p tcp -m multiport --dports 80,443 -j ACCEPT
ip6tables -A INPUT -s 2405:8100::/32 -p tcp -m multiport --dports 80,443 -j ACCEPT
ip6tables -A INPUT -s 2a06:98c0::/29 -p tcp -m multiport --dports 80,443 -j ACCEPT
ip6tables -A INPUT -s 2c0f:f248::/32 -p tcp -m multiport --dports 80,443 -j ACCEPT

If the default INPUT policy is DROP, then we delete the allow rules; if it is ACCESS, then the deny rules should always be after the allow rules:

iptables -D INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -D INPUT -p tcp -m tcp --dport 443 -j ACCEPT
ip6tables -D INPUT -p tcp -m tcp --dport 80 -j ACCEPT
ip6tables -D INPUT -p tcp -m tcp --dport 443 -j ACCEPT

iptables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP
ip6tables -A INPUT -p tcp -m multiport --dports 80,443 -j DROP

See also my article:
Setting up Cloudflare proxy

Leave a comment

Leave a Reply