0x01 前言
DDNS解析脚本持续更新,后面将新增其他服务商的DNS解析服务,通过调用API实现DDNS功能。因为IPv6的部署已经在快速推进,我也顺应时代的发展,更新脚本,实现对IPv6的支持。
0x02 本地IP地址获取服务
先讲解下新上线的本地IP地址获取服务,我是通过nginx实现相关功能的,完全不需要后端的支持,以下是nginx的配置文件:
server { listen 443 ssl http2; server_name ipv4.ngx.hk; ssl_certificate /usr/local/nginx/ssl/ngx.hk.crt; ssl_certificate_key /usr/local/nginx/ssl/ngx.hk.key; ssl_buffer_size 16k; ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3; ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521; ssl_ciphers TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256; ssl_prefer_server_ciphers on; ssl_session_timeout 3h; ssl_stapling on; ssl_session_tickets on; access_log /var/log/nginx/access.log main; add_header Strict-Transport-Security "max-age=31536000; preload; includeSubDomains" always; add_header X-Frame-Options SAMEORIGIN; gzip on; location / { default_type text/plain; return 200 "$remote_addr"; } }
以上是:ipv4.ngx.hk 这个域名的配置文件,其中最为重要的是location字段,直接给访客返还200响应码并附带访客的IP地址。通过浏览器打开的效果如下:
没错,及其简单的一个页面,源代码里完全没有一个多余的字符,但这已经满足我们的需求了。而IPv6和IPv4类似,就是listen和server_name有所区别:
listen [::]:443 ssl http2; server_name ipv6.ngx.hk;
监听所有和IPv4一样,nginx会监听我服务器中所有的IPv6地址,虽然我只有一个IPv6地址。
因为我这域名加入了HSTS list,还需要添加80端口的虚拟机配置,以便让访客跳转到HTTPS协议:
# IPv4 server { listen 80; server_name ipv4.ngx.hk; access_log /var/log/nginx/access.log main; gzip on; return 301 https://ipv4.ngx.hk; } # IPv6 server { listen [::]:80; server_name ipv6.ngx.hk; access_log /var/log/nginx/access.log main; gzip on; return 301 https://ipv6.ngx.hk; }
其实我有想过只通过一个域名同时监听IPv4和IPv6的,但当客户机同时拥有两种IP的时候,访问我的服务就只能返还一种IP地址,除非在脚本中加入相关代码进行区分。这样过于繁琐,因此我决定将其拆分,形成以下两个域名:
- IPv4:https://ipv4.ngx.hk
- IPv6:https://ipv6.ngx.hk
最后是这个服务器的服务商,我计划长期租用OVH的高防VPS,每月仅3.5美元,1个核心,2G内存,百兆端口不限量,还带抗DDOS服务。这价格是及其良心,为什么不用?就是延迟高点,所以在新版的脚本里调整了HTTP超时时长为30秒。
也正是只运行一个nginx,这个资源的VPS也足够用一段很长的时间了,价格也是我能承受得起的。
0x03 准备
脚本仅支持通过python3调用,需要通过pip3安装以下依赖包:
pip3 install aliyun-python-sdk-core-v3 aliyun-python-sdk-alidns requests
然后到使用以下命令将源码克隆到本地:
git clone https://gitlab.ngx.hk/aliyun/DDNS.git
也可以访问我的GitHub镜像:
克隆到本地后先将配置文件复制一份并重命名为config.conf,然后进行修改:
{ "0": { "access_key_id": "", "access_Key_secret": "", "domain": "", "sub_domain": "", "ttl": "", "ip_ver": 4 }, "1": { "access_key_id": "", "access_Key_secret": "", "domain": "", "sub_domain": "", "ttl": "", "ip_ver": 6 } }
脚本支持同时为同一个域名添加IPv4和IPv6的DNS记录,如:
IPv4:https://ip.ngx.hk -> 51.75.251.225 IPv6:https://ip.ngx.hk -> 2001:41d0:305:2100:0:0:0:68c0
这时候的配置文件如下:
{ "0": { "access_key_id": "aaaaaaaaaaaaaaaaaaaa", "access_Key_secret": "bbbbbbbbbbbbbbbbbbb", "domain": "ngx.hk", "sub_domain": "ip", "ttl": "600", "ip_ver": 4 }, "1": { "access_key_id": "aaaaaaaaaaaaaaaaaaaa", "access_Key_secret": "bbbbbbbbbbbbbbbbbbb", "domain": "ngx.hk", "sub_domain": "ip", "ttl": "600", "ip_ver": 6 } }
也可以为不同域名添加记录,此时只要按需修改domain和sub_domain即可。如果只需要添加单一IP版本,则需要删除多余的配置信息,如:
{ "0": { "access_key_id": "aaaaaaaaaaaaaaaaaaaa", "access_Key_secret": "bbbbbbbbbbbbbbbbbbb", "domain": "ngx.hk", "sub_domain": "ip", "ttl": "600", "ip_ver": 4 } }
而最后的“ip_ver”则是指定IP版本的配置信息,上一个“ttl”则需要根据实际情况进行选择,非腾讯云DNS解析服务的VIP,最小ttl为600,此时请勿填写小于600的数,否则会报错。
0x04 脚本更新与执行
脚本仅修改了小部分代码,首先是本地IP检测的部分:
# 获取IP地址,支持v4与v6 def my_ip(i_ip_ver): if i_ip_ver == 4: get_ip_value = requests.get('https://ipv4.ngx.hk', timeout=30).content.decode().strip('\n') else: get_ip_value = requests.get('https://ipv6.ngx.hk', timeout=30).content.decode().strip('\n') return get_ip_value
该函数会根据传入的IP类型访问不同的域名,从而获取到自身的IP并返还。
因为新增了IPv6,因此在新增与更新域名解析的函数也需要稍作调整:
# 更新子域名信息 def update_dns(ali_ctl, sub_domain, dns_value, ttl, dns_record_id, ip_ver): request = UpdateDomainRecordRequest.UpdateDomainRecordRequest() request.set_RR(sub_domain) request.set_Value(dns_value) request.set_RecordId(dns_record_id) request.set_TTL(ttl) request.set_accept_format('json') if ip_ver == 4: request.set_Type('A') else: request.set_Type('AAAA') result = ali_ctl.do_action_with_exception(request) return result # 新增子域名解析 def add_dns(ali_ctl, dns_value, domain, sub_domain, ttl, ip_ver): request = AddDomainRecordRequest.AddDomainRecordRequest() request.set_DomainName(domain) request.set_RR(sub_domain) request.set_Value(dns_value) request.set_TTL(ttl) if ip_ver == 4: request.set_Type('A') else: request.set_Type('AAAA') result = ali_ctl.do_action_with_exception(request) return result
其余部分则未作修改。脚本的执行的方式与之前无异,使用python3调用脚本即可:
[root@web ~]# python3 /usr/local/services_data/shell/DDNS/aliyun_ddns.py
0x05 结语
完整的代码可留意我的私有gitlab与GitHub镜像:
如果有其他功能需求或建议,请通过电子邮件与我取得联系。如果有BUG,请在GitHub提issues。
之前版本的相关文章请留意以下链接: