天狼晓月 发表于 2018-8-17 16:22:14

EdgeRouter 配置 dnspod 动态域名更新

作者:mostone

测试路由器:UBNT EdgeRouter ER-X

路由器系统:EdgeRouter X v1.9.1.1

使用 Shell 脚本,配置为 pppoe 建立连接后被调用。

系统的 /etc/ppp/ip-up 脚本,会在 pppoe 连接建立后执行,并搜索 /config/scripts/ppp/ip-up.d/ 目录,执行目录下的所有脚本文件。

其中 /config/scripts 是路由器默认的配置目录,如果更新路由器固件,并不会删除其中的文件。

这款路由器支持 ssh 远程登录,可以使用 sftp 上传文件,放到 /config/scripts/ppp/ip-up.d/ 目录下即可,如果目录不存在,先建立目录层级。

脚本文件以下面方式运行(脚本文件名可以任意更改):

(注:在使用之前,需要修改文件,设置正确的 ACCESS_TOKEN。参考:https://support.dnspod.cn/Kb/showarticle/tsid/227/)

1.$> /config/scripts/ppp/ip-up.d/ddnspod.sh -q mydomain.com www

    这用来查询 mydomain.com 在平台上的 domainId, www 的 recordId

2. $> /config/scripts/ppp/ip-up.d/ddnspod.sh --test 1111 2222 www 0 10.1.1.1

    这用来提交测试的 IP 地址, 1111 为上面取得的 domainId,2222 为上面取得的 recordId,www 为子域名(可以用 @ 来更新主域名),0 为 record_line_id,最后是要提交的新 IP 地址。

    record_line_id,如果是默认线路,值为 0,更多的可选值请参考:https://www.dnspod.cn/docs/domains.html#record-line

"line_ids": {
      "默认": 0,
      "国内": "7=0",
      "国外": "3=0",
      "电信": "10=0",
      "联通": "10=1",
      "教育网": "10=2",
      "移动": "10=3",
      "百度": "90=0",
      "谷歌": "90=1",
      "搜搜": "90=4",
      "有道": "90=2",
      "必应": "90=3",
      "搜狗": "90=5",
      "奇虎": "90=6",
      "搜索引擎": "80=0"
    }    提交的线路 id 值应该与你的设置保持一致。
    如果 id 值中含有等号,请将 '=' 换成 '%3D',进行转义,如 "7%3D0"

3. 路由器重新建立 pppoe 连接时,自动被调用执行

    这种方式使用,需要修改文件的最后一行,设置由上面第一种方式取得的 domainId 和 recordId,如果有多个域名要更新,复制为多行,并修改相应的 domainId, recordId 即可。

    可以在 /var/log/ppp.log 中查看最后一次记录消息

ddnspod-ubnt.sh 代码:

#!/bin/sh
#################################################
# MosDdns for EdgeRouter X v1.0
# Dynamic DNS using DNSPod API
# Original by mostone<mostone@hotmail.com>, http://www.anrip.com/ddnspod
# Tested on EdgeRouter X v1.9.1.1
#################################################

# Usage:
#step 1. Set accessToken value at bellow.
#step 2. Input command in Shell: ddnspod-ubnt.sh -p domainName subdomainName
#            this command will print domainId and recordId.
#step 3. Add updateDdns function call in the last of this file, replace your
#            real domainId and recordId which get from step 1.
#step 4. copy this shell script file to ubnt router.
#            path: /config/scripts/ppp/ip-up.d/
#            this file will be call by /etc/ppp/ip-up.
#
#Done.


# Global Variables:
# Combine your token Id and token together as follows
ACCESS_TOKEN="11111,exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx4"

IS_PPP_UP=1
if [ -z $PPP_LOCAL ]; then
      IS_PPP_UP=0
fi

showMsg() {
      echo $1
      if [ $IS_PPP_UP -eq 1 ]; then
                echo $1 >> /var/log/ppp.log
      fi
}

# arguments: apiInterface postParameters
callApi() {
    local agent="MosDdns/1.0(mostone@hotmail.com)"
    local url="https://dnsapi.cn/${1:?'Info.Version'}"
    local params="login_token=${ACCESS_TOKEN}&format=json&${2}"
    curl --silent --request POST --user-agent $agent $url --data $params
}

# arguments: domainName subdomainName
printDomainAndRecordIds() {
    local response domainId recordId lastIp
   
    # Get domain Id
    response=$(callApi "Domain.Info" "domain=${1}")
    # echo "Domain.Info call respone: ${response}"
    domainId=$(echo $response | sed 's/.*{"id":"\(*\)".*/\1/')
    echo "    Domain[${1}] Id is:                ${domainId}"

    # Get Record Id
    response=$(callApi "Record.List" "domain_id=${domainId}&sub_domain=${2}")
    # echo "Record.List call respone: ${response}"
    recordId=$(echo $response | sed 's/.*\[{"id":"\(*\)".*/\1/')
    echo "    Record[${2}] Id is:                ${recordId}"
   
    # Print last Ip
    lastIp=$(echo $response | sed 's/.*,"value":"\(*\)".*/\1/')
    echo "    Server side last Ip:                ${lastIp}"
}

# arguments: domainId recordId
getLastIp() {
    local response lastIp
   
    # get last Ip
    response=$(callApi "Record.Info" "domain_id=${1}&record_id=${2}")
    lastIp=$(echo $response | sed 's/.*,"value":"\(*\)".*/\1/')
   
    # validate Ip
    case "$lastIp" in
      *)
      echo $lastIp
      return 0
      ;;
      *)
      echo $response | sed 's/.*,"message":"\([^"]*\)".*/\1/'
      return 1
      ;;
    esac
}

