一、背景 前些年各种免费网盘如雨后春笋、铺天盖地,年轻的小伙伴纷纷将珍藏多年的学(稀)习(缺)材(资)料(源)拿出来上云,可是好景不长,各大网盘纷纷关闭,某度也对教育视屏痛下杀手。老师们飘逸的身姿、优雅的背影随着时间一点一点在小伙伴的记忆中慢慢褪去,消香玉损。 作为掌握先进科学知识的互联网从(屌)业(丝)者,自然要发扬“艰苦创业,自力更生”的革命精神,在家里打造属于自己的私有网盘。当然我们不必自己去开发一个完整功能的网盘,目前已经有好几个十分成熟的私有网盘项目,比如资格较老的OwnCloud,由上述原班人马打造的NextCloud,功能和插件都非常丰富的FileRun。你可以让它们运行在家里的电脑上、树莓派上、甚至是路由器上,但是接下来的问题是家庭使用宽带拨号上网的IP总是变化的,总不能每次在家里查好了IP再去访问网盘,所以本文重点是使用python脚本利用华为云解析服务的API实现动态域名解析 二、准备 1、域名一个,建议买一个,通常一年的费用也就60左右,却能给你带来巨大的品牌价值(逼格),当然免费的也有很多,详情Google。 2、在域名注册商将此域名解析到华为权威服务器,参考:http://support.huaweicloud.com/u ... pic_0035467702.html 3、在家里的服务器(PC、树莓派、路由器,有啥都行)上安装python执行环境 三、Code 1、一个对三方库requests封装的类,实现一些简单的HTTP方法请求及响应处理
- #!/usr/bin/python
- # coding: utf-8
- # HttpRequest.py
- # author : qshujun
- # version : 1.0.0
- # date : 2017/11/25
- import requests
- class HttpRequests():
- ´´´
- 对requests库封装的GET、POST、PUT等方法调用类
- ´´´
- def __init__(self, url, data=None, type=´GET´, cookie=None, headers=None):
- self.url = url
- self.data = data
- self.type = type
- self.cookie = cookie
- self.headers = headers
- self.send_request()
- def send_request(self):
- ´´´´´
- setup a request
- ´´´
- if self.url == None or self.url == ´´:
- raise ´The url should not empty!´
- if self.type == ´POST´:
- self.req = requests.post(self.url, data=self.data, headers=self.headers)
- elif self.type == ´GET´:
- if self.data == None:
- self.req = requests.get(self.url, headers=self.headers)
- else:
- self.req = requests.get(self.url, params=self.data, headers=self.headers)
- elif self.type == ´PUT´:
- self.req = requests.put(self.url, data=self.data, headers=self.headers)
- else:
- self.req = None
- raise ´The http request type NOT support now!´
- def get_code(self):
- try:
- return self.req.status_code
- except Exception,e:
- raise str(e)
- def get_url(self):
- try:
- return self.req.url
- except Exception,e:
- raise str(e)
- def get_text(self):
- try:
- return self.req.text
- except Exception,e:
- raise str(e)
- def get_headers(self):
- try:
- return self.req.headers
- except Exception,e:
- raise str(e)
- def get_cookie(self):
- headers = self.get_headers()
- if ´set-cookie´ in headers:
- return headers[´set-cookie´]
- else:
- return None
- #!/usr/bin/python
- # coding: utf-8
- # hwcloud-ddns.py
- # author : qshujun
- # version : 1.0.0
- # date : 2017/11/25
- import json
- import socket
- from HttpRequest import HttpRequests
- ´´´
- 定义全局变量
- ´´´
- #需要解析的域名及主机名
- domain = ´shujun.com´
- host = ´www´
- #认证信息
- domainname = ´domainname ´
- username = ´username ´
- password = ´password ´
- regionId = ´cn-north-1´
- iam_endpoint = ´https://iam.{regionId}.myhwclouds.com´
- get_token_uri = ´/v3/auth/tokens´
- #DNS接口信息
- nds_endpoint = ´https://dns.myhwclouds.com´
- query_zones_uri = ´/v2/zones?type=public&limit=50´
- create_zone_uri = ´/v2/zones´
- query_recordsets_uri = ´/v2/zones/{zone_id}/recordsets?limit=500´
- modify_recordset_uri = ´/v2/zones/{zone_id}/recordsets/{recordset_id}´
- create_recordset_uri = ´/v2/zones/{zone_id}/recordsets´
- #默认请求头
- headers = {´content-type´: ´application/json´}
- def get_iam_token():
- ´´´
- 以用户名、密码从IAN换取token并加入headers
- :return:
- ´´´
- iam_token_url = iam_endpoint.replace(´{regionId}´, regionId) + get_token_uri
- data = {
- "auth": {
- "identity": {
- "methods": [
- "password"
- ],
- "password": {
- "user": {
- "name": username,
- "password": password,
- "domain": {
- "name": domainname
- }
- }
- }
- },
- "scope": {
- "project": {
- "name": regionId
- }
- }
- }
- }
- req = HttpRequests(iam_token_url, data=json.dumps(data),type=´POST´, headers=headers)
- if ´X-Subject-Token´ in req.get_headers():
- headers[´X-Auth-Token´] = req.get_headers()[´X-Subject-Token´]
- else:
- print ´Get IAM token failed, http code: %s, %s´ % (str(req.get_code()),req.get_text())
- exit(1)
- def query_zone():
- ´´´
- 查询zone(即domain:shujun.net)的id
- :return:zone_id
- ´´´
- query_zones_url = nds_endpoint + query_zones_uri
- req = HttpRequests(query_zones_url, headers=headers)
- if req.get_code() == 200:
- zones = json.loads(req.get_text())[´zones´]
- for zone in zones:
- if zone[´name´] == domain + ´.´:
- return zone[´id´]
- return None
- else:
- print ´Query zone list failed, http code: %s, %s´ % (str(req.get_code()),req.get_text())
- exit(1)
- def create_zone():
- ´´´
- 创建zone(即domain:shujun.net)的,并返回新zone的id
- :return: zone_id
- ´´´
- create_zone_url = nds_endpoint + create_zone_uri
- data = {
- "name": domain + ´.´,
- "description": "This is an example zone.",
- "zone_type": "public",
- "email": "xx@example.org"
- }
- req = HttpRequests(create_zone_url, type=´POST´, data=json.dumps(data), headers=headers)
- if req.get_code() == 202:
- zone = json.loads(req.get_text())
- return zone[´id´]
- else:
- print ´Create zone failed, http code: %s, %s´ % (str(req.get_code()),req.get_text())
- exit(1)
- def query_recordset(zone_id):
- ´´´
- 查询主机A记录,并返回记录链接及其值
- :param zone_id:
- :return: recordset_url,old_ip
- ´´´
- query_recordset_url = nds_endpoint + query_recordsets_uri.replace(´{zone_id}´,zone_id)
- req = HttpRequests(query_recordset_url, headers=headers)
- if req.get_code() == 200:
- recordsets = json.loads(req.get_text())[´recordsets´]
- for recordset in recordsets:
- if recordset[´name´] == host + ´.´ + domain + ´.´:
- return recordset[´links´][´self´], recordset[´records´][0]
- return None, None
- else:
- print ´Query recordset list failed, http code: %s, %s´ % (str(req.get_code()),req.get_text())
- exit(1)
- def modify_recordset(recordset_url,new_ip):
- ´´´
- 修改host.domain对应的A记录为新ip
- :param recordset_url:
- :param new_ip:
- :return:
- ´´´
- data = {
- "description": "This is an example record set.",
- "ttl": 300,
- "records": [new_ip]
- }
- req = HttpRequests(recordset_url, type=´PUT´, data=json.dumps(data), headers=headers)
- if req.get_code() == 202:
- return True
- else:
- print ´Modify recordset failed, http code: %s, %s´ % (str(req.get_code()),req.get_text())
- def create_recordset(zone_id,new_ip):
- ´´´
- 创建新的主机记录
- :param zone_id:
- :param new_ip:
- :return:
- ´´´
- create_recordset_url = nds_endpoint + create_recordset_uri.replace(´{zone_id}´, zone_id)
- date = {
- "name": host + ´.´ + domain + ´.´,
- "description": "This is an example record set.",
- "type": "A",
- "ttl": 300,
- "records": [new_ip]
- }
- req = HttpRequests(create_recordset_url, type=´POST´, data=json.dumps(date), headers=headers)
- if req.get_code() == 202:
- return True
- else:
- print ´Create recordset failed, http code: %s, %s´ % (str(req.get_code()),req.get_text())
- exit(1)
- def get_public_ip():
- ´´´
- 查询当前正在连接的公网ip
- :return:
- ´´´
- get_ip_url = ´http://www.3322.org/dyndns/getip´
- try:
- req = HttpRequests(get_ip_url)
- if req.get_code() == 200:
- return req.get_text()
- except Exception:
- pass
- try:
- sock = socket.create_connection((´ns1.dnspod.net´,6666))
- ip = sock.recv(16)
- sock.close()
- return ip
- except Exception:
- pass
- print ´Get Public IP failed, http code: %s, %s´ % (str(req.get_code()),req.get_text())
- exit(1)
- if __name__ == ´__main__´:
- new_ip = get_public_ip()
- get_iam_token()
- zone_id = query_zone()
- if zone_id == None:
- zone_id = create_zone()
- recordset_url, old_ip = query_recordset(zone_id)
- if recordset_url == None:
- create_recordset(zone_id,new_ip)
- else:
- if old_ip != new_ip:
- modify_recordset(recordset_url,new_ip)