I use cloudflare to proxy requests to the server hosting this site, as it adds protection such as DDoS and such. But if someone knows the IP address of the server, they can connect directly, bypassing the protections provided by Cloudflare. Cloudflare publishes the IP address range CIDR’s that they use on their website, but it is also accessible via an API call. Because I didn’t want to spend time typing the commands individually, I wrote a bash script, well I started with a bash script, then thought I should write it in Go, but after spending a couple hours messing around with Go, I decided to actually use bash, which was a lot easier.
I spent some time in the cloudflare interface trying to add a new API token which was scoped to call the IPs page, but couldn’t find anything that listed it as allow. This is because the IPs API call doesn’t require authentication, which is what I expected at first, but never tested the curl call without API token. It was only when they API call was working on my server without the variable specified, that I realized that the API key does not have to be sent. This makes sense as the page of IP CIDRs is publicly accessible.
Out of the box, Ubuntu comes with UFW (which stands for Uncomplicated Firewall). It is a daemon which uses IPTables (kernel level firewall standard on Linux) on the backend to apply the rules.
Where is the bash script?
I wrote the bash script, which is really simple. I just use curl and jq to parse the response from the API. I had to use sed to remove the JSON list attributes and double quotes to make a bash array, stackoverflow article here. The script is here:
|
|
The script first calls the Cloudflare API ips endpoint “https://api.cloudflare.com/client/v4/ips" and saves the response in the “res” variable. It then uses jq - looking for the .result.ipv4_cidrs node in JSON, then there is some sed find, replace which removes the square brackets, commas and double quotes. Pretty simple overall. More information on the API call can be found at the cloudflare docs here.
To test the script, I added the “–dry-run” flag to the command, this will echo out the rules that will be applied, and will show an error if it has issues. I recommend you do this is running it, just as a sanity check. I might update the script to add those tags if a flag is specified when it is run.
Conclusion
I have yet to set this up as a cron job or something, this would allow the rules to be updated automatically when Cloudflare adds new servers in new CIDR blocks. I tested the script and if the CIDR block is already added, UFW will not apply the rule. This saved me some time as I was thinking of a way to save the response and check to see if the CIDR range was already added. In the future I might detail how to setup a cron job, or maybe systemd service (which I think can run scheduled), to allow the script to run on an interval and automate adding the IP address CIDR’s.
comments powered by Disqus