欢迎光临
我们一直在努力

openwrt 原生动态DNS(DDNS) 支持DnsPod解析

官方的动态DNS(DDNS)里面没有支持dnspod ddns自动更新ip

之前一直使用脚本操作,参考:

https://www.haiyun.me/archives/1305.html

http://www.cloudchou.com/work/post-984.html

https://zhuanlan.zhihu.com/p/20629213

由于openwrt使用的是脚本所以每次更新openwrt或者openwrt恢复出厂设置脚本文件都会没有了,本人又喜欢折腾路由器.所以就想着自己修改一个插件来实现这个功能

软件包我已经打包编译好了
opwnwrt x86 ddns-scripts_dnspod

使用方法:

保存运用即可

如果觉得软件包不安全你也可以使用一下代码自己编译或者直接使用手动的方式自己吧各文件修改了.

代码如下:

添加文件"/usr/lib/ddns/update_dnspod_cn.sh"

#!/bin/sh

# 检查传入参数
[ -z "$username" ] && write_log 14 "Configuration error! [User name] cannot be empty"
[ -z "$password" ] && write_log 14 "Configuration error! [Password] cannot be empty"

# 检查外部调用工具
[ -n "$CURL_SSL" ] || write_log 13 "Dnspod communication require cURL with SSL support. Please install"
[ -n "$CURL_PROXY" ] || write_log 13 "cURL: libcurl compiled without Proxy support"

# 变量声明
local __URLBASE __HOST __DOMAIN __TYPE __CMDBASE __POST __POST1 __RECIP __RECID __TTL
__URLBASE="https://dnsapi.cn"

# 从 $domain 分离主机和域名
[ "${domain:0:2}" = "@." ] && domain="${domain/./}" # 主域名处理
[ "$domain" = "${domain/@/}" ] && domain="${domain/./@}" # 未找到分隔符,兼容常用域名格式
__HOST="${domain%%@*}"
__DOMAIN="${domain#*@}"
[ -z "$__HOST" -o "$__HOST" = "$__DOMAIN" ] && __HOST=@

# 设置记录类型
[ $use_ipv6 = 0 ] && __TYPE=A || __TYPE=AAAA

# 构造基本通信命令
build_command(){
	__CMDBASE="$CURL -Ss"
	# 绑定用于通信的主机/IP
	if [ -n "$bind_network" ];then
		local __DEVICE
		network_get_physdev __DEVICE $bind_network || write_log 13 "Can not detect local device using 'network_get_physdev $bind_network' - Error: '$?'"
		write_log 7 "Force communication via device '$__DEVICE'"
		__CMDBASE="$__CMDBASE --interface $__DEVICE"
	fi
	# 强制设定IP版本
	if [ $force_ipversion = 1 ];then
		[ $use_ipv6 = 0 ] && __CMDBASE="$__CMDBASE -4" || __CMDBASE="$__CMDBASE -6"
	fi
	# 设置CA证书参数
	if [ $use_https = 1 ];then
		if [ "$cacert" = IGNORE ];then
			__CMDBASE="$__CMDBASE --insecure"
		elif [ -f "$cacert" ];then
			__CMDBASE="$__CMDBASE --cacert $cacert"
		elif [ -d "$cacert" ];then
			__CMDBASE="$__CMDBASE --capath $cacert"
		elif [ -n "$cacert" ];then
			write_log 14 "No valid certificate(s) found at '$cacert' for HTTPS communication"
		fi
	fi
	# 如果没有设置,禁用代理 (这可能是 .wgetrc 或环境设置错误)
	[ -z "$proxy" ] && __CMDBASE="$__CMDBASE --noproxy '*'"
	__CMDBASE="$__CMDBASE -d"
}

