Skip to content

Instantly share code, notes, and snippets.

@StalkingKillah
Created January 7, 2015 16:14
Show Gist options
  • Save StalkingKillah/acafdb3a98b644df4008 to your computer and use it in GitHub Desktop.
Save StalkingKillah/acafdb3a98b644df4008 to your computer and use it in GitHub Desktop.
DynFlare - CloudFlare as dynamic dns service
#!/usr/bin/env python
# encoding: utf-8
"""
dynflare
Created by Djordje Stojanovic <djordje.stojanovic@shadow-inc.net>
"""
import sys
import socket
import logging
try:
import json
except ImportError:
import simplejson as json
try:
import requests
except ImportError:
logging.error('`requests` library required. Install with `sudo pip install requests`')
sys.exit(1)
try:
import dns.resolver as resolver
except ImportError:
logging.error('`dnspython` library required. Install with `sudo pip install dnspython`')
sys.exit(1)
class CloudFlare(object):
def __init__(self, email, token):
self.url = 'https://www.cloudflare.com/api_json.html'
self.email = email
self.token = token
def _request(self, payload):
r = requests.get(self.url, params=payload)
if r.status_code == 200:
return r.json()
else:
logging.error('Unable to make request to CloudFlare!')
return None
def _create_payload(self, action, data=None):
payload = {
'a': action,
'tkn': self.token,
'email': self.email
}
return ((data is not None and type(data) is dict) and dict(payload, **data)) or payload
def get_records(self, domain):
data = { 'z': domain }
payload = self._create_payload('rec_load_all', data)
return self._request(payload)
def get_record(self, domain, name):
records = self.get_records(domain)['response']['recs']
fqdn = "{}.{}".format(name, domain)
record = filter(lambda record: record['name'] == fqdn, records['objs'])
if len(record) > 0:
return record[0]
else:
logging.warning('Record for %s not found.', fqdn)
return None
def create_record(self, domain, name, content, record_type='A', ttl=1):
record_types = ['A', 'CNAME', 'MX', 'TXT', 'SPF', 'AAAA', 'NS', 'SRV', 'LOC']
if record_type.upper() in record_types:
data = {
'z': domain,
'type': record_type.upper(),
'name': name,
'content': content,
'ttl': ttl
}
payload = self._create_payload('rec_new', data)
return self._request(payload)
else:
logging.error('Record type is not in %s', '/'.join(record_types))
return None
def edit_record(self, domain, name, content, record_type='', ttl=None):
record = self.get_record(domain, name)
if record is not None:
filter_non_empty = lambda dictionary: dict([ (i, dictionary[i]) for i in dictionary if dictionary[i] is not None or dictionary[i] is not ''])
data = {
'z': domain,
'type': record_type,
'id': record['rec_id'],
'content': content,
'ttl': ttl
}
data = filter_non_empty(data)
payload = self._create_payload('rec_edit', data)
return self._request(payload)
else:
return None
def delete_record(self, domain, name):
record = self.get_record(domain, name)
if record is not None:
data = {
'z': domain,
'id': record['rec_id']
}
payload = self._create_payload('rec_delete', data)
return self._request(payload)
else:
return None
def get_public_ip():
r = resolver.Resolver()
r.nameservers = [socket.gethostbyname('resolver1.opendns.com')]
return r.query('myip.opendns.com', 'A')[0].address
def main():
hostname = socket.gethostname()
ip = get_public_ip()
cf = CloudFlare("YOUR_EMAIL", "YOUR_CF_TOKEN")
domain = 'YOUR_DOMAIN'
record = cf.get_record(domain, hostname)
r = None
if record is not None:
if 'name' in record:
logging.info('Updating record for %s.%s', hostname, domain)
r = cf.edit_record(domain, hostname, ip)
else:
logging.info('Creating record for %s.%s', hostname, domain)
r = cf.create_record(domain, hostname, ip)
if r is None:
logging.error('Errored out while editing CloudFlare DNS Record')
print r
sys.exit(1)
logging.info('%s.%s -> %s', hostname, domain, ip)
logging.info('Update sucessfull')
# print hostname+'.'+domain+' -> '+ip
# print 'Update sucessfull'
sys.exit(0)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment