Skip to content

Instantly share code, notes, and snippets.

@StalkingKillah
Last active April 18, 2020 02:08
Show Gist options
  • Save StalkingKillah/3fb3df63c5eb145c304a0f1bcbd6beab to your computer and use it in GitHub Desktop.
Save StalkingKillah/3fb3df63c5eb145c304a0f1bcbd6beab to your computer and use it in GitHub Desktop.
Mikrotik dynamic DNS using CloudFlare API v4
## Meta
# Script by Djordje Stojanovic (djordje.stojanovic<at>shadow-inc.net)
# Updated: 2020-04-18
## Script Permissions
# Read
# Write
# Test
# Sniff
# Sensitive
## Variables
:local wanInterface "ether1-gateway"
:local externalHostname ""
:local preferedDns "1.1.1.1"
# Safe value is 30s
:local waitForDns "30s"
:local dryRun "false"
# https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
# HTTP Header `X-Auth-Email`
:local apiEmail ""
# HTTP Header `X-Auth-Key`
:local apiKey ""
# API Parameter `zone_identifier`
:local apiZoneId ""
# API Parameter `identifier` (record identifier)
:local apiRecordId ""
# API Parameter `name`
:local apiRecordName $externalHostname
:local wanAddress [/ip address get [/ip address find interface=$wanInterface] address]
:local wanIp [:pick $wanAddress 0 [:find $wanAddress "/"]]
:local resolvedIp [:resolve $externalHostname server=$preferedDns]
# API Parameter `type`
:local apiRecordType "A"
# API Parameter `content`
:local apiRecordContent "$wanIp"
# API Parameter `ttl` (1 - Automatic)
:local apiRecordTtl "1"
# API Parameter `proxied` (true/false)
:local apiRecordProxied "false"
:local apiMethod "put"
:local apiUrl "https://api.cloudflare.com/client/v4/zones/$apiZoneId/dns_records/$apiRecordId"
:local apiHeaders "X-Auth-Email:$apiEmail,X-Auth-Key:$apiKey,content-type:application/json"
:local apiData "{\"type\":\"$apiRecordType\",\"name\":\"$apiRecordName\",\"content\":\"$apiRecordContent\",\"ttl\":$apiRecordTtl,\"proxied\":$apiRecordProxied}"
:log info "[CloudFlare] Running..."
:if ($dryRun = "true") do={
:log debug "[CloudFlare] Mode: Dry Run"
}
:log debug "[CloudFlare] Local IP ($wanInterface): $wanIp"
:log debug "[CloudFlare] Resolved IP ($externalHostname): $resolvedIp"
:log debug "[CloudFlare] API URL: $apiUrl"
:log debug "[CloudFlare] API Headers: $apiHeaders"
:log debug "[CloudFlare] API Data: $apiData"
:if ($resolvedIp != $wanIp) do={
:log debug "[CloudFlare] $externalHostname ($resolvedIp) does not point to $wanIp"
:if ($dryRun = "false") do={
:log debug "[CloudFlare] Updating..."
:local result [/tool fetch mode=https http-method="$apiMethod" url="$apiUrl" http-header-field="$apiHeaders" http-data="$apiData" output=user as-value]
:if ([:len $result] > 0) do={
:if (($result->"data")~"\"success\":true") do={
:log debug "[CloudFlare] Update Successful!"
:log debug "[CloudFlare] Flushing DNS Cache..."
/ip dns cache flush
:log debug "[CloudFlare] Waiting $waitForDns for the DNS ($preferedDns) to pick up the changes..."
:delay $waitForDns
:log debug "[CloudFlare] Checking if `$externalHostname` points to `$wanIp`..."
:set resolvedIp [:resolve $externalHostname server=$preferedDns]
:if ($resolvedIp = $wanIp) do={
:log info "[CloudFlare] Success!"
} else={
:log info "[CloudFlare] Success! (but the DNS does not yet resolve `$externalHostname` to `$wanIp`)"
}
} else={
:log error "[CloudFlare] Update Failed!"
}
} else={
:log error "[CloudFlare] Error! Response has no data. Please check request parameters in debug log."
}
}
} else={
:log info "[CloudFlare] Everything is fine."
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment