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.
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
Verify that 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-v4
and store it with .tmp
file extension. This prevents a failed retrieval from overwriting the last good file.# 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 wget
and ca-certificates
packages to be installed.
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