# 用于Dnspod API的通信函数
dnspod_transfer(){
	__CNT=0
	case "$1" in
		0)__A="$__CMDBASE '$__POST' $__URLBASE/Record.List";;
		1)__A="$__CMDBASE '$__POST1' $__URLBASE/Record.Create";;
		2)__A="$__CMDBASE '$__POST1&record_id=$__RECID&ttl=$__TTL' $__URLBASE/Record.Modify";;
	esac

	write_log 7 "#> $__A"
	while ! __TMP=`eval $__A 2>&1`;do
		write_log 3 "[$__TMP]"
		if [ $VERBOSE -gt 1 ];then
			write_log 4 "Transfer failed - detailed mode: $VERBOSE - Do not try again after an error"
			return 1
		fi
		__CNT=$(( $__CNT + 1 ))
		[ $retry_count -gt 0 -a $__CNT -gt $retry_count ] && write_log 14 "Transfer failed after $retry_count retries"
		write_log 4 "Transfer failed - $__CNT Try again in $RETRY_SECONDS seconds"
		sleep $RETRY_SECONDS &
		PID_SLEEP=$!
		wait $PID_SLEEP
		PID_SLEEP=0
	done
	__ERR=`jsonfilter -s "$__TMP" -e "@.status.code"`
	[ $__ERR = 1 ] && return 0
	[ $__ERR = 10 ] && [ $1 = 0 ] && return 0
	__TMP=`jsonfilter -s "$__TMP" -e "@.status.message"`
	local A="$(date +%H%M%S) ERROR : [$__TMP] - 终止进程"
	logger -p user.err -t ddns-scripts[$$] $SECTION_ID: ${A:15}
	printf "%s\n" " $A" >> $LOGFILE
	exit 1
}

# 添加解析记录
add_domain(){
	dnspod_transfer 1
	printf "%s\n" " $(date +%H%M%S)       : 添加解析记录成功: [$([ "$__HOST" = @ ] || echo $__HOST.)$__DOMAIN],[IP:$__IP]" >> $LOGFILE
	return 0
}

# 修改解析记录
update_domain(){
	dnspod_transfer 2
	printf "%s\n" " $(date +%H%M%S)       : 修改解析记录成功: [$([ "$__HOST" = @ ] || echo $__HOST.)$__DOMAIN],[IP:$__IP],[TTL:$__TTL]" >> $LOGFILE
	return 0
}

# 获取域名解析记录
describe_domain(){
	ret=0
	__POST="login_token=$username,$password&format=json&domain=$__DOMAIN&sub_domain=$__HOST"
	__POST1="$__POST&value=$__IP&record_type=$__TYPE&record_line_id=0"
	dnspod_transfer 0
	__TMP=`jsonfilter -s "$__TMP" -e "@.records[@.type='$__TYPE' && @.line_id='0']"`
	if [ -z "$__TMP" ];then
		printf "%s\n" " $(date +%H%M%S)       : 解析记录不存在: [$([ "$__HOST" = @ ] || echo $__HOST.)$__DOMAIN]" >> $LOGFILE
		ret=1
	else
		__RECIP=`jsonfilter -s "$__TMP" -e "@.value"`
		if [ "$__RECIP" != "$__IP" ];then
			__RECID=`jsonfilter -s "$__TMP" -e "@.id"`
			__TTL=`jsonfilter -s "$__TMP" -e "@.ttl"`
			printf "%s\n" " $(date +%H%M%S)       : 解析记录需要更新: [解析记录IP:$__RECIP] [本地IP:$__IP]" >> $LOGFILE
			ret=2
		fi
	fi
}

build_command
describe_domain
if [ $ret = 1 ];then
	sleep 3
	add_domain
elif [ $ret = 2 ];then
	sleep 3
	update_domain
else
	printf "%s\n" " $(date +%H%M%S)       : 解析记录不需要更新: [解析记录IP:$__RECIP] [本地IP:$__IP]" >> $LOGFILE
fi

return 0

编辑文件"/etc/ddns/services"添加以下内容:

"dnspod.com" "/usr/lib/ddns/update_dnspod_cn.sh"

编辑文件"/etc/ddns/services_ipv6"

"dnspod.com" "/usr/lib/ddns/update_dnspod_cn.sh"

添加完之后你就可以在openwrt后台添加你的dnspod 域名解析了.

觉得麻烦的可以直接使用软件包安装代码都是一样的.

源码下载:https://git.nixonli.com/nixon/ddns-scripts_dnspod.git

大神勿喷哈代码都是我在网上找的跟着自己的思路修改拼凑的.有什么问题可以给我留言交流.谢谢

---------------------------------------------------------------------------

2019年10月1日

更新了脚本返回错误代码!

2020年2月17日

