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。
之前版本的相关文章请留意以下链接:






















