Categories
Linux

Dynamic DNS(DDNS) with OpenWRT and Cloudflare

Do you want to update your DNS when your IP changes? Are you using a router running OpenWRT and Cloudflare? Then this short guide is perfect for you!

Let’s dive right into it. The OpenWRT router needs to modify your DNS settings on Cloudflare, so we need to create an API token. We could use the global API token, but we’ll use an API token with more limited access instead.

Creating a token on Cloudflare

Head to Cloudflare and go to My profile -> API Tokens -> Create Token -> Create custom token.

Give your token a name, e.g., OpenWRT DDNS and add the following permissions:

  • Zone, Zone: Read
  • Zone, DNS: Edit

Under Zone Resources, select Include, then Specific Zone and choose your domain, e.g., example.com. Hit Continue to summary and then Create Token.

Remember to take note of this token as you’ll need it later.

Configuring OpenWRT

Next up is configuring OpenWRT to work with Cloudflare. We’ll mostly use the Web GUI, but we’ll also SSH into the router to make a small change to how authentication is done with Cloudflare.

In the Web GUI, do the following:

  1. Go to System -> Software and press Update lists.
  2. Enter “ddns” into the filter field, and press Install on the ddns-scripts-cloudflare and the luci-app-ddns packages.
  3. Log out of the GUI and back in. You should now have a Services -> Dynamic DNS option. Go to it.
  4. Press Edit on myddns_ipv4.
  5. Set DDNS Service provider to cloudflare.com-v4 and click Switch service.
  6. Then set Lookup Hostname and Domain to the domain you want to update, e.g., example.com. Check the Enable and the Use HTTP Secure checkbox, set Path to CA-Certificate to /etc/ssl/certs.
  7. Finally, set the Username to Bearer and paste the Cloudflare token you created into the Password field and hit Save and Apply.

If you want to update a subdomain instead, use the following format in the Domain field: [email protected] and sub.example.com in the Lookup field.

The settings should now look something like this:

Example of how the page might look when you have entered your settings.
Example of how the page might look when you have entered your settings.

Great work. We’re almost done.

Change how your current IP is determined

If you head to Network -> Interfaces and you can see an IPV4-address under WAN, then OpenWRT knows what your current IP is, and you can skip this step.

However, if you don’t see an IP address there, you’ll have to go to Services -> Dynamic DNS -> press Edit on myddns_ipv4 -> Go to Advanced Settings tab and change IP address source to something else.

Start using it

Now, head to Services -> Dynamic DNS and press Restart DDns.

Congratulations! 🎉 It should now be up and running. You can press Edit -> Log file viewer to view the log of what it’s doing.

If you have any questions, feel free to ask! 🙂

Questions and answers

Not all situations are the same, so here are some hopefully helpful answers where the problem is slightly different.

What if I’m using Cloudflare to proxy traffic for the domain I’m using with DDNS?

The setup above works by using DNS to check what IP the domain example.com points to. If the domain doesn’t point to your current IP, then it’s updated.

But what if you’re also using Cloudflare to proxy requests? When Cloudflare is proxying the requests, example.com no longer points at your IP address directly. Instead, example.com points to Cloudflare, and Cloudflare becomes a middleman between your IP and the user.

Proxying can be helpful for multiple things: It hides your IP address from the user, and Cloudflare can cache things like images for you.

The issue arises when you now compare the IP of example.com with your IP. Since you’ll no longer get your own IP when checking the DNS record of example.com, OpenWRT will think that the IP for the domain is wrong and start interacting with Cloudflare to update it.

The thing is that the IP is most likely correct, but it can’t know for sure without using Cloudflare’s API to check.

It goes something like this:

  1. OpenWRT gets the IP of example.com, and Cloudflare returns its own IP’s as the real IP is hidden behind Cloudflare.
  2. OpenWRT thinks that DNS needs to be updated as you got Cloudflare’s IP and not your own.
  3. It connects to Cloudflare using the API and gains access to see the real IP the domain points to through Cloudflare.
  4. If the real IP is wrong, it’s updated to your current IP.

So, as you can see, it will still work, but you’ll have unnecessary interactions with the Cloudflare API.

So you might wonder: How do we avoid unnecessary interactions with Cloudflare?

There is a clever solution to this problem that is possible thanks to Cloudflare supporting CNAME flattening. Let me show you how.

First, create a new subdomain that is mostly random by going to DNS settings for your domain on Cloudflare. If you want to hide your IP, the domain should not be guessable. I’m going to use the subdomain top-secret.example.com in this example. Replace it with your own.

Press the Add record -> choose Type A -> enter top-secret.example.com in the Name field -> enter a incorrect IP like 123.123.123.123 in the IPv4 field. Make sure it’s not proxied and press Save.

How to add the subdomain on Cloudflare.

Next, remove the record for the proxied domain. In my case, that’s example.com. Now, create a new DNS record, for example.com, but this time with the Type CNAME. Point it to top-secret.example.com and enable proxying, then Save.

How to add the root domain back to Cloudflare.

Adding this CNAME will make Cloudflare redirect example.com to top-secret.example.com internally, without exposing the actual IP of your server.

You’re now done with the Cloudflare part. The only thing you need to do now is to make two small changes to your DDNS settings in OpenWRT.

