Dynamic DNS with Cloudflare
Presented by: Nico van Niekerk
Originally aired on March 8, 2021 @ 3:30 PM - 4:00 PM EST
Build your own Dynamic DNS service using Cloudflare Workers and a Raspberry Pi.
English
DNS
Security
Performance
Transcript (Beta)
Hi, good evening. Tonight I'm going to show you a very simple dynamic DNS script and show you how to use Cloudflare to dynamically update your DNS records if your IP address changes.
This is maybe useful if you want to host something on your home network or you want to, you know, you're sitting on an ISP connection that constantly changes IP address and you want to set up a DNS record to connect to a home VPN or something.
But yeah, it's it's pretty simple. So the way we'll do this, or what we'll need is we'll need obviously a domain.
So we'll register domain and we'll publish that domain on Cloudflare.
We'll use Cloudflare to host the DNS records.
Then we also need to find a way to, you know, to check what your IP address is and to know if it's changed or not.
And we can do that using a worker script.
So, and the other thing we'll need is we'll constantly need to, to run some script at, you know, at your house.
You can use a Raspberry Pi for that, but that script will basically check your IP address and then use the API to update your DNS records at Cloudflare.
So without further ado, let's get started. So first thing we'll do is we'll just go and create a DNS domain.
So I created a domain dynamicdnstest.cf.
And to add this domain to Cloudflare, we can go in Cloudflare and in your Cloudflare account, you can go click add a new site and go and set the site up here.
So dynamicdnstest.cf.
Click on add a site.
And then everything we'll do here, we'll do on a free plan. So you can just use a free domain.
You're going to confirm the plan. So initially Cloudflare will try to scan for any existing DNS records and import them into your domain.
So on this, on this zone, there's going to be nothing. So I don't think we'll come up with anything apart from maybe a SOA or something.
You can also import them in a, in a bind format if you want to.
So we'll just click on continue here.
That's all right. So for Cloudflare to become authoritative for this domain, we'll need to change the DNS, the name server records to add our registrar to point to these two, Arushi and Ed.
So we'll go into, we'll just click there to copy them and we'll go into our registrar.
And we'll go and manage the domain here and we'll see if we can update the name server records.
So let's say name servers over there.
We're going to use custom name servers. And we'll just paste those two name servers in here.
And the other one was Ed. All right. So we're going to change the name servers.
That might take a bit of time depending on the, you know, on how quickly they propagate this change.
So let's just double check that this is right.
We can do a, you know, we can go and do a dig on that domain. So let's do a dig on DynamicDNSTest .cf and we'll just do a try on as well.
Let's just see if we can find the DNS records.
All right, so I don't see those name servers there yet.
So let's just have a look.
Okay, so we might take a bit of time. So the next thing we'll do is we'll say done check name servers.
So Cloudflare will go and check that we've changed them. You know, all of these kind of settings are for, you know, coming to play a bit later when we actually host something on the domain.
So I'll just skip over these for now as well.
All right, and this zone will get activated once Cloudflare can confirm that my name servers have been updated.
So we'll wait on that. So the next thing we want to do is we'll go and set up a We're going to set up a worker script.
And this worker script, our sole purpose of this will be to, it'll be an endpoint that'll check my IP address that I'm coming from and just return that to me.
Similar to ICANN as IP or any of those kind of, you know, check your Internet, your public IP kind of APIs.
So let's go and Let's go and create the script first. Right, so we can set up some sort of Dev domain.
Okay. And then we're going to create the worker. So this is going to be the basic event.
Basically, the listener event. So, and then we want to handle it somehow.
So What we'll do here is Basically, we just want to grab the IP address that the client is coming from and Cloudflare actually has a Has a header called the CF connecting IP header that we inject the client IP address that's hitting our edge.
So we'll go and find that Basically, we want to return a new response that will be using the request object.
So we'll change that to request. And in the request, there's a dot headers.
So we'll use request on headers and from the headers.
We're going to get The CF connecting IP header CF. Actually, I think we need to quote that will be CF dash connecting dash IP.
And the status 200 so that'll be all right.
So that looks all right. I think that's what we need to do.
This is super simple, super simple script. So let's go and save that and then we'll go and test it out as well.
All right, so we've basically gone and set it up on this on this endpoint, which is a Just a dev endpoint for us.
We can go and test it out there. We can see if If we're actually getting what we're needing.
Let's copy that. And let's see what we're getting back.
And that is actually working. So that's pretty cool.
So we can see our public IP address here and I'm running this out of a an EC2 server in AWS.
At the moment, just for, you know, for proving the concept. It's, it's going to be easier for me to change my The IP address my EC2 server than my home than my home network.
So, all right. So now we need to publish this on some path inside of our inside of our zone as well.
So let's go and figure out how to do that.
Right, so we've got our work script working running so we can maybe call this something else we can call this get IP or something makes a bit more sense.
All right.
Now the next thing we want to do is we want to publish this worker script on a on a on a route in our zone.
So let's go back to our zone. And you can see now the cloud phase actually was able to check those NS those name server records and has now activated design.
So any DNS we do here now will will be live so we can go and create Yeah, let's go and create a record.
We're going to say this is going to be, we can make an A record and because the only thing on this will be The only thing on this record will be the worker script.
So it doesn't really need to have a real origin.
There's going to be no origin. Actually, the origin is actually just workers at the edge.
So let's call this Let's call this get IP.
And the IP address.
It doesn't really have to exist and we'll just fake it. Yeah, let's put a broadcast address in and it's going to be proxied because it needs to be intercepted by workers.
So we'll deploy that Cool. So we get we got get IP dot dynamic DNS test dot CF and we're going to deploy the work on there now.
So let's add around And it's going to be for get dash IP dot dynamic DNS test dot CF slash anything Right.
And the work is going to be the get IP worker.
Right, let's save that and then we'll go and test it out as well.
So let's just go and check if that's going to work.
I'm not sure if that training slash is actually going to going to break it or not.
But let's, let's go and check what happens. So this time we want to go and get The round on our network.
Yeah, and that works fine. So we can see we actually we actually get that now for the worker.
In our zone right now we want to use this.
We basically want to use this endpoint from from something within my house and for this purpose of testing will obviously use the easy to instance.
So we're going to create a Python script, just to go and check periodically.
What our IP address is the public IP address and if it's changed and then update the DNS recording for that.
So we'll go and create another DNS record. This is the one we want to track our IP address in so we'll make it needs to be an a record, obviously, as well.
And let's give it a name. We'll just call it dynamic.
It could be anything could be dub dub dub, whatever, whatever. Dynamic IP address will just use something to start off with.
Does really have to Be a real address and we can make a DNS only or proxy.
It doesn't really matter.
For just for testing. Yeah, we'll, we'll make a DNS only so this will not return Cloudflare's IP address.
It will not be proxied. It'll just return the IP address in here.
Let's go and create that record. Alright, so we got the record now.
Right, and we now want to go and set up the Python script.
Right. So in up. So let's go and set up a Python script.
We're gonna We'll use IPython to kind of quickly test it out.
IPython3 Okay, a couple of things we might need is we'll probably need Python requests to actually To actually go and grab this or hit this worker script.
So import requests. Right, and let's test out if we can get that IP address by the worker.
So let's go and say Yeah, so let's go and say, you know, it'll be requests.
So it's basically just a get request.
We're going to do on that on that worker endpoint. So request .get and the worker endpoint is HTTPS And was get-ip.dynamic -dns-test.cf And if we do that, we get a 200 response.
Yeah, that's great. So this is basically a request.
It's an object and inside of that object, there'll be, you know, some content and that'll be Basically what we're looking for is that is that I producing the content, we can get the text value by just going doing a dot text method on that on that request object.
So, and yes, we actually getting it out. So if we do something like print If we just go and test this out.
I just want to see that it's coming through without the without those quotes.
So, If you have a look at that.
Yeah, great. So we're getting an IP address so we can get this in Python. By doing this.
So let's go and build a Python file here. We'll create it. We'll just call it dns-update.py, something like that.
Right. And we want to start with import Requests.
And we want to do something like that.
And we'll, we'll give this will assign this to a variable.
So we'll just say Kill that one. We'll just call it current IP. Current IP address equals that.
Cool. And actually, let's just do the current IP address equals.
Yeah. Now we want to know also what the old IP address was. So the old IP address or the existing IP address in DNS is going to be this one.
Yeah, that's in, you know, in my dynamic record.
So somehow we'll need to go and read that out of out of Cloudflare.
So to do that, we can actually use Cloudflare's got a whole bunch of open, open source tools and scripts published on GitHub.
So we can go and look for that on GitHub.
And there's a Python module that we can actually use to interact with the Cloudflare API.
So the name is Cloudflare-Python. And it looks like we may have to go and just search for it here.
So there's Python Cloudflare.
Yeah, that's the one we want to get. So firstly, we need to obviously go and install this.
So we'll just go and install it via pip. Alright, so let's check.
Let's just quickly exit out of here. We're gonna, I'll just install it globally.
This is just a test instance. You may not have pip.
Sorry, that's going to be Python pip.
Python 3 pip actually. Yeah, we're installing pip.
Alright.
So once we have pip installed, we can actually, we can just go and test that we can get this Cloudflare library installed.
And that's what we're going to use in here as well.
So we may as well import Cloudflare. Capital and a capital F.
So that's kind of the old naming convention. Yeah, that's the right one.
Import Cloudflare. Okay. Right. So pip's installed.
So we can now go and install Cloudflare by pip. Cool.
So that's all done. So let's go and run IPython again. And we're always working with Python 3 nowadays.
Hopefully nobody's using Python 2 anymore. All right.
So what are we trying to do? We're trying to read a DNS record. So actually before we even start this to read a DNS record, we'll need an API key to interact with the Cloudflare API.
So to do that, you can click on your, on your profile.
There's your API tokens. We're going to go and create a token. This token will be a scope token to only do a DNS edit.
So it's going to be able to edit a specific zone's DNS.
We'll create a specific zone only for that zone. And that's all we'll be able to do with this, with this API token.
Right. So we created the token.
It's going to give us the token value there. We'll copy that. Right.
And we'll go back into the zone. Yeah. Now we need to go and configure that token, that API token for for this Cloudflare module here.
It's going to interact with it, with API.
So to do that in our home directory, we can go and just go and create and make a directory dot Cloudflare spell it correctly.
Let's just clean that up.
All right. So if we look at that, we've got the dot Cloudflare directory here.
So, and this is actually, if we go into this Cloudflare module here, right at the bottom, there's actually a section on how to create a profile.
So you can use, so to connect to the Cloudflare API, you go and use Cloudflare dot Cloudflare and you can use the token directly in that call, which is probably not advisable because then you need to save your token in your code or we can specify a profile.
That profile will then look for a configuration file in your Cloudflare directory.
So let's go and find, find where that profile is done. So basically that profile is going to look like this.
We're going to create a file called Cloudflare dot CFG inside of Cloudflare directory, and we're going to give it a name and we'll put the token in there, in that file.
So let's go and create a file with Vim.
All right. We'll go into cert mode. We'll call it, we'll just call it din DNS or something.
Let's just call it dynamic. Okay. Dynamic.
That's the profile name. And for that to work, we need a token. So we'll go and paste, we'll go and paste the token ID in there.
And I think I might have navigated off that.
So we'll just go and create another token actually, because with these API tokens, once you, you know, you'll only get that token value once.
So if you go in there, you know, there's no way we can see this token.
So I'm going to delete this token and we'll just create one again.
Let's go and delete that. All right.
We'll go and create a token, edit DNS. It'll be only for this one specific zone and that's it.
So creating the token that gives us the token ID. We'll go and paste it in there.
Let's go and check if we need quotes around it. No, but it looks like we need those spaces.
Let's just be kind of pedantic about that. All right.
So that's all we need in this, in this file. We're going to save that file.
So the file is there. LL.Cloudflare. Great.
So that file is there. So that means we should be able to, to use the, the Cloudflare module.
So let's go and fire that up. All right.
Let's test it out in IPython again. So import. All right.
So that looks all right.
I think we've managed to create that. So now let's go and initiate the, the Cloudflare API.
So we basically want to say. I actually want to say something like that where we just go and say CF equals Cloudflare.Cloudflare.
And we're going to name the profile in there. Profile equals. That profile we created dynamic.
Okay.
And I think it needs to be text value there. Right. So we've got that sorted out.
So now let's go and list all our DNS records because for this DNS record, we'll need to get a DNS ID for the DNS record as well.
So we'll go and set up that.
We'll just go and check out how to, how to get all the DNS records so we can find ID.
So for that, we're going to, I'll just quickly have a look at the Cloudflare API.
Cloudflare.com.
And we want to go and list the DNS records. DNS list, DNS records.
So this one is just basically you need the zone identifier and the DNS records.
And it's just to get on the zone. So, right. So. Let's get back to our test here.
So cf. Zones.
And we need to feed the zone ID in there. Let me just quickly check how to do that again.
Okay.
So I'll just set up two things we're going to need is a zone ID. So let's see if zone equals now to get our zone ID for this zone that we're in, you can, you can get in a couple of different places.
You can either get it up in the, in the URL bar when you're doing things on the zone itself, or you can just go to the overview page and you'll see the zone ID in here.
So that's what we need for the zone. Right?
So I'll just zone ID is going to be this. And we can call it. equals. Right.
Right. So basically for, to get all the DNS records, we're just going to say cf or we can say cloud.
Sorry. We can say cf. Zones.
Sorry. We want DNS records. And we're just going to put the cf zone in there.
That should give us all the DNS records in the zone.
So we can see these DNS records have an ID and we just want to find the one called dynamic.
So this one is dynamic.
Dynamic DNS test. So that's the zone ID for this one, or actually the DNS record ID.
Right. So we're just going to say cf let's call it cf record equals this.
Right. So now we can basically go and check for that specific record. So same kind of command here, but we'll just say cf record, which we don't have the value in there yet.
We'll just paste it in there. So that just works with this one single record.
Okay. So we'll, we'll need something like this. We'll need, we'll basically say old, old IP is going to be okay.
Let's instantiate that. I think cf equals Cloudflare dot Cloudflare profile equals dynamic.
Okay. Current IP, the old IP is going to be cf dot zones dot DNS records dot get and for that zone and for record for that record.
All right. So that should give us old IP.
Then basically we're just going to say if old IP is not equal to current IP, then we want to update it.
So then we'll just say, you know, let's, let's get a result object back.
So we just want to say cf dot zones dot DNS records. And this time we want to, we want to update it.
So in the, in the API documentation to update a record, update a DNS record, we just going to have to do a put.
Okay. We're the same kind of parameters.
So over there we can do a put dot put.
And for this one, we're going to say in the put, we're going to say for the zone and for this record.
And we need to, for the put, we also need to send some data.
So this data is basically just going to tell it what type of record, what the value is, et cetera.
So we're going to say data equals in this case, we need to basically JSON object here.
We're going to say the type of record. Oops. The type of record is going to be the same.
So we can actually, we can actually feed the old type.
So the old type is going to be you know, it's a type A.
I think we might actually run out of time yet.
Okay. Let me see how far we could get in the next two minutes.
All right. So it's going to be an A record, the name, you know, it's going to have a name, a name value as well.
So the name needs to be the same as it was dynamic dot dynamic DNS test dot CF.
And we also need to give it a value.
So the last thing is going to be the content. That's going to be the value content.
And the content is just going to be basically the current IP. All right.
And that's basically it. So that's basically all there is to this, this, this little script, you can put in a, in a cron tab, in a cron job, and then, you know, just run this every couple of minutes.
If your IP address changes, you up, you automatically update your DNS record and voila, you have a basically rolled your own dynamic DNS service using CloudFleet workers and CloudFleet's DNS API.
Easy as pie. Thank you for your time. Cheers.