埋头干活,抬头看路
利用云服务商API自己动手实现DDNS

利用云服务商API自己动手实现DDNS

IPV6越来越流行了,有了IPV6后,再搞个动态的DDNS解析服务,就圆满了。

与现成的能用DDNS相比,支持IPV6,而且灵活,简单。

云服务商,我们还是用的最中意的华为云。

找到云解析服务的查询API

https://console.huaweicloud.com/apiexplorer/#/openapi/DNS/debug?api=ListRecordSets

先查询一下,自己当前的记录集

我这边的结果如下:

{
    "id": "ff8080828e61eabc018ea161e5d910f0",
    "name": "nav.xudongvp.com.",
    "description": null,
    "type": "AAAA",
    "ttl": 30,
    "records": [
        "240e:3333:3333:3333:3333:3333:3333:3333"
    ],
    "status": "ACTIVE",
    "zone_id": "8aace3ba78033e080178e2b501f00821",
    "zone_name": "xudongvp.com.",
    "create_at": "2024-04-03T00:35:31.405",
    "update_at": "2024-04-03T00:35:31.448",
    "default": false,
    "project_id": "08e5652c18000f3e2ffec01afc3fe9a4",
    "links": {
        "self": "https://dns.myhuaweicloud.com/v2/zones/8aace3ba78033e080178e2b501f00821/recordsets/ff8080828e61eabc018ea161e5d910f0"
    },
    "tags": []
}

下面我们用更新记录集的API,进行DNS信息更新。

更新的代码,我们就不自己重新全部写了。借用一个现成的,修改一下,原文参考:https://www.bilibili.com/read/cv20113893/

#!/usr/bin/sh
#. /etc/profile
# Copyright 2021 LVCS
# https://github.com/lllvcs/huaweicloud_ddns
# https://gitee.com/lvcs/huaweicloud_ddns
# 在运行此脚本之前,请先在华为云DNS管理控制台内添加对应域名的A记录
# 并获取对应的 ZONE_ID 和 RECORDSET_ID

DOMAIN_NAME="XXXXXXX"
RECORDSET_ID="XXXXXXX"


# 一般来说用户名和账户名相同
USERNAME="XXXXXXX"
ACCOUNTNAME="XXXXXXX"
PASSWORD="XXXXXXX"

# 对应解析记录的 ZONE_ID、RECORDSET_ID和PROJECT_ID,其中PROJECT_ID可以在华为云APIexplorer中的云解析服务>recordset管理>showRecordSet中填写id后的调试结果中的请求头X-Project-Id看到
ZONE_ID="XXXXXXX"
PROJECT_ID="XXXXXXX"


# 从外网API获取ip地址(默认开启1)
REMOTE_RESOLVE=1

# 从网卡获取ip地址(填写网卡名)
# 并请根据实际情况填写sed行数
INTERFACE="eth0"

# 更新IP
TARGET_IP=""

# 获取ip地址网址
GETIPURL="https://6.ipw.cn"

# End Point 终端地址 请根据地域选择,默认为北京1
IAM="iam.af-south-1.myhuaweicloud.com"
DNS="dns.cn-east-3.myhuaweicloud.com"

#认证token获取:
TOKEN_X="$(
    curl -L -k -s -D - -X POST \
    "https://$IAM/v3/auth/tokens" \
    -H 'content-type: application/json' \
    -d '{
    "auth": {
        "identity": {
            "methods": ["password"],
            "password": {
                "user": {
                    "name": "'$USERNAME'",
                    "password": "'$PASSWORD'",
                    "domain": {
                        "name": "'$ACCOUNTNAME'"
                    }
                }
            }
        },
        "scope": {
            "domain": {
                "name": "'$ACCOUNTNAME'"
            }
        }
    }
  }' | grep X-Subject-Token 
)"

TOKEN="$(echo $TOKEN_X | awk -F ' ' '{print $2}')"
#获取本机IP:
if [ -z $TARGET_IP ]; then
    if [ $REMOTE_RESOLVE -eq 1 ]; then
        if [ $INTERFACE ]; then
            TARGET_IP=$(curl -s -6 --interface $INTERFACE $GETIPURL)
        else
            TARGET_IP=$(curl -s -6 $GETIPURL)
        fi
    else
        if [ $INTERFACE ]; then
            TARGET_IP=$(ifconfig $INTERFACE | grep 'inet6' | grep Global | grep -oE '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' | sed -n 1p)
        else
            TARGET_IP=$(ifconfig | grep 'inet6' | grep Global | grep -oE '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' | sed -n 1p)
        fi
    fi
fi
#获取云解析IP:
HWcloud_IP=$(echo $(curl -X GET -L -k  "https://$DNS/v2/zones/$ZONE_ID/recordsets/$RECORDSET_ID" \
-H "X-Auth-Token: $TOKEN" \
-H "Content-Type: application/json" \
-H "X-Project-Id: $PROJECT_ID")| sed 's/,/\n/g'|grep 'records'| grep -oE '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))')


#判断IP是否一致、是否需要调用API修改:
if [ "$TARGET_IP" == "$HWcloud_IP" ]; then
    echo $(echo "[";date "+%Y-%m-%d %H:%M:%S";echo "] ";echo "云解析IP"[$HWcloud_IP]"与本机IP"[$TARGET_IP]"相同,无需修改";)
else
    echo $(echo "[";date "+%Y-%m-%d %H:%M:%S";echo "] ";echo "云解析IP"[$HWcloud_IP]"与本机IP"[$TARGET_IP]"不同,正在修改,API响应内容如下:";
    curl -X PUT -L -k -s \
    "https://$DNS/v2/zones/$ZONE_ID/recordsets/$RECORDSET_ID" \
    -H "Content-Type: application/json" \
    -H "X-Auth-Token: $TOKEN" \
    -d "{\"name\": \"$DOMAIN_NAME\",\"type\": \"AAAA\",\"records\": [\"$TARGET_IP\"],\"ttl\": 30}";)

fi

脚本中,相比与原脚本,主要更新了外部IP获取方式,本地IPV6的过滤筛选方式等,然后调试通过。

至于为什么我们只更新了IPV6的解析,没有更新IPV4的解析,原因就不展开了,懂得自然懂。

2条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注