Skip to content

Instantly share code, notes, and snippets.

@solicomo
Created January 14, 2019 04:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save solicomo/343d37348647bbefe3d498772b821c16 to your computer and use it in GitHub Desktop.
Save solicomo/343d37348647bbefe3d498772b821c16 to your computer and use it in GitHub Desktop.
CloudFlare Dynamic DNS
#!/usr/bin/env python3
#-*- coding: utf-8 -*-
import sys
import requests
import json
from datetime import datetime
EMAIL='Your Email'
APIKEY='Your API Key from CloudFlare'
ZONEID='ZONE ID which can be found at left of Overview page'
DOMAINS=['domain.org', '*.domain.org', 'www.domain.org']
def log(msg):
print('[{}] {}'.format(datetime.now().isoformat(' '), msg))
pass
def request(method, url, data = None):
headers = {
'X-Auth-Email': EMAIL,
'X-Auth-Key': APIKEY,
'Content-Type': 'application/json',
}
rsp = None
try:
if method == 'get':
rsp = requests.get(url, headers=headers)
elif method == 'post':
rsp = requests.post(url, headers=headers, data=data)
elif method == 'put':
rsp = requests.put(url, headers=headers, data=data)
else:
return None
rsp.raise_for_status()
except requests.exceptions.RequestException as e:
log('Request Failed: {}:\n{} {}\n{}'.format(e, method, data, rsp.text))
return None
data = rsp.json()
if not data['success']:
log('List DNS Records Failed: {}'.format(json.dumps(data, indent=4)))
return None
return data
def getMyIP():
try:
rsp = requests.get('https://ifconfig.me/all.json')
rsp.raise_for_status()
return 'A', rsp.json()['ip_addr']
except requests.exceptions.RequestException as e:
log('Request Failed: {}'.format(e.message))
return None, None
def getRecordIDs():
rsp = request('get', 'https://api.cloudflare.com/client/v4/zones/{}/dns_records'.format(ZONEID))
if rsp is None:
return False
rids = {}
for record in rsp['result']:
rids[record['name']] = {
'id': record['id'],
'ip': record['content'],
}
return rids
def create(domain, ipType, ip):
data = {
'name': domain,
'type': ipType,
'content': ip,
}
rsp = request('post', 'https://api.cloudflare.com/client/v4/zones/{}/dns_records'.format(ZONEID), json.dumps(data))
if rsp is None:
return False
result = rsp['result']
log('Created record {}: {} - {} - {}'.format(result['id'], result['type'], result['name'], result['content']))
return True
def update(rid, domain, ipType, ip):
data = {
'name': domain,
'type': ipType,
'content': ip,
}
rsp = request('put', 'https://api.cloudflare.com/client/v4/zones/{}/dns_records/{}'.format(ZONEID, rid), json.dumps(data))
if rsp is None:
return False
result = rsp['result']
log('Updated record {}: {} - {} - {}'.format(result['id'], result['type'], result['name'], result['content']))
return True
def createOrUpdate():
ipType, ip = getMyIP()
if ip is None:
return False
rids = getRecordIDs()
for domain in DOMAINS:
if domain in rids:
if ip == rids[domain]['ip']:
log('Omitted record {}: {} - {}'.format(rids[domain]['id'], domain, ip))
else:
update(rids[domain]['id'], domain, ipType, ip)
else:
create(domain, ipType, ip)
return True
def main(argv):
createOrUpdate()
if __name__ == '__main__':
try:
main(sys.argv)
except KeyboardInterrupt:
log ("Crtl+C Pressed. Shutting down.")
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment