利用 CloudFlare API 实现自动 DDNS 功能|支持IPv4|IPv6
不知道什么时候起,宽带变成了 N 级 NAT,花生壳、ORAY、NO-IP 等基于动态公网 IP 的 DDNS 服务全线倒地,虽然 FRP、NGROK 这些内网穿透依然可以实现类 DDNS 功能,但网络严重依赖于中转服务器带宽,不是非常适合有大流量需求的业务,比如监控、云盘、同步等等。
最近发现本地宽带终于支持 IPv6 了,DDNS 就又可以搞起来了,考虑到安全问题,本文将探讨使用 CloudFlare API 来实现 DDNS 功能。
对了,DDNS 是指动态 DNS(英语:Dynamic DNS)是域名系统(DNS)中的一种自动更新名称服务器(Name Server)内容的技术,根据互联网的域名订立规则,域名必须有固定的 IP 地址,动态 DNS 系统就是为动态 IP 提供一个固定的名称服务器(Name Server),通过即时更新,使外界用户能够连上使用动态 IP 用户的网址。
一、思路
虽然现在上了 IPv6,可以直接与外界通信,但仍然不是静态 IP,即重新拨号或重新联网后,IP 会发生变更,根据 DDNS 原理,可以通过实时监测公网 IP,判断是否发生变更,一旦监测到发生变更,则立即更新 DNS 记录。
二、实现
CloudFlare 以前就有介绍过,是一家功能十分强大的电信服务提供商,今天我们就是通过其 DNS 管理和 API 功能来实现上述思路。
1、SHELL 脚本代码
#!/bin/bash
############### 授权信息(需修改成你自己的) ################
# CloudFlare 注册邮箱
auth_email=”user@example.com”
# CloudFlare Global API Key,下一节会说到
auth_key=”c2547eb745079dac9320b638f5e225cf483cc5cfdda41″
# 做 DDNS 的根域名
zone_name=”example.com”
# 做 DDNS 的域名,创建成功后就是通过该域名访问内网资源
record_name=”www.example.com”
###################### 修改配置信息 #######################
# 域名类型,IPv4 为 A,IPv6 则是 AAAA
record_type=”AAAA”
# IPv6 检测服务
ip=$(curl -s https://ipv6.vircloud.net)
# IPv4 检测服务
#ip=$(curl -s https://ipv4.vircloud.net)
# 变动前的公网 IP 保存位置
ip_file=”ip.txt”
# 域名识别信息保存位置
id_file=”cloudflare.ids”
# 监测日志保存位置
log_file=”cloudflare.log”
###################### 监测日志格式 ########################
log() {
if [ “$1” ]; then
echo -e “[$(date)] – $1” >> $log_file
fi
}
log “Check Initiated”
###################### 判断 IP 是否变化 ####################
if [ -f $ip_file ]; then
old_ip=$(cat $ip_file)
if [ “$ip” == “$old_ip” ]; then
echo “IP has not changed.”
exit 0
fi
fi
###################### 获取域名及授权 ######################
if [ -f $id_file ] && [ $(wc -l $id_file | cut -d ” ” -f 1) == 2 ]; then
zone_identifier=$(head -1 $id_file)
record_identifier=$(tail -1 $id_file)
else
zone_identifier=$(curl -s -X GET “https://api.cloudflare.com/client/v4/zones?name=$zone_name” -H “X-Auth-Email: $auth_email” -H “X-Auth-Key: $auth_key” -H “Content-Type: application/json” | grep -Po ‘(?<=”id”:”)[^”]*’ | head -1 )
record_identifier=$(curl -s -X GET “https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?name=$record_name&type=$record_type” -H “X-Auth-Email: $auth_email” -H “X-Auth-Key: $auth_key” -H “Content-Type: application/json” | grep -Po ‘(?<=”id”:”)[^”]*’) echo “$zone_identifier” > $id_file
echo “$record_identifier” >> $id_file
fi
###################### 更新 DNS 记录 ######################
update=$(curl -s -X PUT “https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier” -H “X-Auth-Email: $auth_email” -H “X-Auth-Key: $auth_key” -H “Content-Type: application/json” –data “{\”id\”:\”$zone_identifier\”,\”type\”:\”$record_type\”,\”name\”:\”$record_name\”,\”content\”:\”$ip\”}”)
################### 更新反馈 #########################
if [[ $update == *”\”success\”:false”* ]]; then
message=”API UPDATE FAILED. DUMPING RESULTS:\n$update”
log “$message”
echo -e “$message”
exit 1
else
message=”IP changed to: $ip”
echo “$ip” > $ip_file
log “$message”
echo “$message”
fi
2、获取授权信息
使用 CloudFlare “DDNS 服务” 需要把域名托管到 CloudFlare,此处不做介绍,自行搜索。
在 DNS 页面,由于我们要达到的是 DDNS 效果,所以 CDN 不要开启,即这朵云保持灰色状态(默认是开启的):
DNS Records.png图 1:DNS Records(图片不显示?)
其中 Type 是你要设置的 IP 类型,Name 是要做为连接的域名, Value 第一次可以随便设一个,TTL 2 minutes 或者 Automatic 都可以,再次强调 Status 这朵云不要点亮。
在 个人信息页面 下滑到 API Keys,把 Global API Key 一串字符贴到上述脚本中的 auth_key:
API Keys.png图 2:API Keys(图片不显示?)
3、执行结果
~# chmod +x ddns.sh
~# ./ddns.sh
IP changed to: ****
~# ./ddns.sh
IP has not changed.
4、定时运行
由于无法得知运营商什么时候会把 IP 变了,所以我们可以设置定时运行脚本来实现实时监控 并更新 IP 的变化。比如通过 crontab 实现:
~# crontab -e
……
*/10 * * * * /root/ddns.sh >/dev/null 2>&1
……
可以通过 cloudflare.log 来查看历史执行记录。
5、错误分析
问题
~# ./ddns.sh
API UPDATE FAILED. DUMPING RESULTS:
{“success”:false,”errors”:[{“code”:6007,”message”:”Malformed JSON in request body”}],”messages”:[],”result”:null}
分析
猜测是网络原因引起的,概率出现这个提示,如若出现忽略再执行一次即可。
三、总结
自己搭建 DDNS 最大的好处在于可以充分发挥宽带的带宽,不再局限于服务端的限制,其次安全性有了保证,可以不受服务提供者的记录。
其实并不仅仅 CloudFlare 可以实现,其他支持 API 更新 DNS 的 DNS 服务商理论上都支持通过上面的方法来实现 DDNS,而且从网络大环境而言,国内的服务商肯定会比国外的稳定。