Skip to content

Instantly share code, notes, and snippets.

@cl0rm
Last active February 23, 2025 14:33
Show Gist options
  • Save cl0rm/ffed1d052ec6a50aa2eeecc2314d3ff6 to your computer and use it in GitHub Desktop.
Save cl0rm/ffed1d052ec6a50aa2eeecc2314d3ff6 to your computer and use it in GitHub Desktop.
MikroTik RouterOS: Update porkbun.com DNS entries
# Porkbun DDNS script for RouterOS v7
# By cl0rm, 02/2025
#
# I have not used ROS scripts before, so this might not be perfect.
# e.g. in line 37f. it might be better to iterate over entries.
# currently I manually paste lines for ->1-> etc.
# trigger this every time DHCP client gets new IP or PPP WAN interface gets up.
######## Please edit below ########
:local pbDomainName "test.com"
:local pbAPIKey "pkxxx"
:local pbAPISecret "skxxxx"
:local wanIntf "WAN"
###################################
:local wanAddrCidr [/ip address get [find interface=$wanIntf] address]
:local wanAddr [:pick $wanAddrCidr 0 [:find $wanAddrCidr "/"]];
:log info "[Porkbun DDNS] Detected WAN IP: $wanAddr"
# Retrieve current DNS records
:local pbGetURL "https://api-ipv4.porkbun.com/api/json/v3/dns/retrieve/$pbDomainName"
:local pbHeaders "Content-Type: application/json"
:local pbPayload "{\"apikey\":\"$pbAPIKey\",\"secretapikey\":\"$pbAPISecret\"}"
:local pbDNSGet ""
:log info "[Porkbun DDNS] Fetching current DNS records from Porkbun..."
:onerror pbGetInfo in={
:set pbDNSGet ([/tool fetch mode=https http-method=post output=user http-header-field=$pbHeaders http-data=$pbPayload url=$pbGetURL as-value]->"data")
:log info "[Porkbun DDNS] Received response: $pbDNSGet"
} do={:log error "[Porkbun DDNS] Failed to retrieve records from Porkbun"; :error "err015"}
:if ([:len $pbDNSGet] != 0) do={
# Extract record ID, current IP, and TTL from response
:local pbRecordId ([:deserialize from=json value=$pbDNSGet]->"records"->0->"id")
:local pbPrevAddr ([:deserialize from=json value=$pbDNSGet]->"records"->0->"content")
:local pbTTL ([:deserialize from=json value=$pbDNSGet]->"records"->0->"ttl")
:local pbType ([:deserialize from=json value=$pbDNSGet]->"records"->0->"type")
:log info "[Porkbun DDNS] Current DNS IP: $pbPrevAddr, TTL: $pbTTL, Record ID: $pbRecordId"
# Update only if IP has changed
:if ($pbPrevAddr = $wanAddr) do={
:log info "[Porkbun DDNS] Current address is already registered and will not be updated";
} else={
:onerror pbUpdate in={
:local pbUpdateURL "https://api-ipv4.porkbun.com/api/json/v3/dns/edit/$pbDomainName/$pbRecordId"
:local pbUpdateData "{\"apikey\":\"$pbAPIKey\",\"secretapikey\":\"$pbAPISecret\",\"content\":\"$wanAddr\",\"ttl\":$pbTTL,\"type\":\"$pbType\",\"name\":\"$pbDomainName\"}"
:log info "[Porkbun DDNS] Updating DNS record: $pbUpdateData"
:local pbDNSUpdate [/tool fetch mode=https http-method=post output=user http-header-field=$pbHeaders http-data=$pbUpdateData url=$pbUpdateURL as-value]
:log info "[Porkbun DDNS] DNS record updated! [ $pbPrevAddr -> $wanAddr ]"
} do={:log error "[Porkbun DDNS] An error occurred while updating the DNS record"; :error "err014"}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment