├── README.md ├── kd-ddns.sh ├── cf-cn-ddns.sh └── cf-ddns.sh /README.md: -------------------------------------------------------------------------------- 1 | # 通过此项目修改 2 | ## [https://github.com/yulewang/cloudflare-api-v4-ddns](https://github.com/yulewang/cloudflare-api-v4-ddns) 3 | 4 | 5 | # 一键代码 6 | 7 | 8 | ``` 9 | curl -L -O -s https://raw.githubusercontent.com/xb0or/KD-DDNS/main/kd-ddns.sh && chmod +x kd-ddns.sh && ./kd-ddns.sh 10 | ``` 11 | 12 | # 使用教程 13 | ## 选择服务器类型 14 | 15 | ### 1.国外服务器(有TG通知) 16 | 17 | ### 2.国内服务器(无通知) 18 | 19 | 20 | #### 请输入主域名(eg:example.com):example.com 21 | 22 | #### 请输入子域名(eg:123.example.com 只需填入123):123 23 | 24 | #### 请输入 cloudflare API :12345678999999 25 | 在 https://dash.cloudflare.com/profile/api-tokens 中获得Global API Key 26 | 27 | 28 | #### 请输入 cloudflare Username: 123456789@gmail.com 29 | ``` 30 | 为账号邮箱 31 | ``` 32 | #### 请输入TG机器人token:123456:abcderg 33 | 34 | 在此机器人创建@BotFather 35 | 36 | #### 请输入TG接收人ID:123456789 37 | 38 | ``` 39 | 1、打开Telegram,在搜索栏搜索 @userinfobot 40 | 2、选择点击灰色头像 41 | 3、点击 Start 42 | 4、将第二行Id后数字填入 43 | ``` 44 | 45 | `cf-ddns.sh` 如果IP无变化则不运行 46 | 47 | `cf-ddns.sh -f true` 为无论IP是否改变强制运行 48 | 49 | # 后期修改 50 | 一键脚本为一次性 如续修改到 `/usr/local/bin/cf-ddns.sh` 进行手动修改 或者删除此文件再运行一键 51 | -------------------------------------------------------------------------------- /kd-ddns.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo && echo -e "欢迎使用kd-ddns 3 | 请选择您的服务器: 4 | 1.国外服务器(有TG通知) 5 | 2.国内服务器(无通知)" && echo 6 | read -e -p "(默认: 取消):" bk_modify 7 | [[ -z "${bk_modify}" ]] && echo "已取消..." && exit 1 8 | if [[ ${bk_modify} == "1" ]]; then 9 | curl https://raw.githubusercontent.com/xb0or/KD-DDNS/main/cf-ddns.sh > /usr/local/bin/cf-ddns.sh && chmod +x /usr/local/bin/cf-ddns.sh 10 | read -p "请输入主域名(eg:example.com) :" zhuyuming 11 | read -p "请输入子域名(eg:123.example.com 只需填入123) :" ziyuming 12 | read -p "请输入 cloudflare API :" youkey 13 | read -p "请输入 cloudflare Username:" youuser 14 | read -p "请输入 TG 机器人Token:" jiqirentoken 15 | read -p "请输入 TG 接收人ID:" tongzhirenid 16 | elif [[ ${bk_modify} == "2" ]]; then 17 | curl https://raw.githubusercontent.com/xb0or/KD-DDNS/main/cf-cn-ddns.sh > /usr/local/bin/cf-ddns.sh && chmod +x /usr/local/bin/cf-ddns.sh 18 | read -p "请输入主域名(eg:example.com) :" zhuyuming 19 | read -p "请输入子域名(eg:123.example.com 只需填入123) :" ziyuming 20 | read -p "请输入 cloudflare API :" youkey 21 | read -p "请输入 cloudflare Username:" youuser 22 | else 23 | echo -e "${Error} 请输入正确的数字(1-2)" && exit 1 24 | fi 25 | 26 | sed -i "s/zhuyuming/${zhuyuming}/g" /usr/local/bin/cf-ddns.sh 27 | sed -i "s/ziyuming/${ziyuming}.${zhuyuming}/g" /usr/local/bin/cf-ddns.sh 28 | sed -i "s/youkey/${youkey}/g" /usr/local/bin/cf-ddns.sh 29 | sed -i "s/youuser/${youuser}/g" /usr/local/bin/cf-ddns.sh 30 | sed -i "s/jiqirentoken/${jiqirentoken}/g" /usr/local/bin/cf-ddns.sh 31 | sed -i "s/tongzhirenid/${tongzhirenid}/g" /usr/local/bin/cf-ddns.sh 32 | 33 | cf-ddns.sh 34 | 35 | echo "请使用 crontab -e 添加计划任务" 36 | echo "*/1 * * * * /usr/local/bin/cf-ddns.sh >/dev/null 2>&1" 37 | echo 38 | -------------------------------------------------------------------------------- /cf-cn-ddns.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit 3 | set -o nounset 4 | set -o pipefail 5 | 6 | # Automatically update your CloudFlare DNS record to the IP, Dynamic DNS 7 | # Can retrieve cloudflare Domain id and list zone's, because, lazy 8 | 9 | # Place at: 10 | # curl https://raw.githubusercontent.com/yulewang/cloudflare-api-v4-ddns/master/cf-v4-ddns.sh > /usr/local/bin/cf-ddns.sh && chmod +x /usr/local/bin/cf-ddns.sh 11 | # run `crontab -e` and add next line: 12 | # */1 * * * * /usr/local/bin/cf-ddns.sh >/dev/null 2>&1 13 | # or you need log: 14 | # */1 * * * * /usr/local/bin/cf-ddns.sh >> /var/log/cf-ddns.log 2>&1 15 | 16 | 17 | # Usage: 18 | # cf-ddns.sh -k cloudflare-api-key \ 19 | # -u user@example.com \ 20 | # -h host.example.com \ # fqdn of the record you want to update 21 | # -z example.com \ # will show you all zones if forgot, but you need this 22 | # -t A|AAAA # specify ipv4/ipv6, default: ipv4 23 | 24 | # Optional flags: 25 | # -f false|true \ # force dns update, disregard local stored ip 26 | 27 | # default config 28 | 29 | # API key, see https://www.cloudflare.com/a/account/my-account, 30 | # incorrect api-key results in E_UNAUTH error 31 | CFKEY=youkey 32 | 33 | # Username, eg: user@example.com 34 | CFUSER=youuser 35 | 36 | # Zone name, eg: example.com 37 | CFZONE_NAME=zhuyuming 38 | 39 | # Hostname to update, eg: homeserver.example.com 40 | CFRECORD_NAME=ziyuming 41 | 42 | # Record type, A(IPv4)|AAAA(IPv6), default IPv4 43 | CFRECORD_TYPE=A 44 | 45 | # Cloudflare TTL for record, between 120 and 86400 seconds 46 | CFTTL=1 47 | 48 | # Ignore local file, update ip anyway 49 | FORCE=false 50 | 51 | WANIPSITE="http://ipv4.icanhazip.com" 52 | 53 | # Site to retrieve WAN ip, other examples are: bot.whatismyipaddress.com, https://api.ipify.org/ ... 54 | if [ "$CFRECORD_TYPE" = "A" ]; then 55 | : 56 | elif [ "$CFRECORD_TYPE" = "AAAA" ]; then 57 | WANIPSITE="http://ipv6.icanhazip.com" 58 | else 59 | echo "$CFRECORD_TYPE specified is invalid, CFRECORD_TYPE can only be A(for IPv4)|AAAA(for IPv6)" 60 | exit 2 61 | fi 62 | 63 | # get parameter 64 | while getopts k:u:h:z:t:f: opts; do 65 | case ${opts} in 66 | k) CFKEY=${OPTARG} ;; 67 | u) CFUSER=${OPTARG} ;; 68 | h) CFRECORD_NAME=${OPTARG} ;; 69 | z) CFZONE_NAME=${OPTARG} ;; 70 | t) CFRECORD_TYPE=${OPTARG} ;; 71 | f) FORCE=${OPTARG} ;; 72 | esac 73 | done 74 | 75 | # If required settings are missing just exit 76 | if [ "$CFKEY" = "" ]; then 77 | echo "Missing api-key, get at: https://www.cloudflare.com/a/account/my-account" 78 | echo "and save in ${0} or using the -k flag" 79 | exit 2 80 | fi 81 | if [ "$CFUSER" = "" ]; then 82 | echo "Missing username, probably your email-address" 83 | echo "and save in ${0} or using the -u flag" 84 | exit 2 85 | fi 86 | if [ "$CFRECORD_NAME" = "" ]; then 87 | echo "Missing hostname, what host do you want to update?" 88 | echo "save in ${0} or using the -h flag" 89 | exit 2 90 | fi 91 | 92 | # If the hostname is not a FQDN 93 | if [ "$CFRECORD_NAME" != "$CFZONE_NAME" ] && ! [ -z "${CFRECORD_NAME##*$CFZONE_NAME}" ]; then 94 | CFRECORD_NAME="$CFRECORD_NAME.$CFZONE_NAME" 95 | echo " => Hostname is not a FQDN, assuming $CFRECORD_NAME" 96 | fi 97 | 98 | # Get current and old WAN ip 99 | WAN_IP=`curl -s ${WANIPSITE}` 100 | WAN_IP_FILE=$HOME/.cf-wan_ip_$CFRECORD_NAME.txt 101 | if [ -f $WAN_IP_FILE ]; then 102 | OLD_WAN_IP=`cat $WAN_IP_FILE` 103 | else 104 | echo "No file, need IP(第一次使用请忽略)" 105 | OLD_WAN_IP="" 106 | fi 107 | 108 | # If WAN IP is unchanged an not -f flag, exit here 109 | if [ "$WAN_IP" = "$OLD_WAN_IP" ] && [ "$FORCE" = false ]; then 110 | echo "IP似乎没有变化,无论如何都要更新请使用 cf-ddns.sh -f true" 111 | exit 0 112 | fi 113 | 114 | # Get zone_identifier & record_identifier 115 | ID_FILE=$HOME/.cf-id_$CFRECORD_NAME.txt 116 | if [ -f $ID_FILE ] && [ $(wc -l $ID_FILE | cut -d " " -f 1) == 4 ] \ 117 | && [ "$(sed -n '3,1p' "$ID_FILE")" == "$CFZONE_NAME" ] \ 118 | && [ "$(sed -n '4,1p' "$ID_FILE")" == "$CFRECORD_NAME" ]; then 119 | CFZONE_ID=$(sed -n '1,1p' "$ID_FILE") 120 | CFRECORD_ID=$(sed -n '2,1p' "$ID_FILE") 121 | else 122 | echo "正在更新IP中..." 123 | CFZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$CFZONE_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 ) 124 | CFRECORD_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records?name=$CFRECORD_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 ) 125 | echo "$CFZONE_ID" > $ID_FILE 126 | echo "$CFRECORD_ID" >> $ID_FILE 127 | echo "$CFZONE_NAME" >> $ID_FILE 128 | echo "$CFRECORD_NAME" >> $ID_FILE 129 | fi 130 | 131 | # If WAN is changed, update cloudflare 132 | echo "已将域名更新到新的IP: $WAN_IP" 133 | 134 | RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records/$CFRECORD_ID" \ 135 | -H "X-Auth-Email: $CFUSER" \ 136 | -H "X-Auth-Key: $CFKEY" \ 137 | -H "Content-Type: application/json" \ 138 | --data "{\"id\":\"$CFZONE_ID\",\"type\":\"$CFRECORD_TYPE\",\"name\":\"$CFRECORD_NAME\",\"content\":\"$WAN_IP\", \"ttl\":$CFTTL}") 139 | 140 | 141 | if [ "$RESPONSE" != "${RESPONSE%success*}" ] && [ "$(echo $RESPONSE | grep "\"success\":true")" != "" ]; then 142 | echo "更新成功!" 143 | echo $WAN_IP > $WAN_IP_FILE 144 | exit 145 | else 146 | echo '更新失败了请看下面报错:' 147 | echo "Response: $RESPONSE" 148 | exit 1 149 | fi 150 | -------------------------------------------------------------------------------- /cf-ddns.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit 3 | set -o nounset 4 | set -o pipefail 5 | 6 | # Automatically update your CloudFlare DNS record to the IP, Dynamic DNS 7 | # Can retrieve cloudflare Domain id and list zone's, because, lazy 8 | 9 | # Place at: 10 | # curl https://raw.githubusercontent.com/yulewang/cloudflare-api-v4-ddns/master/cf-v4-ddns.sh > /usr/local/bin/cf-ddns.sh && chmod +x /usr/local/bin/cf-ddns.sh 11 | # run `crontab -e` and add next line: 12 | # */1 * * * * /usr/local/bin/cf-ddns.sh >/dev/null 2>&1 13 | # or you need log: 14 | # */1 * * * * /usr/local/bin/cf-ddns.sh >> /var/log/cf-ddns.log 2>&1 15 | 16 | 17 | # Usage: 18 | # cf-ddns.sh -k cloudflare-api-key \ 19 | # -u user@example.com \ 20 | # -h host.example.com \ # fqdn of the record you want to update 21 | # -z example.com \ # will show you all zones if forgot, but you need this 22 | # -t A|AAAA # specify ipv4/ipv6, default: ipv4 23 | 24 | # Optional flags: 25 | # -f false|true \ # force dns update, disregard local stored ip 26 | 27 | # default config 28 | 29 | # API key, see https://www.cloudflare.com/a/account/my-account, 30 | # incorrect api-key results in E_UNAUTH error 31 | CFKEY=youkey 32 | 33 | # Username, eg: user@example.com 34 | CFUSER=youuser 35 | 36 | # Zone name, eg: example.com 37 | CFZONE_NAME=zhuyuming 38 | 39 | # Hostname to update, eg: homeserver.example.com 40 | CFRECORD_NAME=ziyuming 41 | 42 | # Record type, A(IPv4)|AAAA(IPv6), default IPv4 43 | CFRECORD_TYPE=A 44 | 45 | # Cloudflare TTL for record, between 120 and 86400 seconds 46 | CFTTL=1 47 | 48 | # Ignore local file, update ip anyway 49 | FORCE=false 50 | 51 | WANIPSITE="http://ipv4.icanhazip.com" 52 | 53 | # Site to retrieve WAN ip, other examples are: bot.whatismyipaddress.com, https://api.ipify.org/ ... 54 | if [ "$CFRECORD_TYPE" = "A" ]; then 55 | : 56 | elif [ "$CFRECORD_TYPE" = "AAAA" ]; then 57 | WANIPSITE="http://ipv6.icanhazip.com" 58 | else 59 | echo "$CFRECORD_TYPE specified is invalid, CFRECORD_TYPE can only be A(for IPv4)|AAAA(for IPv6)" 60 | exit 2 61 | fi 62 | 63 | # get parameter 64 | while getopts k:u:h:z:t:f: opts; do 65 | case ${opts} in 66 | k) CFKEY=${OPTARG} ;; 67 | u) CFUSER=${OPTARG} ;; 68 | h) CFRECORD_NAME=${OPTARG} ;; 69 | z) CFZONE_NAME=${OPTARG} ;; 70 | t) CFRECORD_TYPE=${OPTARG} ;; 71 | f) FORCE=${OPTARG} ;; 72 | esac 73 | done 74 | 75 | # If required settings are missing just exit 76 | if [ "$CFKEY" = "" ]; then 77 | echo "Missing api-key, get at: https://www.cloudflare.com/a/account/my-account" 78 | echo "and save in ${0} or using the -k flag" 79 | exit 2 80 | fi 81 | if [ "$CFUSER" = "" ]; then 82 | echo "Missing username, probably your email-address" 83 | echo "and save in ${0} or using the -u flag" 84 | exit 2 85 | fi 86 | if [ "$CFRECORD_NAME" = "" ]; then 87 | echo "Missing hostname, what host do you want to update?" 88 | echo "save in ${0} or using the -h flag" 89 | exit 2 90 | fi 91 | 92 | # If the hostname is not a FQDN 93 | if [ "$CFRECORD_NAME" != "$CFZONE_NAME" ] && ! [ -z "${CFRECORD_NAME##*$CFZONE_NAME}" ]; then 94 | CFRECORD_NAME="$CFRECORD_NAME.$CFZONE_NAME" 95 | echo " => Hostname is not a FQDN, assuming $CFRECORD_NAME" 96 | fi 97 | 98 | # Get current and old WAN ip 99 | WAN_IP=`curl -s ${WANIPSITE}` 100 | WAN_IP_FILE=$HOME/.cf-wan_ip_$CFRECORD_NAME.txt 101 | if [ -f $WAN_IP_FILE ]; then 102 | OLD_WAN_IP=`cat $WAN_IP_FILE` 103 | else 104 | echo "No file, need IP(第一次使用请忽略)" 105 | OLD_WAN_IP="" 106 | fi 107 | 108 | # If WAN IP is unchanged an not -f flag, exit here 109 | if [ "$WAN_IP" = "$OLD_WAN_IP" ] && [ "$FORCE" = false ]; then 110 | echo "IP似乎没有变化,无论如何都要更新请使用 cf-ddns.sh -f true" 111 | exit 0 112 | fi 113 | 114 | # Get zone_identifier & record_identifier 115 | ID_FILE=$HOME/.cf-id_$CFRECORD_NAME.txt 116 | if [ -f $ID_FILE ] && [ $(wc -l $ID_FILE | cut -d " " -f 1) == 4 ] \ 117 | && [ "$(sed -n '3,1p' "$ID_FILE")" == "$CFZONE_NAME" ] \ 118 | && [ "$(sed -n '4,1p' "$ID_FILE")" == "$CFRECORD_NAME" ]; then 119 | CFZONE_ID=$(sed -n '1,1p' "$ID_FILE") 120 | CFRECORD_ID=$(sed -n '2,1p' "$ID_FILE") 121 | else 122 | echo "正在更新IP中..." 123 | CFZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$CFZONE_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 ) 124 | CFRECORD_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records?name=$CFRECORD_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 ) 125 | echo "$CFZONE_ID" > $ID_FILE 126 | echo "$CFRECORD_ID" >> $ID_FILE 127 | echo "$CFZONE_NAME" >> $ID_FILE 128 | echo "$CFRECORD_NAME" >> $ID_FILE 129 | fi 130 | 131 | # If WAN is changed, update cloudflare 132 | echo "已将域名更新到新的IP: $WAN_IP" 133 | 134 | RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records/$CFRECORD_ID" \ 135 | -H "X-Auth-Email: $CFUSER" \ 136 | -H "X-Auth-Key: $CFKEY" \ 137 | -H "Content-Type: application/json" \ 138 | --data "{\"id\":\"$CFZONE_ID\",\"type\":\"$CFRECORD_TYPE\",\"name\":\"$CFRECORD_NAME\",\"content\":\"$WAN_IP\", \"ttl\":$CFTTL}") 139 | 140 | #TG机器人通知 141 | TOKEN=jiqirentoken #机器人密钥 142 | chat_ID=tongzhirenid #通知人ID 143 | message_text=" 144 | ⚠️主人IP变动了 145 | ——————————————— 146 | 域名:【$CFRECORD_NAME】 147 | 新IP:$WAN_IP 148 | 旧IP:$OLD_WAN_IP 149 | ——————————————— " #通知内容 150 | MODE='HTML' 151 | URL="https://api.telegram.org/bot${TOKEN}/sendMessage" 152 | 153 | 154 | if [ "$RESPONSE" != "${RESPONSE%success*}" ] && [ "$(echo $RESPONSE | grep "\"success\":true")" != "" ]; then 155 | echo "更新成功!" 156 | echo $WAN_IP > $WAN_IP_FILE 157 | curl -s -o /dev/null -X POST $URL -d chat_id=${chat_ID} -d text="${message_text}" 158 | exit 159 | else 160 | echo '更新失败了请看下面报错:' 161 | echo "Response: $RESPONSE" 162 | exit 1 163 | fi 164 | --------------------------------------------------------------------------------