阿里云ddns更新cloudflare ddns更新

cloudflare ddns

#!/usr/bin/env bash
: <<'COMMENT'
env ("ddns_update")
cron: */10 * * * * bash /opt/.cloudflare.sh
COMMENT
auth_email="myki@gmail.com"                                     # 用于登录https://dash.cloudflare.com的邮箱
auth_method="token"                                            # Api Key类型"global"或"token"其中一种
auth_key="_U3K6aVSMIdYPlyWm7pwFDW0GHDefpdlZdvoMyki"            # Api Key
zone_identifier="5395f01b438935203978758d20211222"             # 域名概览页(Overview)找到区域id(Zone ID)
record_name="ql.myki.com"                                 # 需要更新的域名A记录+根域名全称,比如要更新domain.com的sub子域名,就完整填入,即record_name="sub.domain.com"
ttl="60"                                                       # DNS TTL (单位秒,最低60)
proxy=false                                                    # 是否通过Cloudflare代理
tgChatId="tg-id"                                           # tgChatId
tgBotToken="1975051314:AAG9jQSok0AjwerUV9xzOidiita1314"    # tgBotToken
tgurl="https://tg.myki.workers.dev/bot${tgBotToken}/sendMessage"                 # tgurl,不需要tg推送更新情况的话,此处留空即可,需要则填"https://api.telegram.org/bot${tgBotToken}/sendMessage"

function  CREATE(){
  curl -X POST "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records" \
  -H "X-Auth-Email: $auth_email" \
  -H "$auth_header $auth_key" \
  -H "Content-Type: application/json" \
  --data "{\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\",\"ttl\":\"$ttl\",\"proxied\":${proxy}}"
}

function GET_INFO() {
  record=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?type=A&name=$record_name" \
      -H "X-Auth-Email: $auth_email" \
      -H "$auth_header $auth_key" \
      -H "Content-Type: application/json")
}
###########################################
## 推送
###########################################
sendnotify() {
    if [[ $tgurl != "" ]]; then
        notify=$(curl -s -X POST $tgurl -d chat_id=${tgChatId} -d text="${message}")
        case "$notify" in
        *"\"success\":false"*)
            printf "Telegram推送失败。\n"
            exit 1
            ;;
        *)
            printf "Telegram推送成功。\n"
            exit 0
            ;;
        esac
    fi
    printf "未开启Telegram推送功能。\n"
}
###########################################
## 检测公网IP(如果你的环境有做科学上网,请注意选择下面适合自己的ip获取域名)
###########################################
ip=$(curl -s ip.1nth.com || curl -s https://api.ipify.org || curl -s https://ipv4.icanhazip.com/ || curl -s http://members.3322.org/dyndns/getip)
if [ "${ip}" == "" ]; then
    printf "DDNS 更新助手:公网IP获取失败\n"
    message="DDNS 更新助手:公网IP获取失败"
    sendnotify
    exit 1
fi
###########################################
## 检查api_key类型
###########################################
if [ "${auth_method}" == "global" ]; then
    auth_header="X-Auth-Key:"
else
    auth_header="Authorization: Bearer"
fi
###########################################
## 查找A记录是否存在
###########################################
printf "DDNS 更新助手: 检查开始...\n"
record=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?type=A&name=$record_name" \
    -H "X-Auth-Email: $auth_email" \
    -H "$auth_header $auth_key" \
    -H "Content-Type: application/json")
if [[ $record == *"\"count\":0"* ]]; then
    printf "DDNS 更新助手:${record_name} 记录不存在,请先手动创建一次 ${record_name} 记录\n"
    message="DDNS 更新助手:${record_name} 记录不存在,请先手动创建一次 ${record_name} 记录"
    CREATE
    GET_INFO
    #sendnotify
    #exit 1
fi
###########################################
## 获取已存在的IP
###########################################
old_ip=$(echo "$record" | sed -E 's/.*"content":"(([0-9]{1,3}\.){3}[0-9]{1,3})".*/\1/')
# Compare if they're the same
if [[ $ip == $old_ip ]]; then
    printf "DDNS 更新助手: ${record_name} 记录IP - ${ip}未发生变动\n"
##如果自己设置的定时比较频繁,比如10分钟或者半小时更新一次,建议删除下面两行
##删除起点
    message="DDNS 更新助手: ${record_name} 记录IP - ${ip}未发生变动"
    sendnotify
##删除终点
    exit 0
fi
###########################################
## 匹配record id
###########################################
record_identifier=$(echo "$record" | sed -E 's/.*"id":"(\w+)".*/\1/')
###########################################
## 更新IP
###########################################
update=$(curl -s -X PATCH "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$record_identifier" \
    -H "X-Auth-Email: $auth_email" \
    -H "$auth_header $auth_key" \
    -H "Content-Type: application/json" \
    --data "{\"type\":\"A\",\"name\":\"$record_name\",\"content\":\"$ip\",\"ttl\":\"$ttl\",\"proxied\":${proxy}}")
###########################################
## 最终状态反馈
###########################################
case "$update" in
*"\"success\":false"*)
    printf "DDNS 更新助手:DDNS记录$record_name更新失败,详细信息:\n$update\n"
    message="DDNS 更新助手:DDNS记录$record_name更新失败,请手动查看日志。"
    sendnotify
    exit 1
    ;;
