工信部强制要求运营商为家庭宽带设置公网IPv6,基本所有人都能够获取到IPv6,由于大部分IP是动态的,所以可以用python代码去动态解析域名到家庭公网上
手动运行一次:
python dynamic_modify_dns.py -domain=xxx.top -sub_domain=ipv6 -is_ipv6 -check_ip_fmt
参数解释:
-is_ipv6选项可以选择ipv6模式,默认是ipv4模式
-domain参数即为你拥有的域名
-sub_domain是指定子域名,默认二级域名为ipv4 (例:ipv4.xxx.top)
-check_ip_fmt参数可以不加
运行前准备工作:
1.到为你的域名提供解析服务的dnspod控制台获取secret,填入到代码中的SECRET_ID和SECRET_KEY中,dnspod控制台网址:https://console.dnspod.cn/
2.安装一下依赖包
pip install -i https://mirrors.tencent.com/pypi/simple/ --upgrade tencentcloud-sdk-python click IPy
3.放到你的服务器上长久运行,推荐使用crontab(使用绝对路径更佳)
1 |
* * * * * python dynamic_modify_dns.py -domain=xxx.top -sub_domain=ipv6 -is_ipv6 -check_ip_fmt > /tmp/ddns.log |
python代码
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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
import json import datetime import time import traceback import click as click from tencentcloud.common import credential from tencentcloud.common.profile.http_profile import HttpProfile from tencentcloud.common.profile.client_profile import ClientProfile from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException from tencentcloud.dnspod.v20210323 import dnspod_client, models SECRET_ID = "" SECRET_KEY = "" def try_catch_and_score_time(fn): def _wrapper(*args, **kwargs): start = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(f"{start} start ddns.") ret = None try: ret = fn(*args, **kwargs) except TencentCloudSDKException as e: print(f"{traceback.format_exc()} error: {e}") end = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(f"{end} program exit now.") return ret return _wrapper class DDNS: def __init__(self, domain, sub_domain="", ipv6=True, check_ip_fmt=False): self._domain = domain self._sub_domain = sub_domain if len(sub_domain) > 0 else ("ipv6" if ipv6 else "ipv4") self._is_ipv6 = ipv6 self._record_type = "AAAA" if self._is_ipv6 else "A" # 待修改解析记录的解析类型,AAAA为解析到ipv6的记录类型 self._client = self.get_tencentcloud_client() self._check_ip_format = check_ip_fmt @try_catch_and_score_time def dynamic_modify_dns(self): """ 默认DDNS到ipv6地址 """ if self._client is None: return # 1. 获取域名下的所有解析记录 req = models.DescribeRecordRequest() params = { "Domain": self._domain } req.from_json_string(json.dumps(params)) resp = self._client.DescribeRecordList(req) # with open("record_list.json", "w") as f: # f.write(resp.to_json_string()) record_list = resp.RecordList if len(record_list) <= 0: print(f"RecordList length is 0. service will exit.") return # 2. 过滤解析记录列表,拿到需要修改的记录 record_need_to_modify: models.RecordListItem = None for record in record_list: name = record.Name record_type = record.Type if self._sub_domain != name or self._record_type != record_type: continue record_need_to_modify = record old_value = None if record_need_to_modify is None: print(f"{self._domain} doesn't have {self._sub_domain} {self._record_type} sub domain. " f"to create {self._sub_domain}.{self._domain} {self._record_type} record.") mod_record_id = self.create_dns_record() else: mod_record_id = record_need_to_modify.RecordId old_value = record_need_to_modify.Value # 3. 修改解析记录到动态ip上 dst_ip = self.get_dst_ip_for_dns_record(is_ipv6=self._is_ipv6, check=self._check_ip_format) if dst_ip is None: print(f"can't get new ip for ddns.") return if old_value == dst_ip: print(f"value doesn't need to update. value: {old_value}.") return req = models.ModifyDynamicDNSRequest() params = { "Domain": self._domain, "SubDomain": self._sub_domain, # 如果不传,默认为 @ "RecordId": mod_record_id, "RecordLine": "默认", "Value": dst_ip } print(params) req.from_json_string(json.dumps(params)) resp = self._client.ModifyDynamicDNS(req) if str(mod_record_id) in resp.to_json_string(): print("successfully update ddns record!") @staticmethod def get_tencentcloud_client(): for cnt in range(3): try: cred = credential.Credential(SECRET_ID, SECRET_KEY) httpProfile = HttpProfile() httpProfile.endpoint = "dnspod.tencentcloudapi.com" clientProfile = ClientProfile() clientProfile.httpProfile = httpProfile client = dnspod_client.DnspodClient(cred, "", clientProfile) return client except TencentCloudSDKException as e: print(f"program get tencent cloud client error for {cnt}: {e}.") time.sleep(cnt + 1) return None def create_dns_record(self): req = models.CreateRecordRequest() params = { "Domain": self._domain, "SubDomain": self._sub_domain, "RecordType": self._record_type, "RecordLine": "默认", "Value": "::1" if self._is_ipv6 else "127.0.0.1" } req.from_json_string(json.dumps(params)) resp = self._client.CreateRecord(req) return resp.RecordId def get_dst_ip_for_dns_record(self, is_ipv6, check=True): """ 获取解析到的ip :return: """ # 1. 第一种方法,向免费公共方法获取目前的外网IP import requests url = f"https://api{6 if is_ipv6 else ''}.ipify.org?format=json" r = requests.get(url, timeout=5) ip = json.loads(r.text).get('ip', None) if check: ip = self.check_ip_and_format(ip) return ip def check_ip_and_format(self, ipv6: str): if ipv6 == None: return None try: import IPy v = 6 if self._is_ipv6 else 4 IP = IPy.IP(ipv6) IP.iptype() # if IP.version == v and IP.iptype() in ['ALLOCATED APNIC']: if IP.version() == v: return str(IP) except Exception as e: print(e) return None # * * * * * python dynamic_modify_dns.py -domain=xxx.top -sub_domain=ipv6 -is_ipv6 -check_ip_fmt > /tmp/ddns.log @click.command() @click.option('-domain', required=True, default="", help="个人拥有的域名") @click.option('-sub_domain', default="ipv6", help="设置的二级域名") @click.option('-is_ipv6', is_flag=True, default=False, help="是否DDNS到ipv6上") @click.option('-check_ip_fmt', is_flag=True, default=False, help="检查IP格式") def cmd(domain, sub_domain, is_ipv6, check_ip_fmt): DDNS(domain=domain, sub_domain=sub_domain, ipv6=is_ipv6, check_ip_fmt=check_ip_fmt).dynamic_modify_dns() if __name__ == '__main__': cmd() |
- 转载:然并卵zh
- 本站教程,未注明转载均为原创内容,仅做为学习参考使用,切勿用于非法及商业用途!造成的后果作者不承担任何责任!
- 如果转载请注明出处!oD^Blog
- 本文如果需要更新,或者失效请联系微信 : oldiy2018 【微信不解答任何问题,不接收任何红包!】
- 如果支持作者,请点击下方赞赏,支持一杯饮料!
- 如果有问题可以点击【加入电报群】和我一起沟通或者下方留言讨论!
微信赞赏
支付宝赞赏