家里的J4125小主机装了PVE,装了几个服务:黑群,HA,OpenWrt,等等。有时候需要在外访问,逐个安装DDNS服务显得不太现实,自己又是脚本小白,网络上搜索了许久,东拼西凑了一段代码,感觉挺稳定的。写出来给大佬们看看还有没有改进的地方。
首先的条件是:
一个OpenWrt路由系统,其它系统可以用脚本的应该也可以(想搬到RouterOS试试的,但好像RouterOS脚本不会搞)。OpenWrt会为每个客户端生成三个IPv6地址,三个都可以访问地址,一个是短地址,一个是根据网卡生成的地址,一个隐私地址,除了隐私地址外,前两个一般都不会改变,所以我用脚本获取前缀+固定后缀,通过cloud flare的API更新,实现多主机远程访问。
一个cloudflare账号
一个域名(Cloudflare的API不支持freenom的免费域名,我申请了一个免费的二级域名eu.org的,具体有教程可以搜索)
首先,将域名的nameservers改到cloud flare上,待生效后在DNS记录中添加一条AAAA记录。名称填自己喜欢的,IPv6可以先随意填写一个
等域名解析生效后,ssh登陆到OpenWrt执行下列命令区域ID,API全局密钥,可以从cloud flare账号中找到,分别填入后运行
curl -X GET "https://api.cloudflare.com/client/v4/zones/区域ID/dns_records?type=AAAA&name=ha.你的域名" \
-H "Content-Type:application/json" \
-H "X-Auth-Key:API全局密钥" \
-H "X-Auth-Email:cloudflare账号"
没有出错的话就会得到下列信息,需要的就是第一个DNS ID
然后在Cloudflare中生成一个编辑DNS令牌Token,这个Token只显示一次,记录下来。区域可以是所有区域,也可以针对的域名。
接写来就可以写脚本了。
#!/bin/sh -e
device=br-lan
file=$HOME/.cloudflare.addr6
[ -e $file ] && old=`cat $file`
if [ -z "$netmask" ]; then
netmask=128
fi
if [ -n "$device" ]; then
device="dev $device"
fi
address=$(ip -6 addr list scope global $device | grep -v " fd" | sed -n 's/.*inet6 \([0-9a-f:]\+\).*/\1/p' | head -n 1) #获取IPv6前缀
current=$address/$netmask
if [ "$old" = "$current" ]; then
echo -e "IPv6 address unchanged\n"
fi
# save current address
echo $current > $file
echo `date` $current >> ./ddns-runtime.txt
prefix=${current%%::*}
dev1="123" #短地址
dev2="211:1122:3344:5566" #长地址
address1=$prefix"::"$dev1 #短地址需要两个冒号
address2=$prefix":"$dev2
TOKEN="申请到的区域DNS Token"
ZONE_ID="区域ID"
DNS_ID1="通过前面API得到的DNS ID"
DNS_RECORD1="ha.你的域名"
DNS_ID2="通过前面API得到的DNS ID"
DNS_RECORD2="ab.你的域名" #根据需要添加需要的域名,重复操作得到DNS ID 就可以添加多个访问域名主机
ha=$(nslookup ha.你的域名 | grep -v " fd" | sed -n 's/.*Address 1: \([0-9a-f:]\+\).*/\1/p') #获取当前互连网的域名解析
ab=$(nslookup ab.你的域名 | grep -v " fd" | sed -n 's/.*Address 1: \([0-9a-f:]\+\).*/\1/p')
if [ "$ha" = "$address1" ]; then #条件判断,如果当前的地址与互连网解析一致则不运行更新
echo -e "op address unchanged\n"
elif [ "$op" != "$address1" ]; then #如果当前的地址与互连网解析不一致则通过cloud flare API更新
#send to cloudflare
curl -s \
-X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_ID1" \
-H "Content-Type:application/json" \
-H "Authorization: Bearer $TOKEN" \
--data '{"type":"AAAA","name":"'$DNS_RECORD1'","content":"'$address1'","ttl":1,"proxied":false}'
#output hostname and address
echo "hostname1="$DNS_RECORD1 "address1="$address1 >> ./ddns-runtime.txt #记录更新日志
echo -e "\ncomplete\n"
fi
if [ "$ab" = "$address2" ]; then
echo -e "ha address unchanged\n"
elif [ "$ha" != "$address2" ]; then
#send to cloudflare
curl -s \
-X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_ID2" \
-H "Content-Type:application/json" \
-H "Authorization: Bearer $TOKEN" \
--data '{"type":"AAAA","name":"'$DNS_RECORD2'","content":"'$address2'","ttl":1,"proxied":false}'
#output hostname and address
echo "hostname2="$DNS_RECORD2 "address2="$address2 >> ./ddns-runtime.txt
echo -e "\ncomplete\n"
fi
保存到路由器,定时运行,记得OpenWrt防火墙开放对应端口。
address部分,如果没有固定的后缀的,可以用下列的命令。但是我用着感觉好像地址更新不是实时的。有需要可以改下成如下代码
address1=$(ip -6 n | grep ^2.*00:11:22:33:44:55 | tail -n 1 | awk '{print $1}') #00:11:22:33:44:55改为机器的MAC地址
脚本不是很完美,有没有大佬可以出手完善一下,比如可以设置成监听网络接口,wan口更换了IP地址后就执行。还有多个主机用for循环来运行,节省代码。
|