Go to the Basic settings for DDNS, change the Lookup Hostname to top-secret.example.com, and set the Domain to [email protected] (note the @). Click Save and Apply.

Changing the DDNS lookup hostname and Domain in OpenWRT.

Now, head to Services -> Dynamic DNS and press the Start/Stop button twice to restart the service.

This way, DDNS will interact with the secret subdomain(top-secret.example.com) to keep your DNS updated, while the actual domain(example.com) points to the subdomain without exposing the domain or real IP.

You should now have a setup that only talks to Cloudflare when the IP has changed, even if you’re using proxying. Congratulations!⭐

Note that it, by default, might take up to 10 minutes to update the IP. You can view the logs to see what’s going on. (Dynamic DNS -> Log File Viewer tab)😊

5 replies on “Dynamic DNS(DDNS) with OpenWRT and Cloudflare”

In the new RC (21.02) of OpenWRT, the script has been updated. Now, if you set the username field to “Bearer” (captial B) it will automatically authenticate using the token — no script mods needed!

Really? That’s great! I’ll update the post when 21.02 is released.

Thanks for the heads up 👍

UPDATE: The post is now updated to work with 21.02. 😊

If the webpage I want to serve is proxied by cloudflare, then it somehow doesnt work correctly, since nslookup will report the cloudflare proxy servers IP. Is there a way to make it work so that it updates the cloudflare internal DNS to my host instead of checking the nslookup of my webpage?

192732 : ************ ************** ************** **************
192732 note : PID ‘5138’ started at 2021-07-16 19:27
192732 : ddns version : 2.7.8-13
192732 : uci configuration:
ddns.cloudflare_ipv4_mydomain.domain=’mydomain.com’
ddns.cloudflare_ipv4_mydomain.enabled=’1′
ddns.cloudflare_ipv4_mydomain.ip_source=’web’
ddns.cloudflare_ipv4_mydomain.lookup_host=’mydomain.com’
ddns.cloudflare_ipv4_mydomain.password=’***PW***’
ddns.cloudflare_ipv4_mydomain.service_name=’cloudflare.com-v4′
ddns.cloudflare_ipv4_mydomain.username=’placeholderNotused’
ddns.cloudflare_ipv4_mydomain=service
192733 : verbose mode : 0 – run normal, NO console output
192733 : check interval: 600 seconds
192733 : force interval: 259200 seconds
192733 : retry interval: 60 seconds
192733 : retry counter : 0 times
192733 : No old process
192733 : last update: never
192733 : Detect registered/public IP
192733 : #> /usr/bin/nslookup mydomain.com >/var/run/ddns/cloudflare_ipv4_mydomain.dat 2>/var/run/ddns/cloudflare_ipv4_mydomain.err
192733 : Registered IP ‘104.21.38.92
172.67.221.122’ detected
192733 info : Starting main loop at 2021-07-16 19:27
192733 : Detect local IP on ‘web’
192733 : #> /usr/bin/curl -RsS -o /var/run/ddns/cloudflare_ipv4_mydomain.dat –stderr /var/run/ddns/cloudflare_ipv4_mydomain.err –noproxy ‘*’ ‘http://checkip.dyndns.com’
192733 : Local IP ‘X:X:X:X (MyHomeIP)’ detected on web at ‘http://checkip.dyndns.com’
192734 : Update needed – L: ‘X:X:X:X (MyHomeIP)’ R: ‘104.21.38.92 (CLOUDFLARES IP)
172.67.221.122’
192734 : parsing script ‘/usr/lib/ddns/update_cloudflare_com_v4.sh’
192734 : #> /usr/bin/curl -RsS -o /var/run/ddns/cloudflare_ipv4_mydomain.dat –stderr /var/run/ddns/cloudflare_ipv4_mydomain.err –noproxy ‘*’ –header ‘Authorization:Bearer ***PW***’ –header ‘Content-Type: application/json’ –request GET ‘https://api.cloudflare.com/client/v4/zones?name=mydomain.com’
192735 : #> /usr/bin/curl -RsS -o /var/run/ddns/cloudflare_ipv4_mydomain.dat –stderr /var/run/ddns/cloudflare_ipv4_mydomain.err –noproxy ‘*’ –header ‘Authorization:Bearer ***PW***’ –header ‘Content-Type: application/json’ –request GET ‘https://api.cloudflare.com/client/v4/zones/37a6f1a0762fec47713a9c55e49abebf/dns_records?name=mydomain.com&type=A’
192737 : IPv4 at CloudFlare.com already up to date
192737 info : Update successful – IP ‘X:X:X:X (MyHomeIP)’ send
192737 info : Forced update successful – IP: ‘X:X:X:X (MyHomeIP)’ send
192737 : Waiting 600 seconds (Check Interval)

It should also work when proxying the domain(as seen by “Update successful” in your logs).

However, OpenWRT will have to check with Cloudflare by interacting with their API every single time to check what IP Cloudflare is proxying it to.

I’ve added a workaround(post updated) that eliminates these unnecessary requests if you don’t want them while still hiding your IP. I hope it helps. 😉

Leave a Reply

Your email address will not be published. Required fields are marked *