*)
    printf "DDNS 更新助手: DDNS 已更新,$record_name - $ip。\n"
    message="DDNS 更新助手:DDNS记录更新成功,当前$record_name的新IP地址为$ip。"
    sendnotify
    exit 0
    ;;
esac

aliyun ddns

#!/bin/bash
echo "[$(date "+%G/%m/%d %H:%M:%S")] AliDDNS.sh start..."

while true
do

# 设置需要DDNS的地址,格式为 AliDDNS_SubDomainName.AliDDNS_DomainName ,
# 例如 AliDDNS_DomainName 为 example.com, AliDDNS_SubDomainName 为 ddns ,
# 连接起来就是 ddns.example.com
#
# 设置需要DDNS的域名 <DomainName>
AliDDNS_DomainName=""
# 设置需要DDNS的子域名 <SubDomainName>
AliDDNS_SubDomainName=""
# 设置域名记录的TTL (生存周期)
# 免费版产品最低为600(10分钟)~86400(1天), 付费版(企业版)包括以上范围, 还可以按照购买产品配置设置为:
# 600(10分钟)、120(2分钟)、60(1分钟)、10(10秒)、5(5秒)、1(1秒),
# 请按照自己的产品配置和DDNS解析速度需求妥善配置TTL值, 免费版设置低于600的TTL将会报错。
AliDDNS_TTL="600"

# 设置阿里云的AccessKeyId/AccessKeySecret,
# 可在 https://ak-console.aliyun.com/ 处获取 ,
# 推荐使用 https://ram.console.aliyun.com/#/user/list 生成的AK/SK, 更安全
#
# 设置阿里云的Access Key
AliDDNS_AK=""
# 设置阿里云的Secret Key
AliDDNS_SK=""

# 设置获取本机IP需要执行的命令 (用于nslookup命令获取DDNS域名的当前IP)
AliDDNS_LocalIP="curl -s whatismyip.akamai.com"
# 设置解析使用的DNS服务器 (推荐使用 223.5.5.5/223.6.6.6 , 毕竟都是阿里家的东西)
AliDDNS_DomainServerIP="223.5.5.5"

