How to use DDNS on CloudFlare DNS

Cloudflare API and DNS

For this example we are using a Free Cloudflare account to manage our DNS records. If you don’t have one or your domain is hosted elsewhere you can either transfer it to Cloudflare or update your current providers Name Servers to point to Cloudflare.

Retrieve Zone ID

Once logged in click on the domain you want to use.

Then scroll down and locate the API section, now copy the Zone ID and keep it to hand.

Zone ID:

2ba5972166bcdf34935728843955554e

Create A Record

Now if not already created, click on DNS > Records on the left and add an A Record and set Proxy to OFF and TTL to 1 min

Generate Tokens

Next click in the top right of the screen and select My Profile

Create a Read Token

Now we are going to create 2 Tokens, a Read and Edit one. The first is required to get the Record ID and can be removed afterwards if required for security.

Click on Create Tokens

Then the first option Edit zone DNS

Now under permissions use Zone + DNS + Read. The Zone Resources can be a particular Zone if there are multiple or in this case we’ll just use All Zones.

On the next summery page we just confirm and click Create Token

Now we can see our Read Token, which we copy and make a note of with our other gathered info

Read API Token:

WYlmyM9-9xOSBUDue6_sCErhtvHsqv20nhwXylX7

Create an Edit Token

Next we repeat the process except this time we use Zone + DNS + Edit in the permissions section

Once we have our Edit Token we copy this too

Edit API Token:

5pXqw0U0ZL6GkahuDaBSwVbSc9tLRZYrUEQMRXiq

Retrieve Record ID

The last bit of information we need is the Record ID which we need to run a fetch command on the MikroTik (also possible via Curl on a Linux Machine). Use the following command in a terminal and add your Zone ID and Read API Token found previously.

/tool/fetch url="https://api.cloudflare.com/client/v4/zones/<ZONE ID>/dns_records" http-header-field="Authorization: Bearer <READ API TOKEN>" http-method=get output=user
/tool/fetch url="https://api.cloudflare.com/client/v4/zones/2ba5972166bcdf34935728843955554e/dns_records" http-header-field="Authorization: Bearer WYlmyM9-9xOSBUDue6_sCErhtvHsqv20nhwXylX7" http-method=get output=user

Once ran on the MikroTIk it will provide the following output:

Locate the info after “id”: for the relevant record which will be our Record ID. Copy this with the rest

Record ID:

79e287776ea742f6df0d16cd5073f6cc

Scripts

New we can populate our script. There will be a single script however it’s been broken up below to explain each section

Public IP Check

This part will first download the public IP address by using the fetch command and save it in a txt file named newIP.txt

Then it will check to see if there is an existing file for the current IP. This should only be required the first time the script us run but if the file is removed for whatever reason it will prevent the script from failing to run. If no file is found it will create a new one with the fetch command as was used to get the up-to-date IP and name it currentIP.txt

The last stage is to populate the 2 variables ($newIP & $currentIP) from the txt file contents then compare the 2. If the new one is different to the old one it will log that the IP has changed and update the currentIP.txt for the new IP address.

#Public IP Check
/tool fetch url="http://myip.dnsomatic.com/" mode=http dst-path=newIP.txt

#Check CurrentIP.txt exists
:if ([:len [/file find name=currentIP.txt]] = 0) do={
/tool fetch url="http://myip.dnsomatic.com/" mode=http dst-path=currentIP.txt
}

#Compare New and Existing IP addresses
:local currentIP [file get currentIP.txt contents];
:local newIP [file get newIP.txt contents];

#If different run update script
:if ($newIP != $currentIP) do={

#Log and Save new IP
:log info message="New Pubilc IP: $newIP"
/file set currentIP.txt contents=$newIP

Cloud Flare update

# Define variables
:local apiToken "***<Your API Token>***"
:local zoneID "***<Your Zone ID***"
:local recordID "***<Your Record ID>***"
:local hostname "***<Your DNS record>***"
:local ipAddress "$newIP"


# Validate variables
:if (($apiToken = "") || ($zoneID = "") || ($recordID = "") || ($hostname = "") || ($ipAddress = "")) do={
    :log error "One or more variables are not set. Please configure the API token, Zone ID, Record ID, Hostname, and IP address."
    :error "Script terminated due to missing variables."
}

# Set the API endpoint
:local url ("https://api.cloudflare.com/client/v4/zones/" . $zoneID . "/dns_records/" . $recordID)

:log info $url


# Prepare JSON payload
:local json "{\
\"type\": \"A\", \
\"name\": \"$hostname\", \
\"content\": \"$ipAddress\", \
\"ttl\": 3600, \
\"proxied\": false\
}"

# Send the request
/tool fetch url=$url http-method=put http-header-field="Authorization: Bearer $apiToken,Content-Type: application/json" http-data="$json" output=user

Complete Script

#Public IP Check
/tool fetch url="http://myip.dnsomatic.com/" mode=http dst-path=newIP.txt

#Check CurrentIP.txt exists
:if ([:len [/file find name=currentIP.txt]] = 0) do={
/tool fetch url="http://myip.dnsomatic.com/" mode=http dst-path=currentIP.txt
}

#Compare New and Existing IP addresses
:local currentIP [file get currentIP.txt contents];
:local newIP [file get newIP.txt contents];

#If different run update script
:if ($newIP != $currentIP) do={

#Log and Save new IP
:log info message="New Pubilc IP: $newIP"
/file set currentIP.txt contents=$newIP

# Define variables
:local apiToken "5pXqw0U0ZL6GkahuDaBSwVbSc9tLRZYrUEQMRXiq"
:local zoneID "2ba5972166bcdf34935728843955554e"
:local recordID "79e287776ea742f6df0d16cd5073f6cc"
:local hostname "chr.mikrotikmaster.app"
:local ipAddress "$newIP"


# Validate variables
:if (($apiToken = "") || ($zoneID = "") || ($recordID = "") || ($hostname = "") || ($ipAddress = "")) do={
    :log error "One or more variables are not set. Please configure the API token, Zone ID, Record ID, Hostname, and IP address."
    :error "Script terminated due to missing variables."
}

# Set the API endpoint
:local url ("https://api.cloudflare.com/client/v4/zones/" . $zoneID . "/dns_records/" . $recordID)

:log info $url


# Prepare JSON payload
:local json"{\
\"type\": \"A\", \
\"name\": \"$hostname\", \
\"content\": \"$ipAddress\", \
\"ttl\": 3600, \
\"proxied\": false\
}"

# Send the request
/tool fetch url=$url http-method=put http-header-field="Authorization: Bearer $apiToken,Content-Type: application/json" http-data="$payload" output=user

}

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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