Port forward using iptables to web server only if source is CloudFlare
Looking at my web server’s access logs, not surprisingly I discovered traffic originating from IP addresses not belonging to CloudFlare. Initially, I was using Apache .htaccess to allow incoming traffic only if they originated from CloudFlare. This was somewhat sufficient but some hackers continued attempting to find loopholes instead of giving up so I needed to up the level of security and decided to look at ways to drop unwelcome traffic using OpenWRT firewall.
Scheduled download of CloudFlare IP list
Firstly, create a new folder under
/etc/cloudflare for storing IPv4 addresses of CloudFlare. Run the following command to download and store the initial lists into this folder:
wget -q https://www.cloudflare.com/ips-v4 -O /etc/cloudflare/ips-v4
ips-v4 file exist before proceeding. You can verify by typing
cat /etc/cloudflare/ips-v4. You should see a list of IP addresses.
Under OpenWRT Scheduled Tasks, I then added the following lines to:
ips-v4and store it with
.tmpfile extension. This prevents a failed retrieval from overwriting the last good file.
- Restart firewall only if the retrieval of list succeeded. Using CRON syntax, this task is performed every 1st day of the week at 3am.
# Download updated list of CloudFlare IP addresses and restart the firewall 0 3 * * 1 wget -q https://www.cloudflare.com/ips-v4 -O /etc/cloudflare/ips-v4.tmp && mv /etc/cloudflare/ips-v4.tmp /etc/cloudflare/ips-v4 && /etc/init.d/firewall restart
Note: You need
ca-certificates packages to be installed.
Port forward only if source is CloudFlare
Under OpenWRT Firewall Custom Rules, I added the following lines:
# Forward only incoming HTTPS traffic from CloudFlare to web server for cfip in `cat /etc/cloudflare/ips-v4`; do iptables -A PREROUTING -t nat -i <WAN interface> -s $cfip -p tcp --dport https -j DNAT --to <web server IP>:443; done iptables -A FORWARD -p tcp -d <web server IP> --dport https -j ACCEPT
What this does is when the firewall is initialising, it loads the list of IPv4 addresses (already downloaded by the scheduler) and creates one PREROUTING rule per line of IPv4 address to allow port forwarding the HTTPS port 443 while all other traffic sources will be dropped by default. Be sure to replace
<WAN interface> and
<web server IP> with your settings.
Note: I have no use for IPv6 at the moment so I have not added firewall rules for them.
For security reasons I am forwarding HTTPS port 443 only. I strongly recommend that you do the same. If you want HTTP port 80 to be forwarded as well, add the following:
# Forward incoming HTTP traffic from CloudFlare to web server for cfip in `cat /etc/cloudflare/ips-v4`; do iptables -A PREROUTING -t nat -i <WAN interface> -s $cfip -p tcp --dport http -j DNAT --to <web server IP>:80; done iptables -A FORWARD -p tcp -d <web server IP> --dport http -j ACCEPT