# arguments: domainId recordId subdomainName lineId newIp
updateDdns() {
    local response returnCode recordIp lastIp
   
    # get last Ip
    lastIp=$(getLastIp $1 $2)
    if [ $? -eq 1 ]; then
      showMsg $lastIp
      return 1
    fi
   
    # same Ip check
    if [ "$lastIp" = "$5" ]; then
      showMsg "Server side last Ip is the same as current local Ip!"
      return 1
    fi
      
    # update Ip
    response=$(callApi "Record.Ddns" "domain_id=${1}&record_id=${2}&sub_domain=${3}&record_line_id=${4}&value=${5}&record_type=A")
    returnCode=$(echo $response | sed 's/.*{"code":"\(*\)".*/\1/')
    recordIp=$(echo $response | sed 's/.*,"value":"\(*\)".*/\1/')
   
    showMsg "${response}"
   
    # Output Ip
    if [ "$recordIp" = "$5" ]; then
      if [ "$returnCode" = "1" ]; then
            showMsg "New Ip post success: ${recordIp}"
      else
            # Echo error message
            showMsg $(echo $response | sed 's/.*,"message":"\([^"]*\)".*/\1/')
      fi
    else
      showMsg "Update Failed! Please check your network."
    fi
}

# use -q to print domain and record Ids
if [ "-q" = "$1" ]; then
    printDomainAndRecordIds $2 $3
    exit 0
fi

# use (--test domainId recordId subdomainName lineId newIp) to test update
if [ "--test" = "$1" ]; then
      updateDdns $2 $3 $4 $5 $6
      exit 0
fi

# to sure be call by /etc/ppp/ip-up
if [ $IS_PPP_UP -eq 0 ]; then
    echo "Please copy script file to /config/scripts/ppp/ip-up.d/"
    exit 0
else
      date > /var/log/ppp.log
      echo -e "PPP_LOCAL:${PPP_LOCAL} \nPPP_REMOTE:${PPP_REMOTE}" >> /var/log/ppp.log
fi


# Place each domain you want to update as follows
# you can have multiple domainList blocks
#
# updateDdns arguments: domainId recordId subdomainName lineId newIp
#
# lineId samples: "line_ids": {
#      "默认": 0,
#      "国内": "7=0",   请将 '=' 换成 '%3D', "7%3D0"
#      "国外": "3=0",
#      "电信": "10=0",
#      "联通": "10=1", ......
# lineId list refrence: https://www.dnspod.cn/docs/domains.html#record-line
# (note: lineId if include '=', please replace with '%3D')
updateDdns "1111111" "222222" "@" "0" $PPP_LOCAL
补记:开了 VPN Server 之后,有客户端连接时,也会被执行,这时需要加一个 if 判断:
    if [ "$PPP_IFACE" != "pppoe0" ]; then
                #echo -e "PPP_IFACE:[${PPP_IFACE}]\nnot pppoe0" >> /var/log/ppp.log
                exit 0
    fi参考资料:https://github.com/anrip/ArDNSPod
页: [1]
查看完整版本: EdgeRouter 配置 dnspod 动态域名更新