Configuring ferm to allow connection only from cloudflare CDN
Posted on
Problem
VPS for this site is really slow. I wanted to speed up site load a bit. So I signed up on Cloudflare and set up CDN for it.
What now? Site is still available via ip directly (So if someone want to find it's real ip he/she could just scan entire internet and try to make GET / request with HOST header secwall.me - not so easy task, but real).
This is really THE issue if you are going to use cloudflare as DDoS protection. Attacker task may be really simplier if he/she knows that you use specific hoster (Leaseweb/Digital ocean/etc.).
Solution
Warning! This makes your site unavailable without cloudflare. You will need to disable firewall protection to make it work.
I prefer to use ferm for automatic iptables configuration. Cloudflare gives us a list of it's ip addresses in machine parseble format.
Here is simple shell script for downloading this list and checking if it was changed:
#!/bin/sh
wget https://www.cloudflare.com/ips-v4 -O /tmp/cloudflare-ips-v4.list
LOCAL=`md5sum /etc/ferm/cloudflare-ipv4.list | cut -d\ -f1`
CLOUD=`md5sum /tmp/cloudflare-ips-v4.list | cut -d\ -f1`
if [ "$LOCAL" != "$CLOUD" ]
then
mv /tmp/cloudflare-ips-v4.list /etc/ferm/cloudflare-ipv4.list
/etc/init.d/ferm reload
fi
And example ferm configuraition:
domain ip {
table filter {
chain INPUT {
policy DROP;
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
interface lo ACCEPT;
@def $CLOUDFLARE = `cat /etc/ferm/cloudflare-ipv4.list`;
interface eth0 proto tcp saddr $CLOUDFLARE dport 80 ACCEPT;
proto icmp ACCEPT;
proto tcp dport ssh ACCEPT;
}
chain OUTPUT {
policy ACCEPT;
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
}
chain FORWARD {
policy ACCEPT;
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
}
}
}
domain ip6 {
table filter {
chain INPUT {
policy DROP;
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
proto (ipv6-icmp icmp) ACCEPT;
proto tcp dport ssh ACCEPT;
}
chain OUTPUT {
policy ACCEPT;
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
}
chain FORWARD {
policy ACCEPT;
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
}
}
}
Shell script should be placed is cron.hourly (or daily). This will make rules update automatic.