Skip to content

Instantly share code, notes, and snippets.

@seanlinmt
Created November 22, 2017 13:16
Show Gist options
  • Save seanlinmt/526d4fb8f02a35515c55f249b3fdf087 to your computer and use it in GitHub Desktop.
Save seanlinmt/526d4fb8f02a35515c55f249b3fdf087 to your computer and use it in GitHub Desktop.
cloudflare_dynamic_ip_updater.sh
#!/usr/bin/env python
import json
import requests
import logging
import logging.handlers
import string
import sys
import ipaddress
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address='/dev/log')
formatter = logging.Formatter('%(module)s: %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
base_url = 'https://api.cloudflare.com/client/v4/'
api_email = 'API_EMAIL'
api_key = 'API_KEY'
zone_name = 'DOMAIN_NAME'
headers = {
"X-Auth-Email": api_email,
"X-Auth-Key": api_key,
"Content-Type": "application/json"
}
# get zone id
params = {
"name": zone_name,
"match": "all"
}
r = requests.get(base_url + 'zones', params=params, headers=headers)
json_result = json.loads(r.text)
if r.raise_for_status():
logger.critical(requests.exceptions.HTTPError)
sys.exit(1)
if not json_result["success"]:
logger.critical(string.join(json_result["errors"], ","))
sys.exit(1)
if len(json_result["result"]) > 1:
logger.critical("More than one zone returned")
sys.exit(1)
zone_id = json_result["result"][0]["id"]
# get A record and current IP address
params = {
"type": "A",
"match": "all"
}
r = requests.get(base_url + 'zones/' + zone_id + '/dns_records', params=params
, headers=headers)
json_result = json.loads(r.text)
if r.raise_for_status():
logger.critical(requests.exceptions.HTTPError)
sys.exit(1)
if not json_result["success"]:
logger.critical(string.join(json_result["errors"], ","))
sys.exit(1)
if len(json_result["result"]) > 1:
logger.critical("More than one A record returned")
sys.exit(1)
if json_result["result"][0]["name"] != zone_name:
logger.critical("Record name should be the same as the zone name")
sys.exit(1)
record_id = json_result["result"][0]["id"]
current_ip = json_result["result"][0]["content"]
# get external ip
r = requests.get("http://ipinfo.io/json", timeout=60)
if r.raise_for_status():
logger.critical(requests.exceptions.HTTPError)
sys.exit(1)
json_result = json.loads(r.text)
try:
external_ip = ipaddress.ip_address(json_result["ip"])
except Exception, ex:
logger.critical(ex.message)
sys.exit(1)
if external_ip.version != 4 or not external_ip.exploded:
logger.error("Not global IPv4 address")
sys.exit(1)
if current_ip == external_ip.exploded:
logger.info("No IP change")
sys.exit(0)
# do update
content = {
"id": record_id,
"type": "A",
"name": zone_name,
"content": external_ip.exploded,
"ttl": 300
}
r = requests.put(base_url + 'zones/' + zone_id + '/dns_records/' + record_id,
headers=headers, data=json.dumps(content))
if r.raise_for_status():
logger.critical(requests.exceptions.HTTPError)
sys.exit(1)
logger.info("Public IP " + external_ip.exploded + " published")
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment