Shell脚本实现DNSPod域名动态解析IPv6地址

  1. 为了解决家用宽带和手机移动数据的IPV6地址动态分配,表现为每次设备重启或重新拨号IP地址都会变换。而获取的IPv4地址为内网地址 从而无法通过它访问拨号设备。所以需要通过域名动态解析来使拨号设备的IPv6地址与指定域名绑定,实现其他IPv6设备能通过指定域名访问该拨号的设备

  2. 首先【获取DNSPod的Token】,注意不要弄错成【腾讯云API密钥】了

1
2
3
4
5
6
7
8
9
10
11
# 在腾讯云注册的域名登陆后在【我的账号】的【账号中心】中,有【密钥管理】中点击创建密钥即可创建一个API
# 如果你在腾讯云注册域名叫【test.com】,那么【dnspod_ddnsipv6_domain】后面就填【test.com】
# 然后根据如下常用的规范/自己想要的名字在【dnspod_ddnsipv6_subdomain】填入自己需要的名字
# 现假设为【file】,那么你的访问地址为【file.test.com】

# 常用的【二级域名】规范如下:
# 【www】 常见主机记录,将域名解析为 www.test.com
# 【@】 直接解析主域名 test.com
# 【*】 泛解析,匹配其他所有域名 *.test.com

# 后续脚本来源:https://blog.csdn.net/weixin_43978546/article/details/113222378
  1. 简单的IPV6地址动态域名分配脚本如下:
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
# 需将如下的 4~9行 替换为自己的域名信息即可,后面可以保持不动。执行成功后的访问地址为:http://file.test.com

#!/usr/bin/bash
dnspod_ddnsipv6_id="123456" #【 API_ID 】将引号内容修改为获取的API的ID
dnspod_ddnsipv6_token="**1234abc**" #【API_Token】将引号内容修改为获取的API的Token
dnspod_ddnsipv6_ttl="600" #【TTL 时间】解析记录在 DNS 服务器缓存的生存时间,默认600(s/秒)
dnspod_ddnsipv6_domain='test.com' #【一级域名】引号里改成自己注册的域名
dnspod_ddnsipv6_subdomain='file' #【域名前缀】将引号内容修改为自己想要的名字,需要符合域名规范,附常用的规范
local_net="eth0" #【网卡名称】默认为eth0,如果你的公网ipv6地址不在eth0上,需要修改为对应的网络适配器

if [ "$dnspod_ddnsipv6_record" = "@" ]
then
dnspod_ddnsipv6_name=$dnspod_ddnsipv6_domain
else
dnspod_ddnsipv6_name=$dnspod_ddnsipv6_subdomain.$dnspod_ddnsipv6_domain
fi

die () {
echo "Error: unable to find [public IPv6 address], please use the 'ip addr' command or query the network panel of the system to check the network card, and fill in the name of the network card with the IPv6 address in the 'local_net' position in the command file." >&2
echo "IP地址提取错误: 在指定的网络适配器上[$local_net]找不到<公网IPv6地址>(不是fe80开头),请使用'ip addr'命令或在系统的网络面板查询有公网IP的网络适配器,然后在脚本的[local_net]中用填写网络适配器的名称。" >&2
exit
}

ipv6_list=`ip addr show $local_net | grep "inet6.*global" | awk '{print $2}' | awk -F"/" '{print $1}'` || die

for ipv6 in ${ipv6_list[@]}
do
if [[ "$ipv6" =~ ^fe80.* ]]
then
continue
else
echo select IP: $ipv6 >&1
break
fi
done

if [ "$ipv6" == "" ] || [[ "$ipv6" =~ ^fe80.* ]]
then
die
fi

dns_server_info=`nslookup -query=AAAA $dnspod_ddnsipv6_name 2>&1`

dns_server_ipv6=`echo "$dns_server_info" | grep 'address ' | awk '{print $NF}'`
if [ "$dns_server_ipv6" = "" ]
then
dns_server_ipv6=`echo "$dns_server_info" | grep 'Address: ' | awk '{print $NF}'`
fi

if [ "$?" -eq "0" ]
then
echo "DNS server IP: $dns_server_ipv6" >&1

if [ "$ipv6" = "$dns_server_ipv6" ]
then
echo "The address is the same as the DNS server." >&1
fi
unset dnspod_ddnsipv6_record_id
else
dnspod_ddnsipv6_record_id="1"
fi

send_request() {
local type="$1"
local data="login_token=$dnspod_ddnsipv6_id,$dnspod_ddnsipv6_token&domain=$dnspod_ddnsipv6_domain&sub_domain=$dnspod_ddnsipv6_subdomain$2"
return_info=`curl -X POST "https://dnsapi.cn/$type" -d "$data" 2> /dev/null`
}

query_recordid() {
send_request "Record.List" ""
}

update_record() {
send_request "Record.Modify" "&record_type=AAAA&record_line=默认&ttl=$dnspod_ddnsipv6_ttl&value=$ipv6&record_id=$dnspod_ddnsipv6_record_id"
}

add_record() {
send_request "Record.Create" "&record_type=AAAA&record_line=默认&ttl=$dnspod_ddnsipv6_ttl&value=$ipv6"
}

if [ "$dnspod_ddnsipv6_record_id" = "" ]
then
echo "seem exists, try update." >&1
query_recordid
code=`echo $return_info | awk -F \"code\":\" '{print $2}' | awk -F \",\"message\" '{print $1}'`
echo "return code $code" >&1
if [ "$code" = "1" ]
then
dnspod_ddnsipv6_record_id=`echo $return_info | awk -F \"records\":.{\"id\":\" '{print $2}' | awk -F \",\"ttl\" '{print $1}'`
update_record
echo "update sucessful" >&1
else
echo "error code return, domain not exists, try add." >&1
add_record
echo "add sucessful." >&1
fi
else
echo "domain not exists, try add."
add_record
echo "add sucessful" >&1
fi
  1. 自动运行该动态解析脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
chmod +x /usr/local/bin/ddns.sh		# 首先赋予脚本执行权限

# 方法一:使用开机执行脚本来运行解析脚本,适合IP地址稳定或仅在开机时变动
systemctl status rc-local.service # 查看rc-local服务是否启动,需使其开机自启
# 在 /etc/rc.local 中exit 0之前添加如下一行执行命令,作用是开机等待拨号完成后再执行DDNS脚本
sleep 120 && /usr/local/bin/ddns.sh &>/dev/null

# 方法二:使用定时执行脚本来运行解析脚本
systemctl status cron.service # 查看crontab服务是否启动,需使其开机自启
crontab -e # -e 编辑当前用户时辰表,-l 列出当前用户时辰表,-r 删除当前用户时辰表

# 执行 crontab -e 后添加如下一行来每隔10分钟执行一次DDNS脚本并屏蔽输出日志
*/10 * * * * /usr/local/bin/ddns.sh &>/dev/null

* * * * *
- - - - -
| | | | |
| | | | +----- 星期中星期几 (0 - 6) (星期天 为0)
| | | +---------- 月份 (1 - 12)
| | +--------------- 一个月中的第几天 (1 - 31)
| +-------------------- 小时 (0 - 23)
+------------------------- 分钟 (0 - 59)
  1. 如果你的域名服务商为Cloudflare或Godaddy,那么也可试试【这个项目