今天更新L大的LEDE源码时发现源码中已经集成了该插件源码(https://github.com/coolsnowwolf/lede/tree/master/package/lean/ddns-scripts_dnspod),并且做了优化集成了.cn和.com的脚本维护者是:Small_5

赞(1) 打赏
文章名称:《openwrt 原生动态DNS(DDNS) 支持DnsPod解析》
文章链接:https://www.nixonli.com/23133.html
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
窗外天空


关注公众号『窗外天空』

获取更多资源!
互联网、前沿技术......

评论 15

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    113732 : 获得解析记录ID:[4642****], 类型: ID
    113732 : 地址需要修改,本地地址:[140.*.*.*]
    113735 WARN : 修改解析记录host:[h],type:[A],ip:[140.*.*.*]失败! - TERMINATE
    113735 WARN : PID '9500' exit WITH ERROR '1' at 2019-09-27 11:37

    〃灯火○阑°珊下丶2年前 (2019-09-27)Reply
    • 你直接安装的我提供的软件包还是自己修改添加或者编译的?

      nixon li2年前 (2019-09-27)Reply
  2. #2

    IP地址来源 我选择的是URL

    〃灯火○阑°珊下丶2年前 (2019-09-27)Reply
    • 如果你使用的是我提供编译好的x86的包可能是我之前的脚本有问题,现在我已经跟新了软件包你再试一下。

      nixon li2年前 (2019-09-27)Reply
      • 我是用的你编译好的,好像还是有问题,一点启动,过一会同样的错误,然后自动关闭了!

        〃灯火○阑°珊下丶2年前 (2019-09-27)Reply
        • 你的openwrt版本是多少,这给的信息太少无法判断具体的问题。
          等我修改一下脚本把返回消息写入日志看看集体情况。

          nixon li2年前 (2019-09-27)Reply
          • Powered by LuCI Master (git-19.268.50099-562a894) / OpenWrt R9.10.1
            Fri Sep 27 16:27:40 2019 user.notice ddns-scripts[14648]: myddns_ipv6: PID '14648' started at 2019-09-27 16:27
            Fri Sep 27 16:27:40 2019 user.notice ddns-scripts[14647]: myddns_ipv4: PID '14647' started at 2019-09-27 16:27
            Fri Sep 27 16:27:41 2019 user.warn ddns-scripts[14647]: myddns_ipv4: Service section disabled! - TERMINATE
            Fri Sep 27 16:27:41 2019 user.warn ddns-scripts[14647]: myddns_ipv4: PID '14647' exit WITH ERROR '1' at 2019-09-27 16:27
            Fri Sep 27 16:27:41 2019 user.warn ddns-scripts[14648]: myddns_ipv6: Service section disabled! - TERMINATE
            Fri Sep 27 16:27:41 2019 user.warn ddns-scripts[14648]: myddns_ipv6: PID '14648' exit WITH ERROR '1' at 2019-09-27 16:27
            Fri Sep 27 16:28:05 2019 authpriv.info dropbear[17221]: Child connection from 192.168.88.205:63339
            Fri Sep 27 16:28:05 2019 authpriv.notice dropbear[17221]: Password auth succeeded for 'root' from 192.168.88.205:63339
            Fri Sep 27 16:32:14 2019 user.notice ddns-scripts[19688]: DNSPOD: PID '19688' started at 2019-09-27 16:32
            Fri Sep 27 16:32:19 2019 daemon.err uhttpd[1944]: sh: write error: Broken pipe
            Fri Sep 27 16:32:19 2019 user.warn ddns-scripts[19688]: DNSPOD: 修改解析记录host:[h],type:[A],ip:[140.*.*.*]失败! - TERMINATE
            Fri Sep 27 16:32:19 2019 user.warn ddns-scripts[19688]: DNSPOD: PID '19688' exit WITH ERROR '1' at 2019-09-27 16:32

            〃灯火○阑°珊下丶2年前 (2019-09-27)
        • 还有你的ddns的版本是多少?我写脚本的ddns版本是: 2.7.8-1

          nixon li2年前 (2019-09-27)Reply
          • ddns-scripts 2.7.8-1
            ddns-scripts_aliyun 1.0.0-2
            ddns-scripts_dnspod 1.0-2
            luci-app-ddns 2.4.9-3
            luci-i18n-ddns-zh-cn 2.4.9-3
            是不是 IP 地址来源 [IPv4]不能通过URL获取的IP来推送?

            〃灯火○阑°珊下丶2年前 (2019-09-27)
          • 可以使用URL来获取IP的,我看你的日志IP已经拿到了,是通过API给到dnspod的服务器时出了问题。
            你使用ddns的默认设置只修改 [IP 地址来源 [IPv4]]为URL看看。
            我这边只修改了服务提供商跟ip地址来源是能正常使用的。

            nixon li2年前 (2019-09-27)
          • 这样进程是不会退出,但是是内网IP不推送
            171341 : verbose mode : 0 - run normal, NO console output
            171341 : check interval: 600 seconds
            171342 : force interval: 259200 seconds
            171342 : retry interval: 60 seconds
            171342 : retry counter : 0 times
            171342 : No old process
            171342 : last update: never
            171342 : Detect registered/public IP
            171342 : #> /usr/bin/nslookup h.jw8013.cn >/var/run/ddns/DNSPOD.dat 2>/var/run/ddns/DNSPOD.err
            171342 : Registered IP '2.3.3.3' detected
            171342 info : Starting main loop at 2019-09-27 17:13
            171342 : Detect local IP on 'interface'
            171342 : #> ip -o addr show dev br-lan scope global >/var/run/ddns/DNSPOD.dat 2>/var/run/ddns/DNSPOD.err
            171342 : Local IP '192.168.88.215' detected on interface 'br-lan'
            171342 : Update needed - L: '192.168.88.215' R: '2.3.3.3'
            171342 ERROR : No or private or invalid IP '192.168.88.215' given! Please check your configuration
            171342 ERROR : No update send to DDNS Provider
            171342 : Waiting 600 seconds (Check Interval)

            〃灯火○阑°珊下丶2年前 (2019-09-27)
  3. #3

    你的购买了解析套餐?脚本里面TTL时间为120。。。
    我把它改成600 OK了。。。

    〃灯火○阑°珊下丶2年前 (2019-09-29)Reply
    • 非常感谢你的反馈。我也没有购买解析套餐用的都是免费的解析,我的是很久之前的账号了,我也不清楚为什么我的可以。
      你可以把脚本里的“&ttl=120”这一段代码删掉就可以了,默认就是ttl=600。我会把脚本修改一下重新制作软件包。

      nixon li2年前 (2019-09-29)Reply
  4. #4

    同一域名有多个记录的时候会出错。
    比如 abc.com同时有A记录和AAAA记录的时候,会导致类型不匹配而出错。

    describe_domain() {
    DATFILE=`curl -s -d "login_token=$username,$password&format=json&domain=$__DOMAIN" "https://dnsapi.cn/Record.List"`
    value=`jsonfilter -s "$DATFILE" -e "@.records[@.name='$__HOST'].name"`
    if [ "$value" == "" ]; then
    write_log 7 "解析记录:[$__HOST]不存在,类型: HOST"
    ret=1
    else
    value=`jsonfilter -s "$DATFILE" -e "@.records[@.name='$__HOST'&&@.type='$__TYPE'].type"`
    if [ "$value" != "$__TYPE" ]; then
    write_log 7 "当前解析类型:[$__TYPE], 获得不匹配类型: TYPE. value is $value."
    ret=2; continue
    else
    __RECID=`jsonfilter -s "$DATFILE" -e "@.records[@.name='$__HOST'&&@.type='$__TYPE'].id"`
    write_log 7 "获得解析记录ID:[$__RECID], 类型: ID"
    __RECIP=`jsonfilter -s "$DATFILE" -e "@.records[@.name='$__HOST'&&@.type='$__TYPE'].value"`
    if [ "$__RECIP" != "${__IP}" ]; then
    write_log 7 "地址需要修改,本地地址:[${__IP}]"
    ret=2
    fi
    fi
    fi
    return $ret
    }

    dalin2年前 (2019-11-26)Reply
    • 抱歉,一直没时间登录网站查看,我由于没有ipv6的网络所以没有测试,如果你需要我们可以一起把他优化一些。

      nixon li2年前 (2019-12-16)Reply

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