Skip to content

Instantly share code, notes, and snippets.

@fulopattila122
Created November 6, 2024 09:16
Show Gist options
  • Save fulopattila122/c00cb21b8fa30b6dc2807cd16414902e to your computer and use it in GitHub Desktop.
Save fulopattila122/c00cb21b8fa30b6dc2807cd16414902e to your computer and use it in GitHub Desktop.
Synchronize Cloudflare IP list from API with Linux Firewall (iptables)
#!/bin/bash
# Path to the IPs list
CF_IPS="/var/local/cloudflare_ips.json"
if [ -f $CF_IPS ]; then
OLDETAG=$(cat $CF_IPS| jq -r '.etag')
else
OLDETAG='XXXX'
fi
# Fetch latest Cloudflare IP list
APIRESULT=$(curl -s https://api.cloudflare.com/client/v4/ips)
if [[ $? -ne 0 || $(echo $APIRESULT | jq -r '.success') != "true" ]]; then
echo "There was an error fetching the Cloudflare IP lists"
echo $APIRESULT | jq -r '.errors'
exit 1
fi
echo $APIRESULT | jq '.result' > $CF_IPS
ETAG=$(cat $CF_IPS| jq -r '.etag')
if [ $ETAG == $OLDETAG ]; then
echo "The Cloudflare IP range is unchanged. Firewall rules remain the same."
exit 0
fi
# Load the current rules for comparison
FW_IPV4=$(iptables -L INPUT -v -n | grep tcp | grep dpt:80)
FW_IPV6=$(ip6tables -L INPUT -v -n | grep tcp | grep dpt:80)
CF_IPV4=$(echo $APIRESULT | jq -r '.result.ipv4_cidrs[]')
CF_IPV6=$(echo $APIRESULT | jq -r '.result.ipv6_cidrs[]')
# Apply the new rules if there are changes
if [ "$FW_IPV4" != "$CF_IPV4" ] || [ "$FW_IPV6" != "$CF_IPV6" ]; then
# Clear current rules on TCP 80
# Remove existing rules for port 80 only
iptables -D INPUT -p tcp --dport 80 -j ACCEPT 2>/dev/null
iptables -D INPUT -p tcp --dport 80 -j DROP 2>/dev/null
ip6tables -D INPUT -p tcp --dport 80 -j ACCEPT 2>/dev/null
ip6tables -D INPUT -p tcp --dport 80 -j DROP 2>/dev/null
# Add Cloudflare IPs for IPv4
for ip in $CF_IPV4; do
iptables -A INPUT -p tcp --dport 80 -s "$ip" -j ACCEPT
done
# Add Cloudflare IPs for IPv6
for ip in $CF_IPV6; do
ip6tables -A INPUT -p tcp --dport 80 -s "$ip" -j ACCEPT
done
iptables -A INPUT -p tcp --dport 80 -j DROP
ip6tables -A INPUT -p tcp --dport 80 -j DROP
echo "Firewall updated with latest Cloudflare IPs."
else
echo "No changes in Cloudflare IPs. Firewall rules remain the same."
fi
@fulopattila122
Copy link
Author

I usually put this script in the /usr/local/bin folder. Afterwards, it can be added to the crontab so that it runs periodically.
In the sample, it runs every 4 hours at XX:15 (00:15, 04:15, 08:15, etc.):

15 */4 * * * /usr/local/bin/sync_cf_ips_with_firewall.sh >> /var/log/firewall_update.log 2>&1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment