Linux中获取本机的最新IPv6地址_更新ddns的脚本_获取openwrt的IP地址
转载注明来源: 本文链接 来自osnosn的博客,写于 2019-11-07.
运营商提供ipv6地址。
路由器后有台linux机器,通过eui64方式自动配置ipv6地址。
并配置防火墙,允许转发指定的ipv6连接。见【设置openwrt路由器的防火墙_允许从外网访问_ipv6服务】
不是eui64,需要改为eui64,见【Linux_ipv6_无状态_设置为_eui64_有状态ipv6更改后缀】
但是,运营商会定时强制路由器重拨,导致ipv6的前缀(prefix)变化。
虽然linux会马上自动配置新的ipv6地址。但旧的ipv6地址不会马上消失。
旧ipv6需要等超时expired后才删除,有时要等2000多秒(30多分钟)。
这段时间主机会有两个ipv6地址。如果不能正确找出新的ipv6地址去更新ddns,则这段时间无法访问主机。
通过查看 ip addr show 发现每个ip后面一行给出了expired时间。
新ip的expired时间总是比旧ip大。这样就可以找出最新的ipv6地址了。
如果你的机器中有很多网口,可以指定网口查看ip,如ip addr show eth0, ip addr show br0
以下是shell脚本,会显示出ipv4地址,和最新的ipv6(eui64)地址。
写法一: 逻辑清晰,不易出错,推荐。
#!/bin/sh
ip -o addr show|grep 'inet [^f:]'|sed -nr 's#.+? +inet ([0-9.]+)/[0-9]+ brd [0-9./]+ scope global .*#\1#p'
/bin/ip -o addr show |/bin/grep -v deprecated|/bin/grep ' inet6 [^f:]'|/bin/sed -nr 's#^.+? +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p'|/bin/grep 'ff:fe'|/usr/bin/sort -nr|/usr/bin/head -n1|/usr/bin/cut -d' ' -f2
显示ipv6的脚本执行步骤是,
- ip -o addr show 或 ip -o addr show XXX
- 去除 deprecated 地址
- 挑出inet6地址
- 把expired时间和ipv6地址,通过正则找出来。超时时间在前,ip在后。
- 过滤出eui64地址
- 根据时间的长短,反向排序
- 输出第一行
- 输出第二列(ip)
写法二: 稍微复杂。
#!/bin/sh
ip addr show|grep -A1 'inet [^f:]'|sed -nr 's#^ +inet ([0-9.]+)/[0-9]+ brd [0-9./]+ scope global .*#\1#p'
ip addr show|grep -v deprecated|grep -A1 'inet6 [^f:]'|grep -v ^--|sed -nr ':a;N;s#^ +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p;Ta'|grep 'ff:fe'|sort -nr|head -n1|cut -d' ' -f2
显示ipv6的脚本执行步骤是,
- ip addr show 或 ip addr show XXX
- 去除 deprecated 地址
- 挑出inet6地址,并同时显示下一行
- 去掉分组间隔 "--" (如果有的话)
- 把expired时间和ipv6地址,通过正则找出来,并显示在同一行。超时时间在前,ip在后。
- 过滤出eui64地址
- 根据时间的长短,反向排序
- 输出第一行
- 输出第二列(ip)
如果要把这个地址保存到变量,用来更新ddns,就这样写。
更新成功就不再更新。除非ip变化,或者超过24小时,才再次更新。
#!/bin/sh
hostname='myhostname.dynv6.net'
token='mytoken_mytoken'
service_name='ddns_myhostname'
##------------------
# ipv4='auto'
# ipv4=$(wget -4 --no-proxy -t3 -qO- https://ident.me) #获取自己的外网ipv4地址
# if [ -z "$ipv4" ];then
# ipv4=$(wget -4 --no-proxy -t3 -qO- http://www.pubyun.com/dyndns/getip)
# fi
ipv4=$(ip addr show|grep -A1 'inet [^f:]'|sed -nr 's#^ +inet ([0-9.]+)/[0-9]+ brd [0-9./]+ scope global .*#\1#p')
#ipv4=$(echo -n $ipv4|sed -e 's/^\s*//' -e 's/\s*$//g') #trim()
ipv6=$(/bin/ip -o addr show |/bin/grep -v deprecated|/bin/grep ' inet6 [^f:]'|/bin/sed -nr 's#^.+? +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p'|/bin/grep 'ff:fe'|/usr/bin/sort -nr|/usr/bin/head -n1|/usr/bin/cut -d' ' -f2)
#echo "my ipv6 is:" $ipv6
regex='^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$'
if [ "$ipv4" = 'auto' ];then
isipv4=1
else
isipv4=$(echo $ipv4 | egrep $regex | wc -l)
fi
if [ $isipv4 -eq 0 -o ${#ipv6} -lt 8 -o ${#ipv4} -gt 50 ];then
# 防止没有抓到IP地址,或抓取错误
echo 'ERROR'
exit
fi
updateurl='dynv6.com/api/update'
selfpath=$(/usr/bin/dirname $(/bin/readlink -f -- $0)) #脚本所在的目录
countfile=$selfpath/ipv6_count_${hostname}.stat #记录文件
if [ -f $countfile ]; then
read old_ipv4 old_ipv6 chg4_count chg6_count chg4_time chg6_time chg4_date chg6_date chg0 < $countfile
fi
old_ipv4=${old_ipv4:-'noipv4'}
old_ipv6=${old_ipv6:-'noipv6'}
chg4_count=${chg4_count:-'1'}
chg6_count=${chg6_count:-'1'}
chg4_time=${chg4_time:-'0'}
chg4_date=${chg4_date:-'none'}
chg6_time=${chg6_time:-'0'}
chg6_date=${chg6_date:-'none'}
if [ $ipv4 != $old_ipv4 ]; then #ipv4是否变化了
old_ipv4=$ipv4
chg4_count='1'
else
chg4_count=$(($chg4_count+1))
fi
if [ $ipv6 != $old_ipv6 ]; then #ipv6是否变化了
old_ipv6=$ipv6
chg6_count='1'
else
chg6_count=$(($chg6_count+1))
fi
now_time=$(/bin/date '+%s')
if [ $chg4_count -lt 9 ];then #变化后,只尝试更新9次
# 如果路由器有公网ipv4,可以让ddns根据来源ip自动检测
update4_res=$(wget -4 --no-proxy --no-check-certificate -q -O - 'https://${updateurl}?hostname=${hostname}&token=${token}&ipv4=auto')
exitcode=$?
if [ -n "$(echo $update4_res | grep 'nochg\|unchange\|updated\|good')" -a $chg4_count -gt 2 ]; then
chg4_count='10' #更新成功,就不再更新了
fi
chg4_time=${now_time}
chg4_date=$(/bin/date '+%F_%T%z_%w')
echo $(/bin/date '+%F_%T%z_%w_%a') v4 ${servce_name} "$update4_res" "$exitcode" >> ${countfile}.log
elif [ $(( now_time - chg4_time )) -gt $((24*3600+300)) ]; then
chg4_count='2' #约24小时后,再重新更新一次,有的ddns一天内有更新次数限制
fi
if [ $chg6_count -lt 9 ];then #变化后,只尝试更新9次
update6_res=$(wget --no-proxy --no-check-certificate -q -O - 'https://${updateurl}?hostname=${hostname}&token=${token}&ipv6='$ipv6)
exitcode=$?
if [ -n "$(echo $update6_res | grep 'nochg\|unchange\|updated\|good')" -a $chg6_count -gt 2 ]; then
chg6_count='10' #更新成功,就不再更新了
fi
chg6_time=${now_time}
chg6_date=$(/bin/date '+%F_%T%z_%w')
echo $(/bin/date '+%F_%T%z_%w_%a') v6 ${servce_name} "$update6_res" "$exitcode" >> ${countfile}.log
elif [ $(( now_time - chg6_time )) -gt $((24*3600+300)) ]; then
chg6_count='2' #约24小时后,再重新更新一次,有的ddns一天内有更新次数限制
fi
echo $old_ipv4 $old_ipv6 $chg4_count $chg6_count $chg4_time $chg6_time $chg4_date $chg6_date > $countfile #保存记录
实时查询ddns的IP,对比自身的IP,确定是否需要更新
需要 apt install dnsutils 或 yum install bind-utils 的支持。
#!/bin/sh
ddns='myhostname.dynv6.net' #你的 dynv6的动态域名
token='abcd....1234' #更新密钥
##获取自己的ipv4地址。
#ipv4_new=$(curl -x '' -4s "cip.cc") #方法1,获取 ipv4字符串
#ipv4_new=${ipv4_new##*/} #方法1,去掉最后一个"/"之前的所有字符,仅留下IP.
ipv4_new=$(curl -x '' -4s "http://ip.3322.net") #方法2,获取ipv4地址。
if [ -z "$ipv4_new" ];then
ipv4_new=$(curl -x '' -4s "http://www.pubyun.com/dyndns/getip")
fi
#ipv4_new=$(dig -4 +short myip.opendns.com a @resolver1.opendns.com) #方法3,获取ipv4地址。
##获取自己的ipv6地址。
ipv6_new=$(/bin/ip -o addr show |/bin/grep -v deprecated|/bin/grep ' inet6 [^f:]'|/bin/sed -nr 's#^.+? +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p'|/bin/grep 'ff:fe'|/usr/bin/sort -nr|/usr/bin/head -n1|/usr/bin/cut -d' ' -f2) #方法1,一定是eui64地址。
#ipv6_new=$(dig -6 +short myip.opendns.com aaaa @resolver1.opendns.com) #方法2,未必是eui64地址。
##查询实际的dns解析得到的ipv4
ipv4_old=$(dig +short $ddns a)
#ipv4_old=$(dig +short @114.114.114.114 $ddns a) #指定服务器查询ipv4
##查询实际的dns解析得到的ipv6
ipv6_old=$(dig +short $ddns aaaa)
#ipv6_old=$(dig +short @114.114.114.114 $ddns aaaa) #指定服务器查询ipv4
if [ $ipv4_new != $ipv4_old ]; then #如果不同,则更新
echo $(/bin/date '+%F_%T%z_%w_%a') update $ipv4_old '->' $ipv4_new
curl -sS -x '' -m10 --stderr - "https://dynv6.com/api/update?hostname=$ddns&token=$token&ipv4=$ipv4_new"
fi
if [ $ipv6_new != $ipv6_old ]; then #如果不同,则更新
echo $(/bin/date '+%F_%T%z_%w_%a') update $ipv6_old '->' $ipv6_new
curl -sS -x '' -m10 --stderr - "https://dynv6.com/api/update?hostname=$ddns&token=$token&ipv6=$ipv6_new"
fi
- 如果觉得系统中跑的定时任务太多,不想挤在一起,同时执行。
可以参考【Openwrt_Linux_crontab任务_顺序执行脚本】
python3 的脚本例子。
ip变化之后,更新10次,无论是否成功。10次后,就不再更新,除非IP变化。
#!/usr/bin/python3
# -*- coding: utf-8 -*- #
import urllib.request
import ssl
import subprocess
import re
def getIP():
#interface='eth0'
interface=''
output=subprocess.getoutput('/sbin/ip addr show '+interface+'|grep -v deprecated')
ipv4=re.findall(r' inet ([\d.]+)/(\d+) brd [\d./]+ scope global ',output,re.M|re.I)
ipv6=re.findall(r' inet6 ([^f:][\da-f:]+)/(\d+) scope global .+?\n.+? valid_lft (\d+)sec ',output,re.M|re.I)
# eui64的ipv6地址按超时时间排序,其他的排前面
def my_key(a):
if a[0].find('ff:fe')>4:
return int(a[2])
else:
return -1
ipv6.sort(key=my_key,reverse=True) #反向排序
#print('ipv4=',ipv4)
#print('ipv6=',ipv6)
return (ipv4,ipv6)
def updateddns(ipv4,ipv6):
context = ssl._create_unverified_context()
opener = urllib.request.build_opener(urllib.request.HTTPSHandler(context=context)) #不验证证书
header={
'Accept':'*/*',
'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
'Accept-Encoding':'none',
}
#host='https://dynv6.com/api/update?hostname=myhostname.dynv6.net&token=mytoken_mytoken&ipv4='+ipv4+'&ipv6='+ipv6
#如果路由器有公网ipv4,可以让ddns根据来源ip自动检测
host='https://ipv4.dynv6.com/api/update?hostname=myhostname.dynv6.net&token=mytoken_mytoken&ipv4=auto&ipv6='+ipv6
req=urllib.request.Request(host, b'',header)
content=opener.open(req, timeout=20)
print(content.read().decode('utf8'))
return True
if __name__=='__main__':
filename = 'ipv6_addr.txt'
if not os.path.isfile(filename):
old_addr = ['no ipv4','no ipv6','0']
else:
with open(filename,'r',encoding='utf8') as fp: #读取上次的记录
old_addr = fp.readlines()
for kk in range(len(old_addr)):
old_addr[kk] = old_addr[kk].strip()
ipv4,ipv6=getIP()
if old_addr[0] != ipv4[0][0] or old_addr[1] != ipv6[0][0]: #IP是否变化
old_addr[0] = ipv4[0][0]
old_addr[1] = ipv6[0][0]
old_addr[2] = '1'
else:
old_addr[2] = str(1+int(old_addr[2]))
with open('ipv6_addr.txt','w') as fp: #保存IP,计数
fp.write('\n'.join(old_addr)+'\n')
if int(old_addr[2]) < 10: #ip变化之后,只更新10次
updateddns(ipv4[0][0],ipv6[0][0])
这个是OpenWRT路由器中的lua脚本。
如果你的路由器是OpenWRT,可以用这个脚本直接跑在路由器中。
方法1: 逻辑清晰,过滤严格,找出最新的IP。
- 这个脚本获取的是路由器本身WAN口的ipv4和ipv6(非eui64).
- 有些什么接口。用命令
ip address查看。
#!/bin/sh ip -o addr show pppoe-wan|grep 'inet [^f:]'|sed -nr 's#.+? +inet ([0-9.]+)/[0-9]+ brd [0-9./]+ scope global .*#\1#p' ip -o addr show pppoe-wan|grep -v deprecated|grep ' inet6 [^f:]'|sed -nr 's#^.+? +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p'|grep 'ff:fe'|sort -nr|head -n1|cut -d' ' -f2 ## 或者 ## ip addr show pppoe-wan|grep -A1 'inet [^f:]'|sed -nr 's#^ +inet ([0-9.]+)/[0-9]+ brd [0-9./]+ scope global .*#\1#p' ip addr show pppoe-wan|grep -v deprecated|grep -A1 'inet6 [^f:]'|grep -v ^--|sed -nr ':a;N;s#^ +inet6 ([a-f0-9:]+)/.+? scope global .*? valid_lft ([0-9]+sec) .*#\2 \1#p;Ta'|grep 'ff:fe'|sort -nr|head -n1|cut -d' ' -f2 - 有些什么接口。用命令
方法2: 逻辑清晰。op的WAN口一般只有一个IP。
- 这个脚本获取的是路由器本身WAN口的ipv4和ipv6(非eui64).
- 有些什么接口。用命令
ip address查看。
#!/usr/bin/lua -- 此脚本执行一次就更新一次. require("luci.sys") local a=luci.sys.exec('ip addr show pppoe-wan') local ipv4=string.match(a," inet ([%d%.]+) peer ") local ipv6=string.match(a," inet6 ([%a%d:]+)/[0-9]+ scope global ") -- lua的注释为两个减号 --print(ipv4,ipv6) cc=luci.sys.exec("wget --no-check-certificate -q -O - 'https://dynv6.com/api/update?hostname=myhostname.dynv6.net&token=mytoken_mytoken&ipv4="..ipv4.."&ipv6="..ipv6.."'") - 有些什么接口。用命令
方法3: 逻辑简单,推荐。
- openWRT 中还有个ifstatus命令,如
ifstatus lan,ifstatus wan,ifstatus wan_6会返回对应网口的json数据。- 有些什么接口。用命令
ubus list network.interface.*查看。 - 有
"ipv4-address":[{"address":"...","ptpaddress":"...","mask":32}]
"route":[{"nexthop":"..."}],"dns-server":["...","..."] - 有
"ipv6-address":[{"address":"...","mask":64}],"ipv6-prefix":[{"address":"...","mask":56}]
"route":[{"target":"::","nexthop":"..."},{..},...],"dns-server":["...","..."]
如果wan口没有获取到ipv6地址,"ipv6-address" 这个key不存在。
#!/usr/bin/lua -- example,例子. 此脚本执行一次,就输出一次 ipv4和 ipv6地址. require("luci.sys") require("luci.jsonc") local aa=luci.sys.exec("ifstatus wan") --执行外部命令,获取json文本 local bb=luci.jsonc.parse(aa) --解析json,变成多层数组 ipv4=bb["ipv4-address"][1]["address"] -- 100.64.xx.xx WAN ipv4 aa=luci.sys.exec("ifstatus wan_6") --执行外部命令,获取json文本 bb=luci.jsonc.parse(aa) --解析json,变成多层数组 ipv6=bb["ipv6-address"][1]["address"] -- 240e:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx WAN ipv6 ipv6pre=bb["ipv6-prefix"][1]["address"] -- 240e:xxx:xxx:xxxx:: if (ipv6pre ~= nil) then print(ipv6pre.."/"..bb["ipv6-prefix"][1]["mask"]) -- 输出 240e:xxx:xxx:xxxx::/56 ipv6前缀 -- 有了ipv6的prefix, 直接拼接客户机的eui64后缀, 就可以去更新ddns了。比如后缀为 1234:12ff:fe34:1234 ipv6=string.sub(ipv6pre,1,-2).."1234:12ff:fe34:1234" -- 240e:xxx:xxx:xxxx:1234:12ff:fe34:1234 cc=luci.sys.exec("wget --no-check-certificate -q -O - 'https://dynv6.com/api/update?hostname=myhostname.dynv6.net&token=mytoken_mytoken&ipv4="..ipv4.."&ipv6="..ipv6.."'") end - 有些什么接口。用命令
用openWRT中的ddns应用,为内网机器更新ipv6域名
安装ddns应用,opkg install luci-app-ddns(英文界面)
op-21.02, op-22.03 可以装luci-i18n-ddns-en(英文) 或者 luci-i18n-ddns-zh-cn(中文)
op-23.05, op24.10 可以装luci-app-ddns(英文) 或者 luci-i18n-ddns-zh-cn(中文)

- 如果只是为 OpenWRT本身设置 DDNS,按后两张图设置即可,无需脚本。
- 如果要为内网的机器设置 IPv6 的 DDNS,则使用第一张图,使用下面的脚本配合。
- 根据
ubus list network.interface.*看看有些什么接口。比如wan_6,vwan1_6之类的。用于下面的脚本。 - 脚本内容 getMY_ipv6.lua 如下,记得要
chmod +x getMY_ipv6.lua设置脚本执行权限。 - op的 ddns应用中添加的"脚本",要写"绝对路径",全路径。如:
/root/getMY_ipv6.lua
接口名称: 可能是#!/usr/bin/lua require("luci.sys") require("luci.jsonc") -- 看看有些什么接口名称 -- print(luci.sys.exec("ubus list network.interface.*")) aa=luci.sys.exec("ifstatus wan_6") --执行外部命令,获取json文本 bb=luci.jsonc.parse(aa) --解析json,变成多层数组 -- 这个5205:a2ff:fe34:5678就是内网机器 eui64的 ipv6后缀,自己按需修改 print(string.sub(bb["ipv6-prefix"][1]["address"],1,-2).."5205:a2ff:fe34:5678") --通过数组获取前缀,去掉最后一个字符,拼接eui64后缀,并打印 -- 这个是路由器自身的ipv6地址。 -- print(bb["ipv6-address"][1]["address"]) --直接通过数组获得,并打印wan_6,wan1_6,vwan_6,vwan1_6, - 如果你配置了很多个ddns,为了不要集中在同一秒更新,可以给lua脚本加个延时,见【openwrt中随机sleep】
- 关于luci api 的文档【luci api Reference】。
openwrt中用于ddns更新的lua脚本
- 脚本独立运行。可以加入"计划任务"。
比如加入 crontab每10min执行*/10 * * * * /usr/bin/lua /root/ddns脚本.lua - dedyn 的ddns更新。(备忘,参考,202507)
IP如果变化,更新3次。 每24小时强制更新。#!/usr/bin/lua require("luci.sys") require("luci.jsonc") require("nixio") local aa=luci.sys.exec("/sbin/ifstatus wan") local bb=luci.jsonc.parse(aa) ipv4=bb["ipv4-address"][1]["address"] -- 100.64.xx.xx WAN口的ipv4 aa=luci.sys.exec("/sbin/ifstatus wan_6") bb=luci.jsonc.parse(aa) ipv6=bb["ipv6-address"][1]["address"] -- 240e:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx WAN口的ipv6 ipv6pre=string.sub(bb["ipv6-prefix"][1]["address"],1,-2) -- ipv6pre --ipv6=string.sub(ipv6pre,1,-2).."2020:12ff:fe34:5678" --mac 22:20:12:34:56:78 --print(bb["ipv6-prefix"][1]["address"].."/"..bb["ipv6-prefix"][1]["mask"]) -- 240e:xxx:xxx:xxxx::/56 ipv6 prefix function updateDDNS(hostname,param) --dedyn local token="abc---token------def" local buf="/usr/bin/curl -sS -x '' -m10 --stderr - --user "..hostname..":"..token.." 'https://update.dedyn.io/?"..param.."'" local cc=luci.sys.exec(buf) local result=cc --"Request was throttled. Expected available in 56 seconds." "good" local pos1,pos2=cc:find("Expected available in ") --Is limited? if pos1 then local sec=cc:match("Expected available in (%d+) seconds") nixio.poll({},(tonumber(sec)+1)*1000) -- sec+1秒的sleep cc=luci.sys.exec(buf) result=result..'|'..cc end return result end local selfpath=debug.getinfo(1,'S').source:sub(2):match('^.*/') --本脚本所在的目录 ddns_stat={ip4addr='',ip4count=1,ip4time=0, ip6addr='',ip6count=1,ip6time=0} --init default value local fp=nixio.open(selfpath.."/myddns.dedyn.io.stat","r") if fp then fp:lock('lock') local buf=fp:read(1024) fp:lock('ulock') fp:close() ddns_stat=luci.jsonc.parse(buf) end if (ipv4 ~= nil) then domain='myroute4.dedyn.io' --local aa=nixio.getaddrinfo(domain,'inet'); if aa ~= nil then oldip4=aa[1]['address'] end --openwrt的dns缓存要2小时才更新 --223.5.5.5 在更新IP后2小时内解析结果未更新; 8-12小时内,解析结果会有反复(2025-07); 可以考虑使用114.114.114.114 或 ns1.desec.io local aa=luci.sys.exec("nslookup -type=A "..domain.." 114.114.114.114") oldip4=aa:match("Address: ([%d.]+)") --if not nil --oldip4=ddns_stat['ip4addr'] --不解析,比对上次的值 local need_update=false if (oldip4~=nil and oldip4 ~= ipv4) or os.time()-ddns_stat['ip4time']>24*3600 then need_update=true end if need_update or ddns_stat['ip4count']<3 then local cc=updateDDNS(domain,'myipv6=preserve&myipv4='..ipv4) if need_update then ddns_stat['ip4count']=1 elseif string.sub(cc,-4)=='good' or string.sub(cc,-5)=='nochg' then --endswith ddns_stat['ip4count']=ddns_stat['ip4count']+1 end ddns_stat['ip4result']=cc ddns_stat['ip4addr']=ipv4 ddns_stat['ip4time']=os.time() ddns_stat['ip4date']=os.date("%Y-%m-%d_%H:%M:%S_%w") print(string.format("%s, %s, %s=>%s, %s, %d, %s",os.date("%Y-%m-%d_%H:%M:%S_%w"),domain,tostring(oldip4),ipv4,tostring(need_update),ddns_stat['ip4count'],cc)) --log else ddns_stat['ip4count']=ddns_stat['ip4count']+1 end end if (oldip4==nil or ipv4 == nil) then print(string.format("%s, %s, %s=>%s",os.date("%Y-%m-%d_%H:%M:%S_%w"),domain,tostring(oldip4),tostring(ipv4))) --log end if ddns_stat['ip4count']<=3 then -- dedyn的ip更新,限制 2次/2min ,202507. local ms=1000*61 --61sec --nixio.poll({},ms) -- 61秒的sleep; 暂不sleep. end if (ipv6 ~= nil) then domain='myroute6.dedyn.io' --local aa=nixio.getaddrinfo(domain,'inet6'); if aa ~= nil then oldip6=aa[1]['address'] end --openwrt DNS cache 2hour. local aa=luci.sys.exec("nslookup -type=AAAA "..domain.." 114.114.114.114") oldip6=aa:match("Address: ([%da-f:]+)") --if not nil --oldip6=ddns_stat['ip6addr'] --不解析,比对上次的值 local need_update=false if (oldip6~=nil and oldip6 ~= ipv6) or os.time()-ddns_stat['ip6time']>24*3600 then need_update=true end if need_update or ddns_stat['ip6count']<3 then local cc=updateDDNS(domain,'myipv4=preserve&myipv6='..ipv6) if need_update then ddns_stat['ip6count']=1 elseif string.sub(cc,-4)=='good' or string.sub(cc,-5)=='nochg' then --endswith ddns_stat['ip6count']=ddns_stat['ip6count']+1 end ddns_stat['ip6result']=cc ddns_stat['ip6addr']=ipv6 ddns_stat['ip6time']=os.time() ddns_stat['ip6date']=os.date("%Y-%m-%d_%H:%M:%S_%w") print(string.format("%s, %s, %s=>%s, %s, %d, %s",os.date("%Y-%m-%d_%H:%M:%S_%w"),domain,tostring(oldip6),ipv6,tostring(need_update),ddns_stat['ip6count'],cc)) --log else ddns_stat['ip6count']=ddns_stat['ip6count']+1 end end if (oldip6==nil or ipv6 == nil) then print(string.format("%s, %s, %s=>%s",os.date("%Y-%m-%d_%H:%M:%S_%w"),domain,tostring(oldip6),tostring(ipv6))) --log end local fp=nixio.open(selfpath.."/myddns.dedyn.io.stat","w") fp:lock('lock') local buf=fp:write(luci.jsonc.stringify(ddns_stat,true).."\n") fp:lock('ulock') fp:close() --os.exit() - 针对 dynv6 的ddns更新的lua函数,lua脚本片段。
function updateDDNS(hostname,param) --v6.rocks local token="token-----abcdefg" local buf="/usr/bin/curl -sS -x '' -m10 --stderr - 'https://dynv6.com/api/update?hostname="..hostname.."&token="..token.."&"..param.."'" local cc=luci.sys.exec(buf) local result=cc --"addresses updated" "addresses unchanged" return result end domain='xxxx.v6.rocks' local cc=updateDDNS(domain,'ipv4='..ipv4) local cc=updateDDNS(domain,'ipv6='..ipv6) if string.sub(cc,-7)=='updated' or string.sub(cc,-9)=='unchanged' then --endswith print('update ok') end
---end---
转载注明来源: 本文链接 https://www.cnblogs.com/osnosn/p/11813096.html 来自osnosn的博客

浙公网安备 33010602011771号