Small python script for request & update DNS Record hosting by Cloudflare via Cloudflare API.
- Crontab Using Crontab for job scheduling.
#MIM HOUR DAY MONTH WEEK
*/30 * * * * root python /script_path/script_ddns4.py
- Schedule
Alternatively, automatically execute via
schedule
module, scheduling examples as following.
import schedule
import sys
def SomethingAsPackage():
# Please packing script as script
# Execute setting
schedule.every(30).minutes.do(SomethingAsPackage)
# Loop
try:
while True:
schedule.run_pending()
time.sleep(1)
# Manuel exit
except KeyboardInterrupt:
sys.exit()
- For safety reason, please using API Token instead of legacy API Keys.
For using module and script, you may need a domain registered with Cloudflare, or choice Cloudflare as DNS hosting service.
Then, logged into Cloudflare Dashboard
, select the domain you hosting, find the Get your API token
banner, click API Tokens options.
Modify the token’s permissions. only allowing DNS record edit, then generate API Token. The token secret is only shown once, make sure to copy the secret to a secure place.
Cloudflare API Token, Zone ID, DNS records ID will storage at configuration file as JSON format, the standard configuration file structure as follows:
{
"Telegram_BOTs":{
"TelegramToken": "",
"TelegramChatID": ""
},
"CloudflareAPI":{
"AuthToken": "",
"AuthMail": ""
},
"Zone":{
"ZoneID": ""
},
"RecordsID":{
"DNSRecordIPv4ID": "",
"DNSRecordIPv4Domain": "",
"DNSRecordIPv4ProxyAble": true,
"DNSRecordIPv4ProxyMode": true,
"DNSRecordIPv6ID": "",
"DNSRecordIPv6Domain": "",
"DNSRecordIPv6ProxyAble": true,
"DNSRecordIPv6ProxyMode": true
},
"IPAddressUpdateRecord": {
"DNSRecordIPv4": "",
"DNSRecordIPv4UpdateTime": "",
"DNSRecordIPv6": "",
"DNSRecordIPv6UpdateTime": ""
},
"CNAME": {
"DNSRecordCNAMEID": "",
"NAME": "",
"TARGET": "",
"DNSRecordCNAMEUpdateTime": ""
}
}
For using configuration file, please modify the file path inside script.
ConfigPath = "/file_path/cloudflare_dynamic_dns.config.json"
Error message store at cloudflare_dynamic_dns.log
.
Using Telegram Bot, contect BotFather to create new Bot accounts.
Telegram BOTs Token
and Telegram Chat ID
are needed. if the chat channel wasn't created, Telegram API will return HTTP 400 Bad Request
, You need to start the chat channel, including that bot.
# Import as module
import cloudflare_dynamic_dns
# Import the function independently
from cloudflare_dynamic_dns import UpdateSpecifyDNSRecordCANME
Please reference to the demo script script_verify.py
.
from cloudflare_dynamic_dns import Verify
# Check authorize status
def VerifyCheck(ConfigPath, FullyRespon):
CheckResult = Verify(ConfigPath,FullyRespon)
# Error
if type(CheckResult) is bool:
return ("Error occurred during connect to Cloudflare API, please check the error log.")
# Get HTTP status code
elif type(CheckResult) is int:
return (f"Unable connect to Cloudflare API, HTTP Status Code: {CheckResult}.")
# Output fully Cloudflare API Respon
elif type(CheckResult) is dict:
return (f"Cloudflare API Response:\r\n.{CheckResult}")
# Print authorize status only
elif type(CheckResult) is str:
return (f"The token authorize status is: {CheckResult}.")
# Runtime
try:
ConfigPath = "/file_path/cloudflare_dynamic_dns.config.json"
# If enable FullyRespon, script will print out fully Cloudflare API respon as dictionary
FullyRespon = None
CheckResult = VerifyCheck(ConfigPath,FullyRespon)
print(CheckResult)
Please reference to the demo script script_request_fully.py
. Default will output as Python Dictionary, define OutputJSONFile
to output JSON file.
from cloudflare_dynamic_dns import RequestFullyDNSRecord
# Download DNS record
def Download_DNS_Record(ConfigPath, OutputJSONFile):
ResultDict = RequestFullyDNSRecord(ConfigPath, OutputJSONFile)
# Error
if type(ResultDict) is bool:
return ("Error occurred during connect to Cloudflare API, please check the error log.")
# Get HTTP status code
elif type(ResultDict) is int:
return (f"Unable connect to Cloudflare API, HTTP Status Code: {ResultDict}.")
# Output fully Cloudflare API Respon
elif type(ResultDict) is dict:
return (f"Cloudflare API Response:\r\n.{ResultDict}")
# Print authorize status only
elif type(ResultDict) is list:
JSONFilePath = ResultDict[1]
return (f"Cloudflare API Response Storage at: {JSONFilePath}")
# Runtime
try:
# Configuration file path
ConfigPath = "/file_path/cloudflare_dynamic_dns.config.json"
# Output all DNS record as JSON file or not, Disable will print out as dictionary
OutputJSONFile = None
AskRecordResult = Download_DNS_Record(ConfigPath,OutputJSONFile)
print(AskRecordResult)
except Exception as ErrorStatus:
print(f"Error occurred,\r\n{ErrorStatus}")
import cloudflare_dynamic_dns
# Configuration file path
ConfigPath = "/file_path/cloudflare_dynamic_dns.config.json"
# Asking Cloudflare API
RecordIPv4 = cloudflare_dynamic_dns.RequestSpecifyDNSRecordIPv4(ConfigPath, FullyRespon=None)
# Print result
print(RecordIPv4)
Basic respon specify RecordsID
reference to configuration. If you wish to request multiple or specify DNS A record manually, please define MultiRecord
.
import cloudflare_dynamic_dns
# Configuration file path
ConfigPath = "/file_path/cloudflare_dynamic_dns.config.json"
# Asking Cloudflare API
RecordIPv6 = cloudflare_dynamic_dns.RequestSpecifyDNSRecordIPv6(ConfigPath, FullyRespon=None)
# Print result
print(RecordIPv6)
Basic respon specify RecordsID
reference to configuration. If you wish to request multiple or specify DNS AAAA record manually, please define MultiRecord
.
Please reference to the DDNS demo script script_ddns4.py
.
import cloudflare_dynamic_dns
# Update DNS A record
UpdateStatus = cloudflare_dynamic_dns.UpdateSpecifyDNSRecordIPv4(ConfigPath, UpdateDNSRecordIPv4=CurrentIPv4)
# Get Cloudflare API respon
if type(UpdateStatus) is dict:
# Return success or not
Success02Not = UpdateStatus["success"]
print(f"Cloudflare API Responses: {Success02Not}.")
# Get HTTP status code
elif type(UpdateStatus) is int:
print(f"Unable connect to Cloudflare API, HTTP Status Code: {UpdateStatus}.")
# Error
elif type(UpdateStatus) is bool:
print("Error occurred during connect to Cloudflare API, please check the error log.")
Basis update using Python String, please define IP address UpdateDNSRecordIPv4
. If you wish to update multiple or specify DNS AAAA record, please define MultiRecord
which including RecordsID
, Domain Name
, Proxy Ability
and Proxy Mode
, packing as Python List.
# Array
UpdateArray = ["RecordsID", "Domain Name", True, True]
# Update record
cloudflare_dynamic_dns.UpdateSpecifyDNSRecordIPv4(ConfigPath, MultiRecord=UpdateArray, UpdateDNSRecordIPv4=CurrentIPv4)
Alternatively, expansion to loops for update multiple A record, in case of hostng multiple domain name at same IP address.
# Array
Arraies = [
["RecordsID_1", "Domain Name_1", True, True],
["RecordsID_2", "Domain Name_2", True, True],
["RecordsID_3", "Domain Name_3", True, True],
["RecordsID_4", "Domain Name_4", True, True],
["RecordsID_5", "Domain Name_5", True, True]
]
# Update record
for Array in Arraies:
cloudflare_dynamic_dns.UpdateSpecifyDNSRecordIPv4(ConfigPath, MultiRecord=UpdateArray, UpdateDNSRecordIPv4=CurrentIPv4)
Please reference to the DDNS demo script script_ddns6.py
.
import cloudflare_dynamic_dns
# Update DNS AAAA record
UpdateStatus = cloudflare_dynamic_dns.UpdateSpecifyDNSRecordIPv6(ConfigPath, UpdateDNSRecordIPv6=CurrentIPv6)
# Get Cloudflare API respon
if type(UpdateStatus) is dict:
# Return success or not
Success02Not = UpdateStatus["success"]
print(f"Cloudflare API Responses: {Success02Not}.")
# Get HTTP status code
elif type(UpdateStatus) is int:
print(f"Unable connect to Cloudflare API, HTTP Status Code: {UpdateStatus}.")
# Error
elif type(UpdateStatus) is bool:
print("Error occurred during connect to Cloudflare API, please check the error log.")
Basis update using Python String, please define IP address UpdateDNSRecordIPv6
. If you wish to update multiple or specify DNS AAAA record, please define MultiRecord
which including RecordsID
, Domain Name
, Proxy Ability
and Proxy Mode
, packing as Python List.
# Array
UpdateArray = ["RecordsID", "Domain Name", True, True]
# Update record
cloudflare_dynamic_dns.UpdateSpecifyDNSRecordIPv6(ConfigPath, MultiRecord=UpdateArray, UpdateDNSRecordIPv4=CurrentIPv6)
Alternatively, expansion to loops for update multiple A record, in case of hostng multiple domain name at same IP address.
# Array
Arraies = [
["RecordsID_1", "Domain Name_1", True, True],
["RecordsID_2", "Domain Name_2", True, True],
["RecordsID_3", "Domain Name_3", True, True],
["RecordsID_4", "Domain Name_4", True, True],
["RecordsID_5", "Domain Name_5", True, True]
]
# Update record
for Array in Arraies:
cloudflare_dynamic_dns.UpdateSpecifyDNSRecordIPv6(ConfigPath, MultiRecord=UpdateArray, UpdateDNSRecordIPv4=CurrentIPv6)
Please reference to the DDNS demo script script_update_canme.py
.
from cloudflare_dynamic_dns import UpdateSpecifyDNSRecordCANME
# Update CNAME record
def Download_DNS_Record(ConfigPath, UpdateDNSRecordCNAME):
# Check CNAME input
if type(UpdateDNSRecordCNAME) is list:
ResultDict = UpdateSpecifyDNSRecordCANME(ConfigPath, UpdateDNSRecordCNAME)
# Error
if type(ResultDict) is bool:
return ("Error occurred during connect to Cloudflare API, please check the error log.")
# Get HTTP status code
elif type(ResultDict) is int:
return (f"Unable connect to Cloudflare API, HTTP Status Code: {ResultDict}.")
# Output fully Cloudflare API Respon
elif type(ResultDict) is dict:
return ResultDict
# Print authorize status only
else:
return (f"Unable running CNAME update. Please check input configuration.")
# Runtime
try:
# Configuration file path
ConfigPath = "/file_path/cloudflare_dynamic_dns.config.json"
# CNAME update with list input
UpdateDNSRecordCNAME = ["name.cloudflare.dns","target.cloudflare.dns"]
CNAMEUpdateResult = Download_DNS_Record(ConfigPath, UpdateDNSRecordCNAME)
if type(CNAMEUpdateResult) is dict:
SuccessOrNot = CNAMEUpdateResult["success"]
print(f"Cloudflare API Responses: {SuccessOrNot}.")
else:
print(CNAMEUpdateResult)
except Exception as ErrorStatus:
print(f"Error occurred,\r\n{ErrorStatus}")
Basis update using Python List, please define CNAME NAME
and VALUE
inside UpdateDNSRecordCNAME
. If you wish to update multiple or specify CNAME record, please define UpdateDNSRecordCNAME
including RecordsID
.
# Specify CNAME
UpdateDNSRecordCNAME = ["Cloudflare_DNS_Records_ID", "name.cloudflare.dns", "target.cloudflare.dns"]
- Python 3.7.3 or above
- Testing on the above Python version: 3.9.6 / 3.12.2
- logging
- datetime
- json
- requests
General Public License -3.0