Skip to content

Instantly share code, notes, and snippets.

@mhjwork
Last active June 24, 2017 16:36
Show Gist options
  • Save mhjwork/5b3b3df30abc52f26bfa to your computer and use it in GitHub Desktop.
Save mhjwork/5b3b3df30abc52f26bfa to your computer and use it in GitHub Desktop.
Dynamic DNS using AWS
#!/usr/bin/python
# Run this script as a cron job on a machine inside your network that is always on
# Prerequisites:
# - Python
# - boto3 module for AWS access
# - Route 53 DNS hosted zone that you use as the target
# - SNS topic to send notifications when the DNS is updated (IP changed)
#
# Assumes that you have the AWS configuration directory available (~/.aws/)
# with a default profile that has API access Route 53 and SNS access
import boto3 # Boto3 library for AWS access
import requests # Library for making HTTP requests
import socket # LIbrary for DNS resolution
HOSTZONE = 'AWS_DNS_HOSTED_ZONE_ID' # AWS hosted zone ID
subject = "" # SNS subject variable
message = "" # SNS message body variable
bastion_dns = 'bastion.example.com.' # DNS hostname to be updated
sns_topic_arn = arn:aws:sns:<region>:<accoundid>:<SNS_Topic_Name> # The ARN of the SNS topic for notifications
# Create a custom Boto3 session using the default profile
boto3.setup_default_session(profile_name='default')
# Retrieve the current IP address of the bastion DNS hostname
current_bastion_ip = socket.gethostbyname(bastion_dns)
# Get the current IP address of the local host (using AWS checkip address)
current_local_ip = requests.get('http://checkip.amazonaws.com').text.rstrip()
# Route 53 Update Record Set request, with the appropriate IP address and DNS
batch = {
'Comment': 'Changed by update-dns.py',
'Changes': [ {
'Action': 'UPSERT',
'ResourceRecordSet': {
'Name': bastion_dns, 'Type': 'A', 'TTL': 60, 'ResourceRecords': [ { 'Value': current_local_ip }, ]
}
} ]
}
# If the IP returned by the DNS check is different from the current IP address
if current_bastion_ip != current_local_ip:
# Create a route53 client session
client = boto3.client('route53')
# Request an update to the DNS using the batch dict defined earlier
resp = client.change_resource_record_sets(HostedZoneId=HOSTZONE,ChangeBatch=batch)
# Get the status of the request
status = resp['ChangeInfo']['Status']
# Set the SNS subject name and message
subject = "DNS for " + bastion_dns + " changed"
message = "DNS (" + bastion_dns + ") changed from " + current_bastion_ip + " to " + current_local_ip + "\n"
message = message + "Status: " + status + "\n"
# Create an SNS resource and Topic object
sns = boto3.resource('sns')
topic = sns.Topic(sns_topic_arn)
# Send the message to the topic
snsresp = topic.publish(Subject=subject,Message=message)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment