Skip to content

Instantly share code, notes, and snippets.

@overplumbum
Last active October 13, 2015 12:37
Show Gist options
  • Save overplumbum/4196574 to your computer and use it in GitHub Desktop.
Save overplumbum/4196574 to your computer and use it in GitHub Desktop.
Update Yandex DNS A record with host IP
curl -sL https://gist.github.com/overplumbum/4196574/raw/install.sh > tmp.sh && sudo sh tmp.sh
#!/bin/bash
set -e
if [ "$USER" != root ]; then
echo "root access required:"
exit 1
fi
while true; do
read -p "What IP address you want to use? (external,internal) " kind
if [ "$kind" = external ]; then
export interface=""
break
elif [ "$kind" = internal ]; then
ifs=$(ifconfig -s | cut -d ' ' -f 1 | grep -vxE 'Iface|lo')
read -p "What interface IP to use: $ifs: " interface
export interface=$interface
echo $ifs | grep -Fw "$interface" >/dev/null && break
fi
echo "invalid value, try again"
done
read -p "Main domain name (e.g. domain.ru, not zzz.domain.ru): " domain
read -p "Sub-domain name (e.g. zzz for zzz.domain.ru): " subdomain
read -p "Yandex DNS Token (please auth & open https://pddimp.yandex.ru/get_token.xml?domain_name=$domain in browser): " token
echo -n "$token" > /etc/yandex-dns-token
chmod go-rwx /etc/yandex-dns-token
curl -L -s https://gist.github.com/overplumbum/4196574/raw/yandex-dns.py > /usr/local/bin/yandex-dns-update
chmod +x /usr/local/bin/yandex-dns-update
cmd="/usr/local/bin/yandex-dns-update --domain $domain --interface='$interface' --subdomain $subdomain --token \$(cat /etc/yandex-dns-token) --keep"
echo "@reboot www-data $cmd >/dev/null" > /etc/cron.d/yandexdns
sh -c "$cmd"
#!/usr/bin/env python2
import argparse
import json
import os
import re
import sys
import time
from urllib import urlencode
from urllib2 import urlopen
import xml.etree.ElementTree as ET
parser = argparse.ArgumentParser()
parser.add_argument('--domain', required=True)
parser.add_argument('--subdomain', required=True)
parser.add_argument('--token', required=True)
parser.add_argument('--keep', action='store_true')
parser.add_argument('--force', action='store_true')
parser.add_argument('--interface', default='')
args = parser.parse_args()
storage = '/var/lib/yandex-dns.json'
if os.path.exists(storage):
stored_data = json.load(open(storage, 'r'))
else:
stored_data = {}
store_key = args.domain + '|' + args.subdomain + '|' + args.interface
if not args.interface:
ip = urlopen('http://checkip.dyndns.com/').read().strip()
ip = re.search(r'\d+\.\d+\.\d+\.\d+', ip).group(0)
else:
import socket
import fcntl
import struct
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ip = socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', args.interface[:15])
)[20:24])
print 'detected ip', ip
if not args.force and ip == stored_data.get(store_key):
print 'not changed'
sys.exit(0)
# http://api.yandex.ru/pdd/doc/api-pdd/reference/api-dns.xml
base_params = {
'token': args.token,
'domain': args.domain,
}
def get_sub_id():
data = urlopen('https://pddimp.yandex.ru/nsapi/get_domain_records.xml?' + urlencode(base_params)).read()
root = ET.fromstring(data)
node = root.find("domains/domain/response/record[@subdomain='" + args.subdomain + "']")
if not node is None:
return node.attrib['id']
sub_id = get_sub_id()
if not sub_id:
print 'sub-domain not found, adding'
params = base_params.copy()
params.update({
'subdomain': args.subdomain,
'ttl': 900,
'content': ip,
})
data = urlopen('https://pddimp.yandex.ru/nsapi/add_a_record.xml?' + urlencode(params)).read()
root = ET.fromstring(data)
error = root.findtext('domains/error')
assert error == 'ok', error
print "added"
time.sleep(1)
sub_id = get_sub_id()
assert sub_id
print 'dns listing ok'
params = base_params.copy()
params.update({
'subdomain': args.subdomain,
'record_id': str(sub_id),
'ttl': 900,
'content': ip,
})
data = urlopen('https://pddimp.yandex.ru/nsapi/edit_a_record.xml?' + urlencode(params)).read()
root = ET.fromstring(data)
error = root.findtext('domains/error')
assert error == 'ok', error
print 'dns update ok'
stored_data[store_key] = ip
json.dump(stored_data, open(storage, 'w'), indent=4)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment