4 minutes
From Cloudflare to Europe: deSEC and dynamic DNS
Becoming “more Europeans” and getting to know “how to do stuff here” is a recurring theme, especially lately, in the IT community.
In the last years, I progressively migrated out of US-based solutions: email, storage, photo backup, calendar sync are just some of the services we rely on and that’s easy to bring back to our continent.
However, in the hyper-connected world of today, we all rely on a system that is heavily controlled by the US: DNS.
Yes, the network community put a lot of effort to ensure that the DNS is now a more regulated and safer service w.r.t. some years back, but it’s not a secret that many DNS queries are forwarded to few DNS providers (and that’s why you should have a fully recursive DNS setup at home), and that some big players control most of the DNS traffic.
However, the problem with few DNS resolvers is just one side of the coin, and I believe it’s even more important to take ownership of our own DNS records (this, of course, if you own some domains).
After 10 years on Cloudflare, it has finally come the time to move the DNS of this domain to a better place. An European place.
European Alternatives has been a valuable place where to start, and my choice went to deSEC, a German no-profit company providing an API-first DNS service. For Free.
So, after some fiddling in transferring the domain to another registrar (since Cloudflare doesn’t allow a domain registered with them to have non Cloudflare DNS), I finally brought back sovereignty in the DNS of girondi.net.
What about the “API first”?
One of the reasons I chose deSEC is the API-friendliness, and the ability to create tokens that are scoped to subdomains. This is something it’s not possible to do with Cloudflare (in the free plan), and exposes to risks if one wants to have a dyndns-like service without relying on external parties.
The use case for this is to regularly update the address of the root, where my website lives, and other handy aliases to remote systems, without the need to CNAME to other services, or share a domain-wide key among all systems.
The documentation for this could be found in the excellent pages of deSEC. One needs to put some brain cycles for this (which is always good), but, for future references, this is how I did it.
(0) move to desec.io
Well, no need for instructions here. Note that by default only one domain per account is allowed. When adding a domain, you can import a DNS zone file. This (exported by your current DNS provider), could save time later.
Make sure that the DNS panel of deSEC has the same records of the previous one. Once done, change the name servers of your domain at the registrar with the ones of desec.
(1) create an API key
Go to Token Management and create a token for your (Linux) computer. We will use this to create the subdomain-scoped tokens.
Create on your computer a script similar to this:
#!/bin/bash
set -eu
echo "Using token $TOKEN"
echo "Creating a token for $SUBDOMAIN.$DOMAIN"
OUT=$(curl https://desec.io/api/v1/auth/tokens/ \
--header "Authorization: Token $TOKEN" \
--header "Content-Type: application/json" --data @- <<< \
'{"name": "dyndns-'$SUBDOMAIN'.'$DOMAIN'", "max_unused_period": "30 00:00:00"}')
echo $OUT | jq
ID=$( echo $OUT | jq .id -r)
TOKEN=$( echo $OUT | jq .token -r)
echo "Current policies:"
curl https://desec.io/api/v1/auth/tokens/$ID/policies/rrsets/ \
--header "Authorization: Token $TOKEN" | jq
echo "Create default policy"
curl https://desec.io/api/v1/auth/tokens/$ID/policies/rrsets/ \
--header "Authorization: Token $TOKEN" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": null, "subname": null, "type": null}' | jq
echo "Create a dualstack DNS policy"
curl https://desec.io/api/v1/auth/tokens/$ID/policies/rrsets/ \
--header "Authorization: Token $TOKEN" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": "'$DOMAIN'", "subname": "'$SUBDOMAIN'", "type": "A", "perm_write": true}' | jq
curl https://desec.io/api/v1/auth/tokens/$ID/policies/rrsets/ \
--header "Authorization: Token $TOKEN" \
--header "Content-Type: application/json" --data @- <<< \
'{"domain": "'$DOMAIN'", "subname": "'$SUBDOMAIN'", "type": "AAAA", "perm_write": true}' | jq
echo "Current updated policies: "
curl https://desec.io/api/v1/auth/tokens/$ID/policies/rrsets/ \
--header "Authorization: Token $TOKEN" | jq
echo "Successfully create a token for $SUBDOMAIN.$DOMAIN: $TOKEN"
Now, assuming you have both curl
and jq
installed:
DOMAIN=yourdomain.com SUBDOMAIN=home TOKEN=<whatYouGetFromDesec> bash create_token.sh
(2) Update the DNS records
For a one-off update, you can do something like this (assuming you have both IPv4 and v6):
#!/bin/bash
DOMAIN=yourdomain.com
SUB=subdomain
TOKEN=yourTokenYouJustCreated
IPv4=$(curl https://checkipv4.dedyn.io)
IPv6=$(curl https://checkipv6.dedyn.io)
echo "IP: $IPv4 $IPv6"
curl -X PUT https://desec.io/api/v1/domains/${DOMAIN}/rrsets/ \
--header "Authorization: Token ${TOKEN}" \
--header "Content-Type: application/json" --data @- <<EOF
[
{"subname": "${SUB}", "type": "A", "ttl": 3600, "records": ["${IPv4}"]},
{"subname": "${SUB}", "type": "AAAA", "ttl": 3600, "records": ["${IPv6}"]}
]
EOF
(3) Create a service to do it for you
Running that manually is boring…
Here is a companion systemd service that does it for you!