PiVPN, Static/Dynamic Server Names, and CloudFlare DNS – Part 2

I talked about how to use PiVPN to set up an OpenVPN server on a Raspberry Pi at home previously, here and here. The next step for me was to use CloudFlare as a DNS server, instead of signing up for yet another internet service and having another login here or there to worry about.

This very smart guy, Tomasso Barbato, wrote up how to do it, but he includes two versions, an APIvUnknown and an APIv4 version. CloudFlare only supports the APIv4 version as of next month, I guess, so I’m copying the scripts here, as many of my referenced internet pages have gone offline in recent months. Read his page, though, so that you know what to do. I’ve also bolded the variables so that you can simply run a Replace All command in a text editor to easily adapt the scripts for your use. An enterprising hacker would create a bash script to automate all the other scripts, but…

Initial setup

This should be pretty easy, but:

  1. Go to CloudFlare
  2. Add an A record to your domain through the DNS page
  3. Use your current IP address of your server for the record
  4. Read the page to learn how to do it, but use my edits for an easier time.

The important variables

FULL-DOMAIN: example.com
SUB-DOMAIN: sub.example.com

From the CloudFlare user settings page

EMAIL: Account Email:    X-Auth-Email: [email protected]
KEY: API Key:    X-Auth-Key: 9a7806061c88ada191ed06f989cc3dac

*Note: the API Key is the shorter of the two keys that you have the option of requesting

Use scripts to obtain

ZONE-ID: Zone ID (domain name): “id”: “dac9320b638f5e225cf483cc5cfdda41”
RECORD-ID: Record ID (subdomain/A record): “id”: “8ada191ed06f989cc3dac9a7806061c8”

*Note: I’m using a VARIABLE: explanation: example format here.

The scripts

Get Zone ID:
curl -X GET "https://api.cloudflare.com/client/v4/zones?name=FULL-DOMAIN" \
  -H "X-Auth-Email: EMAIL" \
  -H "X-Auth-Key: KEY" \
  -H "Content-Type: application/json" | jq .
Get Record ID:
curl -X GET "https://api.cloudflare.com/client/v4/zones/ZONE-ID/dns_records?name=SUB-DOMAIN" \
  -H "X-Auth-Email: EMAIL" \
  -H "X-Auth-Key: KEY" \
  -H "Content-Type: application/json" | jq .
Bash script for crontab

[ ! -f /var/tmp/current_ip.txt ] && touch /var/tmp/currentip.txt

NEWIP=`dig +short myip.opendns.com @resolver1.opendns.com`
CURRENTIP=`cat /var/tmp/currentip.txt`

if [ "$NEWIP" = "$CURRENTIP" ]
  echo "IP address unchanged"
  curl -X PUT "https://api.cloudflare.com/client/v4/zones/ZONE-ID/dns_records/RECORD-ID" \
    -H "X-Auth-Email: EMAIL" \
    -H "X-Auth-Key: KEY" \
    -H "Content-Type: application/json" \
    --data "{\"type\":\"A\",\"name\":\"SUB-DOMAIN\",\"content\":\"$NEWIP\"}"
  echo $NEWIP > /var/tmp/currentip.txt


By using this script, I now have an OpenVPN server that is somewhat protected by CloudFlare that I can access anywhere and whenever I want, no matter if my home router reboots or if I change internet providers.

There is a caveat: CloudFlare can only protect ports that are used with HTTP HOST headers, SSH or OpenVPN or any other protocol requires the A record to disable its CloudFlare protection. This exposes your IP address somewhat, but it is also protected somewhat. There’s a tradeoff between domain name privacy and personal convenience here.

I also read that a SRV record hides the IP of an origin server better than an A record, so that’s a logical next step, but not one that I have time for right now.


Photo by Nguyen Vu Hung (vuhung) cc