-
Notifications
You must be signed in to change notification settings - Fork 31
/
Copy pathdnspod.py
147 lines (123 loc) · 4.34 KB
/
dnspod.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python
# -*- coding:utf8 -*-
import os, sys
import requests
import socket
import yaml
reload(sys)
sys.setdefaultencoding("utf8")
def logger():
import logging
LOG_FORMAT = "[%(asctime)s]\t[%(levelname)s]\t[%(message)s]"
LOG_FILE = os.path.join(os.path.dirname(os.path.realpath(__file__)), "log.txt")
logging.basicConfig(format=LOG_FORMAT, level=logging.DEBUG, filename=LOG_FILE)
return logging.getLogger(__name__)
def getopts():
import argparse
parser = argparse.ArgumentParser(description='github.com/migege/dnspod')
parser.add_argument('config', help='config file in yaml')
opts = parser.parse_args()
return opts
class Last(object):
def __init__(self, tag):
self.fn = os.path.join(os.path.dirname(os.path.realpath(__file__)), tag)
def Read(self):
try:
with open(self.fn, "r") as fp:
return fp.read()
except:
return None
def Write(self, value):
with open(self.fn, "w") as fp:
fp.write(value)
class DNSPod(object):
def __init__(self, conf):
self.ip = Last('last.ip').Read()
self.conf_md5 = Last('conf.md5').Read()
self.conf = conf
def run(self):
ip = self.GetIP()
conf_md5 = self.GetConfMD5()
if ip and ip != self.ip:
logger().info("IP changed from '%s' to '%s'", self.ip, ip)
if self.DDns(ip):
self.ip = ip
Last('last.ip').Write(self.ip)
return
if conf_md5 and conf_md5 != self.conf_md5:
logger().info("MD5 of conf changed")
if self.DDns(ip):
self.ip = ip
self.conf_md5 = conf_md5
Last('last.ip').Write(self.ip)
Last('conf.md5').Write(self.conf_md5)
return
def GetIP(self):
try:
sock = socket.create_connection(address=('ns1.dnspod.net', 6666), timeout=10)
ip = sock.recv(32)
sock.close()
return ip
except Exception, e:
logger().error("GetIP Error: %s", e)
return None
def GetConfMD5(self):
try:
import hashlib
import json
md5 = hashlib.md5(json.dumps(self.conf)).hexdigest()
return md5
except Exception, e:
logger().error('GetConfMD5 Error: %s', e)
return None
def __DDnsImpl(self, ip, todo_list):
url = "https://dnsapi.cn/Record.Ddns"
headers = {
"User-Agent": "github.com#migege#dnspod/0.0.2 ([email protected])",
}
retry_list = []
for sub_domain, v in todo_list:
try:
valid = v["valid"]
if not valid:
continue
except:
pass
try:
domain_id = v["domain_id"]
record_id = v["record_id"]
data = {
"login_token": self.conf["token"],
"format": "json",
"domain_id": domain_id,
"record_id": record_id,
"sub_domain": sub_domain,
"record_line": "默认",
"value": ip,
}
r = requests.post(url, data=data, headers=headers)
if int(r.json()["status"]["code"]) == 1:
logger().info("DDns OK for subdomain [%s]", sub_domain)
else:
logger().error("DDns response for subdomain [%s]: %s", sub_domain, r.text)
retry_list.append((sub_domain, v))
except Exception, e:
logger().error("DDns Error for subdomain [%s]: %s", sub_domain, e)
retry_list.append((sub_domain, v))
return retry_list
def DDns(self, ip):
RETRY_LIMIT = 2
retry_list = self.__DDnsImpl(ip, self.conf["sub_domains"].items())
retry = 0
while retry_list and retry < RETRY_LIMIT:
retry_list = self.__DDnsImpl(ip, retry_list)
retry += 1
if not retry_list:
return True
else:
return False
if __name__ == '__main__':
opts = getopts()
conf = yaml.load(open(os.path.join(os.path.dirname(os.path.realpath(__file__)), opts.config), "r"))
dnspod = DNSPod(conf)
dnspod.run()