February 23, 2012
自动更新DNSPod记录
今天将社区和个人的转移到了dnspod,原因是dnspod 提供免费的智能解析(电信、教育网什么的可以制定不同的IP地址),并且有丰富的API,可以用脚本更新记录,于是我就fork了dnspod官方的python脚本,写了个动态更新DNS记录的脚本。
比花生壳强大多啦!!!!
#!/usr/bin/env python2
# -*- coding:utf8 -*-
import httplib, urllib
import socket
import argparse
import time
import fcntl
import struct
from xml.etree import ElementTree
from getpass import getpass
DEBUG = False
params = dict(
login_email="", # replace with your email
login_password="", # replace with your password
format="json",
domain_id=None, # replace with your domain_od, can get it by API Domain.List
record_id=None, # replace with your record_id, can get it by API Record.List
record_type='A', # replace with your record_id, can get it by API Record.List
sub_domain="", # replace with your sub_domain
record_line="默认",
)
def ddns(ip):
params.update(dict(value=ip))
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/json"}
conn = httplib.HTTPSConnection("dnsapi.cn")
conn.request("POST", "/Record.Modify", urllib.urlencode(params), headers)
response = conn.getresponse()
if DEBUG: print response.status, response.reason
data = response.read()
if DEBUG: print data
conn.close()
return response.status == 200
def get_domain_id(domain_name):
keys = ["login_email", "login_password"]
_param = { k:v for k,v in params.iteritems() if k in keys }
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/json"}
conn = httplib.HTTPSConnection("dnsapi.cn")
conn.request("POST", "/Domain.list", urllib.urlencode(_param), headers)
response = conn.getresponse()
id = None
etree = ElementTree.parse(response)
for domain in etree.findall("domains/item"):
if domain.find("name").text == domain_name:
id = domain.find("id").text
conn.close()
if id:
return id
else:
raise Exception("Record '"+domain_name+"' not found!")
def get_record_id():
keys = ["login_email", "login_password", "domain_id"]
_param = { k:v for k,v in params.iteritems() if k in keys }
subdomain = params["sub_domain"]
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/json"}
conn = httplib.HTTPSConnection("dnsapi.cn")
conn.request("POST", "/Record.List", urllib.urlencode(_param), headers)
response = conn.getresponse()
etree = ElementTree.parse(response)
id = None
for record in etree.findall("records/item"):
if record.find("name").text == subdomain:
if DEBUG: print "Found", record.find("name").text
if id:
raise Exception("Multipule records of '"+subdomain+"' found. Please specify record id! ")
id = record.find("id").text
conn.close()
if id:
return id
else:
raise Exception("Record '"+subdomain+"' not found!")
def get_current_ip():
"""get current ip of """
keys = ["login_email", "login_password", "domain_id"]
record_id = params['record_id']
_param = { k:v for k,v in params.iteritems() if k in keys }
headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/json"}
conn = httplib.HTTPSConnection("dnsapi.cn")
conn.request("POST", "/Record.List", urllib.urlencode(_param), headers)
response = conn.getresponse()
etree = ElementTree.parse(response)
cur_ip = None
for record in etree.findall("records/item"):
if record.find("id").text == record_id:
cur_ip = record.find("value").text
conn.close()
return cur_ip
def get_public_ip():
""" get ip address from dnspod """
if DEBUG: print "getting ip address from dnspod..."
sock = socket.create_connection(('ns1.dnspod.net', 6666))
ip = sock.recv(16)
sock.close()
return ip
def get_if_ip(ifname):
"""Get ip address by interface, Linux ONLY"""
if DEBUG: print "getting ip address of", ifname
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
def parse_arg():
parser = argparse.ArgumentParser(description="Update dns record on dnspod dynamically.")
parser.add_argument( '-I', '--interval', help="Set test interval, default is 300 seconds." )
parser.add_argument( '-i', '--interface', help="Set interface." )
parser.add_argument( '-u','--username', help="Set login email." )
parser.add_argument( '-p','--password', help="Set login password." )
parser.add_argument( '-d','--domain', help="Set domain name." )
parser.add_argument( '-s','-r','--subdomain', help="Set subdomain/record name." )
parser.add_argument( '--domain-id', help="Set domain id." )
parser.add_argument( '--record-id', help="Set record id." )
parser.add_argument( '--debug',action="store_true", help="Show debug outputs." )
return parser.parse_args()
if __name__ == '__main__':
args = parse_arg()
# confiure
DEBUG = args.debug or False
interval = args.interval or 300
#Set domain name
domain = args.domain or raw_input("Domain name: ")
params['sub_domain'] = params['sub_domain'] \
or args.subdomain or raw_input("Subomain: ") or "@"
#Login info
params['login_email'] = params['login_email'] \
or args.username or raw_input("E-mail: ")
params['login_password'] = params['login_password'] \
or args.password or getpass()
#domain and record id
params['domain_id'] = params['domain_id'] \
or args.domain_id or get_domain_id(domain)
params['record_id'] = params['record_id'] \
or args.record_id or get_record_id()
print params
if args.interface:
getip = lambda : get_if_ip(args.interface)
else:
getip = lambda : get_public_ip()
if DEBUG:
print "domain_name: ", params['sub_domain']+'.'+domain
print "domain id:", params['domain_id']
print "record id:", params['record_id']
print "interval: ", interval
current_ip = get_current_ip()
while True:
try:
ip = getip()
if DEBUG: print "ip:", ip
if DEBUG: print "record ip:", current_ip
if current_ip != ip:
if ddns(ip):
current_ip = ip
except Exception, e:
print e
pass
time.sleep(interval)
以后可能会常更新,新的代码会放在 github 上。
另有一份增强版,可以读却配置文件,支持更新多个域名,当然代码行数也多了… 放在 这里 。
要求是python2.7,python2.7以下版本(如在centos上)需要单独安装argparse模块
参数说明: ./dnspod.py -h
-I INTERVAL, --interval INTERVAL
心跳时间,默认为5分钟
-i INTERFACE, --interface INTERFACE
指定网络接口,不指定则会请求公共IP
-u USERNAME, --username USERNAME
登陆的email,不指定则交互输入
-p PASSWORD, --password PASSWORD
密码,不指定则交互输入
-d DOMAIN, --domain DOMAIN
主域名,不指定则交互输入
-s SUBDOMAIN, -r SUBDOMAIN, --subdomain SUBDOMAIN
子域,不指定则交互输入
--domain-id DOMAIN_ID
主域ID,可选
--record-id RECORD_ID
子域ID,由于一个子域可以有多条记录,这种情况必须指定,否则可选
--debug 显示debug信息
例如: ./dnspod.py –debug -d bigeagle.me -s home -u xxx@gmail.com
则会更新home.bigeagle.me
的记录