# 防止用户忘记设置参数导致程序报错,部分参数如果检测到空值,自动使用默认值
[ "$AliDDNS_LocalIP" = "" ] && AliDDNS_LocalIP="curl -s whatismyip.akamai.com"
[ "$AliDDNS_DomainServerIP" = "" ] && $AliDDNS_DomainServerIP="223.5.5.5"
[ "$AliDDNS_TTL" = "" ] && AliDDNS_TTL="600"
# 获取本机公网IP
AliDDNS_LocalIP=`$AliDDNS_LocalIP 2>&1` || die "$AliDDNS_LocalIP"
# 获取DDNS域名当前解析记录IP
AliDDNS_DomainIP=`nslookup $AliDDNS_SubDomainName.$AliDDNS_DomainName $AliDDNS_DomainServerIP 2>&1`
# 判断上一条命令的执行是否成功
if [ "$?" -eq "0" ]
then
    # 如果执行成功,分离出结果中的IP地址
    AliDDNS_DomainIP=`echo "$AliDDNS_DomainIP" | grep 'Address:' | tail -n1 | awk '{print $NF}'`
    # 进行判断,如果本次获取的新IP和旧IP相同,则进行休眠一分钟后再继续判断
    if [ "$AliDDNS_LocalIP" = "$AliDDNS_DomainIP" ]
    then
        echo "[$(date "+%G/%m/%d %H:%M:%S")] Local IP ($AliDDNS_LocalIP) is the same with Domain IP ($AliDDNS_DomainIP)"
        echo "[$(date "+%G/%m/%d %H:%M:%S")] No change modified ..."
	sleep 60
	continue
    fi
fi
# 如果IP发生变动,开始进行修改
# 生成时间戳
timestamp=`date -u "+%Y-%m-%dT%H%%3A%M%%3A%SZ"`
# URL加密函数
urlencode() {
    # urlencode <string>
    out=""
    while read -n1 c
    do
        case $c in
            [a-zA-Z0-9._-]) out="$out$c" ;;
            *) out="$out`printf '%%%02X' "'$c"`" ;;
        esac
    done
    echo -n $out
}
# URL加密命令
enc() {
    echo -n "$1" | urlencode
}
# 发送请求函数
send_request() {
    local args="AccessKeyId=$AliDDNS_AK&Action=$1&Format=json&$2&Version=2015-01-09"
    local hash=$(echo -n "GET&%2F&$(enc "$args")" | openssl dgst -sha1 -hmac "$AliDDNS_SK&" -binary | openssl base64)
    curl -s "http://alidns.aliyuncs.com/?$args&Signature=$(enc "$hash")"
}
# 获取记录值 (RecordID)
get_recordid() {
    grep -Eo '"RecordId":"[0-9]+"' | cut -d':' -f2 | tr -d '"'
}
# 请求记录值 (RecordID)
query_recordid() {
    send_request "DescribeSubDomainRecords" "SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&SubDomain=$AliDDNS_SubDomainName.$AliDDNS_DomainName&Timestamp=$timestamp"
}
# 更新记录值 (RecordID)
update_record() {
    send_request "UpdateDomainRecord" "RR=$AliDDNS_SubDomainName&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$AliDDNS_TTL&Timestamp=$timestamp&Type=A&Value=$AliDDNS_LocalIP"
}
# 添加记录值 (RecordID)
add_record() {
    send_request "AddDomainRecord&DomainName=$AliDDNS_DomainName" "RR=$AliDDNS_SubDomainName&SignatureMethod=HMAC-SHA1&SignatureNonce=$timestamp&SignatureVersion=1.0&TTL=$AliDDNS_TTL&Timestamp=$timestamp&Type=A&Value=$AliDDNS_LocalIP"
}

# 判断RecordIP是否为空
if [ "$AliDDNS_RecordID" = "" ]
then
    AliDDNS_RecordID=`query_recordid | get_recordid`
fi
if [ "$AliDDNS_RecordID" = "" ]
then
    AliDDNS_RecordID=`add_record | get_recordid`
    echo "[$(date "+%G/%m/%d %H:%M:%S")] Added RecordID : $AliDDNS_RecordID"
else
    update_record $AliDDNS_RecordID
    echo "[$(date "+%G/%m/%d %H:%M:%S")] Updated RecordID : $AliDDNS_RecordID"
fi

# 输出最终结果
if [ "$AliDDNS_RecordID" = "" ]; then
    # 输出失败结果 (因为没有获取到RecordID)
    echo "[$(date "+%G/%m/%d %H:%M:%S")] DDNS Update Failed !"
else
    # 输出成功结果
    echo "[$(date "+%G/%m/%d %H:%M:%S")] DDNS Update Success, New IP is : $AliDDNS_LocalIP"
fi

sleep 30
done