300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 百度域名解析API+python实现百度云DDNS功能绑定动态公网ip

百度域名解析API+python实现百度云DDNS功能绑定动态公网ip

时间:2021-03-29 19:04:00

相关推荐

百度域名解析API+python实现百度云DDNS功能绑定动态公网ip

背景:前段时间,朋友为了使用NAS服务,开通了电信的动态公网IP,也就是那种公网IP地址会定期变化,重启光猫也会导致IP变化,朋友的水星低端路由器支持花生壳DDNS,去花生壳官网申请服务后能够正常使用,但是隔一两天就会出现路由器花生壳服务掉线,重新连接不上的奇怪问题,久久不能解决,然后他找到了我,本着助人为乐的精神,我给他找到了一个替代方案。

简述:百度注册的域名可以提供域名解析API服务,但是需要工单申请API权限,申请后可以通过 python实现域名解析的动态更新,适合动态公网用户。

前期准备:

1.你需要拥有一个百度云注册的域名,并且已经备案(政策规定,国内未备案域名不能提供域名解析服务)。

2.去百度云个人中心>安全认证界面,创建Access Key,记录下这个Access Key和Secret Key。

3.去工单>域名服务>申请开通域名API>创建工单,贴上Access Key,申请开通域名解析API。

4.去域名管理界面设置一个域名解析A记录,具体设置教程自行百度。

一些说明:

百度云提供了域名解析API相关的帮助文档(域名服务-百度智能云),根据文档,其最重要的部分是生成认证Authorization字符串,具体步骤可以参考其网址(/doc/Reference/s/Njwvz1wot),这里就不做具体阐述。其网站提供了一个例子,签名算法没有问题,但是使用的是python requests模块,经过实践并不能成功,原因在于requests会在请求数据header自动添加一些无关的头,但是这些头服务器会纳入鉴权计算,导致服务器鉴权Authorization字符串算出来和本地不一致。

代码部分:

import hmacimport timeimport requests import urllib.parseimport socketimport jsonimport osclass DDNS:def __init__(self,url,AK,SK):self.url=urlself.AK=AKself.SK=SKdef getTime(self):#获取网络时间戳,用于鉴权url="http://api./rest/api3.do?api=mon.getTimestamp"res=requests.get(url,timeout=5).textres=json.loads(res)["data"]["t"]return int(res)/1000def getIP(self):#获取本地公网IPurl="/cityjson?ie=utf-8"res=requests.get(url,timeout=5).textres=res.split("=")[1].split(";")[0] #转换javascript为json格式res=json.loads(res)res=res["cip"]return resdef enc(self,key,message):h=hmac.new(key,message,digestmod="SHA256")return h.hexdigest()def post(self,URI,_data):#填写参数#获取UTC时间utc = time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime(self.getTime()))#POST字典1data=json.dumps(_data)#创建请求header字典_headers={"host":"","x-bce-date":utc,"Content-Type":"application/json;charset=utf-8","Content-Length":str(len(data))}#格式化字典为http头标准格式headers=""for a,b in _headers.items():headers+=a+":"+b+"\r\n"#生成CanonicalHeadersmethod = "POST"CanonicalQueryString=""CanonicalURI = urllib.parse.quote(URI) result = []for key,value in _headers.items():tempStr = str(urllib.parse.quote(key.lower(),safe="")) + ":" + str(urllib.parse.quote(value,safe=""))result.append(tempStr)result.sort()CanonicalHeaders = "\n".join(result)#拼接得到CanonicalRequestCanonicalRequest = method + "\n" + CanonicalURI + "\n" + CanonicalQueryString +"\n" + CanonicalHeaders#计算signingKeysigningKey=self.enc(self.SK.encode(),b"bce-auth-v1/%b/%b/1800"%(self.AK.encode(),utc.encode()))#计算signaturesignature=self.enc(signingKey.encode(),CanonicalRequest.encode())#生成认证AuthorizationAuthorization="bce-auth-v1/%s/%s/1800/content-length;content-type;host;x-bce-date/%s"%(self.AK,utc,signature)#最后生成完整的http请求http="POST %s HTTP/1.1\r\n%sAuthorization:%s\r\n\r\n"%(URI,headers,Authorization)+data#建立socket链接,发送http数据s=socket.socket()s.connect(("",80))s.send(http.encode())res=b"" while True:_res=s.recv(10240)res+=_resif b"chunked" not in res: #如果不是chunked,一次性读完退出breakif _res[-5:]==b"0\r\n\r\n": #chunked标志,连续读取到标识符退出breaks.close()return resdef getID(self):data={'domain':self.url,'pageNo':1,'pageSize':100}url="/v1/domain/resolve/list"res=self.post(url,data)res=res.decode().split("\r\n{")[1].split("}\r\n")[0]res="{"+res+"}"res=json.loads(res)["result"]recordId={}for i in res:recordId[i["domain"]]=(i["recordId"],i["rdata"])return recordIddef SET(self,domain,ip):recordId=self.getID()self.urlIP=recordId[domain][1]if ip!=recordId[domain][1]:url="/v1/domain/resolve/edit"data={"domain" : domain,"rdType" : "A","rdata" : ip,"ttl" : 60,"zoneName" : self.url,"recordId" : recordId[domain][0]}res=self.post(url,data)#print(res)if __name__ == "__main__":#参数设置url="" #填写你的域名,如,仅填写AK=""#Access Key 百度云控制台申请SK=""#Secret Key 百度云控制台申请sync=60 #检测间隔时间,建议60秒#循环监控ddns=DDNS(url,AK,SK)first=Truejsq=syncwhile True:os.system("title DDNS服务已启动【%s秒后更新】"%jsq)if jsq==0 or first==True:try:ddns.SET("@",ddns.getIP())os.system("cls")now=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(ddns.getTime()))print("---------百度域名DDNS信息---------\n\n域名:%s\n-----\n域名解析IP:%s\n本地公网IP:%s\n更新时间:%s"%(url,ddns.urlIP,ddns.getIP(),now))except:passjsq=syncfirst=Falsetime.sleep(1)jsq-=1

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。