Last active
February 27, 2018 14:16
-
-
Save itay-grudev/754544a9a75eea4ef2fbdf38cfc34f18 to your computer and use it in GitHub Desktop.
Bash Script for free reliable Dynamic DNS (DynDNS) using the Digital Ocean API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
## | |
# This script check whether the server's public IP has changed and updates an | |
# A DNS record with the Digital Ocean API. | |
# /etc/dodyndns configuration file: | |
# SERVER_IP=127.0.0.1 | |
# RECORD_ID= | |
# | |
# DYNDNS_DOMAIN_PREFIX=dyndns | |
# DIGITAL_OCEAN_DOMAIN=example.com | |
# DIGITAL_OCEAN_API_TOKEN=asdfghjkl1234567890 | |
# DNS_TTL=60 | |
# ADMIN_EMAIL="[email protected]" | |
# ADMIN_NAME="John Doe" | |
# | |
# Copyright: Itay Grudev (c) 2018 | |
# License: MIT | |
# | |
source /etc/dodyndns | |
# Acquire the computer's public address | |
IP_DIG=$(dig +short myip.opendns.com @resolver1.opendns.com 2>/dev/null) | |
if [[ $IP_DIG =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
IP=$IP_DIG | |
else | |
IP_CURL=$(curl -s https://checkip.amazonaws.com 2>/dev/null) | |
if [[ $IP_CURL =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
IP=$IP_CURL | |
fi | |
fi | |
# If the script is unable to retrieve the server's external ip address it | |
# should simply exit silently assuming this is normal downtime | |
if [ -z "${IP// }" ]; then | |
exit 0 | |
fi | |
# If the reported IP addresses has changed to the one on record | |
if [ "$SERVER_IP" != "$IP" ]; then | |
function inform_admin_of_error() { | |
/usr/sbin/sendmail $ADMIN_EMAIL <<-EOF | |
From: Server: $(hostname) <$LOGNAME@$(hostname)> | |
To: $ADMIN_NAME <$ADMIN_EMAIL> | |
Content-Type: text/plain; charset=UTF-8 | |
X-Priority: 1 (Highest) | |
X-MSMail-Priority: High | |
Importance: High | |
Subject: Urgent! Unable to update the server's A record. | |
Dear $ADMIN_NAME, | |
The public IP address of $(hostname) has changed from "$SERVER_IP" to "$IP". | |
But due to a problem with the Digital Ocean API updating the A record of the server was not successful. | |
Services are most likely unavailable and urgent changes to the DNS A records are probably required. | |
Kind Regards, | |
$LOGNAME@$(hostname) via crontab | |
EOF | |
} | |
# Verify the authenticity of the new IP address by comparing SSH fingerprints | |
TMP_KNOWN_HOSTS=$(mktemp) | |
ssh-keyscan 127.0.0.1 > $TMP_KNOWN_HOSTS | |
sed -i "s/127\.0\.0\.1/$IP/" $TMP_KNOWN_HOSTS | |
RESPONSE=$(ssh -n -o "UserKnownHostsFile $TMP_KNOWN_HOSTS" -o "StrictHostKeyChecking yes" $IP true 2>&1) | |
rm TMP_KNOWN_HOSTS | |
if ! [[ $RESPONSE = *"Host key verification failed."* ]]; then | |
# If everything checks out and there is no MITM update the Digital Ocean DNS | |
# record. Though we first need to delete the old record. | |
if [ ! -z "$RECORD_ID" ] && [ "$RECORD_ID" != " " ] && [ "$RECORD_ID" != "null" ]; then | |
curl -s -X DELETE \ | |
-H "Content-Type: application/json" \ | |
-H "Authorization: Bearer ${DIGITAL_OCEAN_API_TOKEN}" \ | |
"https://api.digitalocean.com/v2/domains/${DIGITAL_OCEAN_DOMAIN}/records/${RECORD_ID}" 2>&1 >/dev/null | |
fi | |
NEW_RECORD_ID="$(curl -s -X POST \ | |
-H "Content-Type: application/json" \ | |
-H "Authorization: Bearer ${DIGITAL_OCEAN_API_TOKEN}" \ | |
-d " | |
{ | |
\"type\": \"A\", | |
\"name\": \"$DYNDNS_DOMAIN_PREFIX\", | |
\"data\": \"$IP\", | |
\"ttl\": $DNS_TTL | |
}" \ | |
"https://api.digitalocean.com/v2/domains/${DIGITAL_OCEAN_DOMAIN}/records" | \ | |
jq '.domain_record.id')" | |
# Verify the record id is valid | |
NUMERICAL_REGEX='^[0-9]+$' | |
if ! [[ $NEW_RECORD_ID =~ $NUMERICAL_REGEX ]]; then | |
inform_admin_of_error | |
exit 1 | |
fi | |
# Verify the new domain name was saved | |
SAVED_RECORD_ID="$(curl -s -X GET \ | |
-H "Content-Type: application/json" \ | |
-H "Authorization: Bearer ${DIGITAL_OCEAN_API_TOKEN}" \ | |
"https://api.digitalocean.com/v2/domains/${DIGITAL_OCEAN_DOMAIN}/records/${NEW_RECORD_ID}" | \ | |
jq '.domain_record.id')" | |
# Verify the record id is numeric | |
if [[ "$NEW_RECORD_ID" == "$SAVED_RECORD_ID" ]]; then | |
# Update the configuration settings | |
sed -i "s/SERVER_IP=.\+/SERVER_IP=$IP/" /etc/dodyndns | |
sed -i "s/RECORD_ID=.\+/RECORD_ID=$NEW_RECORD_ID/" /etc/dodyndns | |
else | |
inform_admin_of_error | |
exit 1 | |
fi | |
fi | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment