Skip to content

Instantly share code, notes, and snippets.

@AndrewJDR
Last active February 24, 2021 08:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndrewJDR/47ea02e7d5b4665d705e to your computer and use it in GitHub Desktop.
Save AndrewJDR/47ea02e7d5b4665d705e to your computer and use it in GitHub Desktop.
Cloudflare whitelist iptables update cron script
#!/bin/bash
# Based on a template iptables config file, create a new
# iptables file that includes whitelist rules for CloudFlare's
# servers to connect to our HTTP and HTTPS ports. This is useful
# if you want to really lock down your web server so that it only
# communicates with cloudflare's servers, not with the general public.
# It works like this:
# * Get an up-to-date list of CloudFlare's server IPs
# * Read in config template from /etc/sysconfig/iptables.template
# * Output an iptables configuration file /etc/sysconfig/iptables
# ( $CFRULES from the template file becomes the CloudFlare whitelist rules in the output.)
# * Restart iptables to load the new firewall rules -- only does this if the rules got updated.
##
# Make sure you have:
# * An /etc/sysconfig/iptables.template file containing all your iptables rules.
# It should look very similar to /etc/sysconfig/iptables, so I suggest
# "cp /etc/sysconfig/iptables /etc/sysconfig/iptables.template" as a first step.
# * A line containing only $CFRULES somewhere in your iptables.template file
# * Either ":INPUT DROP [0:0]" at the top of your iptables.template,
# or some rule below $CFRULES that blocks all input traffic to your ports 80/443.
# Note this REPLACES your /etc/sysconfig/iptables file.
# Again, before running the script, you should probably just
# "cp /etc/sysconfig/iptables /etc/sysconfig/iptables.template", then drop a $CFRULES line in there.
IPT_TEMP=/tmp/iptables.new
CFRULES=""
IPS=$(curl --max-time 10 --silent -S https://www.cloudflare.com/ips-v4)
if [ "$?" = "0" ]; then
for line in $IPS; do
line=$(echo "$line" | tr -c --delete "[:digit:]./")
CFRULES+="-A INPUT -p tcp -m multiport --dports 80,443 -s $line -j ACCEPT
"
done
eval "cat <<< \"$(</etc/sysconfig/iptables.template)\"" > $IPT_TEMP
diff -q $IPT_TEMP /etc/sysconfig/iptables
if [ -s $IPT_TEMP -a "$?" = "1" ]; then
mv -f $IPT_TEMP /etc/sysconfig/iptables
/etc/init.d/iptables restart
else
rm -f $IPT_TEMP
fi
fi
# An example iptables.template file. You'll probably want to tweak this.
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
# Pings
-A INPUT -j ACCEPT -p icmp --icmp-type destination-unreachable
-A INPUT -j ACCEPT -p icmp --icmp-type source-quench
-A INPUT -j ACCEPT -p icmp --icmp-type time-exceeded
-A INPUT -j ACCEPT -p icmp --icmp-type echo-request
# SSH
-A INPUT -j ACCEPT -p tcp --dport 22
# Loopback
-A INPUT -i lo -j ACCEPT
# Stateful
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# Whitelist Cloudflare IPs
$CFRULES
# All other input traffic gets dropped, per the default policy rules at the top.
COMMIT
@AndrewJDR
Copy link
Author

Tested on a CentOS/RHEL server.

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