cloudflare最新ddns脚本 2020.5.2号 解决老版本脚本无法更新ip

tengxunyun cera

1、前言

服务器 IP 总是变,没事就会变个新的,这时候就需要一个 Dynamic Domain Name Server 来保证实时的 #DNS# 更换。
当然首先这个需要你的 DNS 解析商做配合,本文则采用 Cloudflare+#DDNS#+Shell


2、准备

准备工具

Cloudflare 的 Global #API#

Cloudflare 解析的域名一个

前提要素

Curl Wget 已安装


3、#DDNS# 获取新 IP 地址 Shell 脚本

下载地址:[ 链接 ]

#!/usr/bin/env bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
#
# Dynamic Domain Name Server (Cloudflare API)
#
# Author: StarryVoid <[email protected]>
# Intro:  https://blog.starryvoid.com/archives/313.html
#

# Select API(1) Or Token(2)
SelectAT="1"

# CloudFlare API " X-Auth-Email: *** " " X-Auth-Key: *** "
XAUTHEMAIL="YOUREMAILADDRESS"
XAUTHKEY="YOURCLOUDFLAREAPIKEY"

# CloudFlare Token " Authorization: Bearer *** "
AuthorizationToken="YOURTOKEN"

# Domain Name " example.com " " ddns.example.com "
ZONENAME="DOMAIN"
DOMAINNAME="DOMAINNAME"
DOMAINTTL="1"

# Output
OUTPUTINFO="$(pwd)/ddns_output.info"
OUTPUTLOG="$(pwd)/ddns_shell.log"

# Time
DATETIME=$(date +%Y-%m-%d_%H:%M:%S)

# ------------ Start ------------

check_environment () {
    if ! [ -x "$(command -v curl)" ]; then echo "Command not found \"curl\"" >> "${OUTPUTLOG}" ; exit 1 ; fi
    if ! [ -x "$(command -v wget)" ]; then echo "Command not found \"wget\"" >> "${OUTPUTLOG}" ; exit 1 ; fi
}

check_selectAT () {
    if [[ ! "${SelectAT}" = 1 && ! "${SelectAT}" = 2 ]]; then echo "Failed to Select API(1) Or Token(2)" >> "${OUTPUTLOG}"; exit 1; fi
}

get_zone_records() {
    if [ "${SelectAT}" = 1 ]; then ZONERECORDSLOG=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${ZONENAME}" -H "X-Auth-Email: ${XAUTHEMAIL}" -H "X-Auth-Key: ${XAUTHKEY}" -H "Content-Type: application/json" --connect-timeout 30 -m 10 ); fi
    if [ "${SelectAT}" = 2 ]; then ZONERECORDSLOG=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=${ZONENAME}" -H "Authorization: Bearer ${AuthorizationToken}" -H "Content-Type: application/json" --connect-timeout 30 -m 10 ); fi
    ZONERECORDS=$(echo "${ZONERECORDSLOG}" | awk BEGIN{RS=EOF}'{gsub(/\n/," ");print}' | sed 's/ //g' | grep -Po '(?<="id":")[^"]*' | head -1 )
    if [ ! "${ZONERECORDS}" ]; then echo "Failed to get zone_records from cloudflare." >> "${OUTPUTLOG}" ; echo "---log---" >> "${OUTPUTLOG}" ; echo "${ZONERECORDSLOG}" >> "${OUTPUTLOG}" ; echo "---log---" >> "${OUTPUTLOG}" ; exit 1; fi
}

get_dns_records() {
    if [ "${SelectAT}" = 1 ]; then DNSRECORDSLOG=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONERECORDS}/dns_records?type=A&name=${DOMAINNAME}" -H "X-Auth-Email: ${XAUTHEMAIL}" -H "X-Auth-Key: ${XAUTHKEY}" -H "Content-Type: application/json" --connect-timeout 30 -m 10 ); fi
    if [ "${SelectAT}" = 2 ]; then DNSRECORDSLOG=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONERECORDS}/dns_records?type=A&name=${DOMAINNAME}" -H "Authorization: Bearer ${AuthorizationToken}" -H "Content-Type: application/json" --connect-timeout 30 -m 10 ); fi
    DNSRECORDS=$(echo "${DNSRECORDSLOG}" | awk BEGIN{RS=EOF}'{gsub(/\n/," ");print}' | sed 's/ //g' | grep -Po '(?<="id":")[^"]*' | head -1 )
    if [ ! "${DNSRECORDS}" ]; then echo "Failed to get dns_records from cloudflare." >> "${OUTPUTLOG}"; echo "---log---" >> "${OUTPUTLOG}" ; echo "${DNSRECORDSLOG}" >> "${OUTPUTLOG}" ; echo "---log---" >> "${OUTPUTLOG}" ; exit 1; fi
}
    
get_domain_ip() {
    if [ "${SelectAT}" = 1 ]; then DOMAINIPADDLOG=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONERECORDS}/dns_records/${DNSRECORDS}" -H "X-Auth-Email: ${XAUTHEMAIL}" -H "X-Auth-Key: ${XAUTHKEY}" -H "Content-Type: application/json" --connect-timeout 30 -m 10 ); fi
    if [ "${SelectAT}" = 2 ]; then DOMAINIPADDLOG=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONERECORDS}/dns_records/${DNSRECORDS}" -H "Authorization: Bearer ${AuthorizationToken}" -H "Content-Type: application/json" --connect-timeout 30 -m 10 ); fi
    DOMAINIPADD=$(echo "${DOMAINIPADDLOG}" | awk BEGIN{RS=EOF}'{gsub(/\n/," ");print}' | sed 's/ //g' | grep -Po '(?<="content":")[^"]*' | head -1 )
    if [ ! "${DOMAINIPADD}" ]; then echo "Failed to get DNS resolution address from cloudflare." >> "${OUTPUTLOG}"; echo "---log---" >> "${OUTPUTLOG}" ; echo "${DOMAINIPADDLOG}" >> "${OUTPUTLOG}" ; echo "---log---" >> "${OUTPUTLOG}" ; exit 1; fi
}

update_new_ipaddress() {
    if [ "${SelectAT}" = 1 ]; then curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONERECORDS}/dns_records/${DNSRECORDS}" -H "X-Auth-Email: ${XAUTHEMAIL}" -H "X-Auth-Key: ${XAUTHKEY}" -H "Content-Type: application/json"  --data "{\"type\":\"A\",\"name\":\"${DOMAINNAME}\",\"content\":\"${NEWIPADD}\",\"ttl\":"${DOMAINTTL}",\"proxied\":false}" --connect-timeout 30 -m 10 > /dev/null 2>&1 && UPDATENEWIPADDRESS=1 || UPDATENEWIPADDRESS=0; fi
    if [ "${SelectAT}" = 2 ]; then curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONERECORDS}/dns_records/${DNSRECORDS}" -H "Authorization: Bearer ${AuthorizationToken}" -H "Content-Type: application/json"  --data "{\"type\":\"A\",\"name\":\"${DOMAINNAME}\",\"content\":\"${NEWIPADD}\",\"ttl\":"${DOMAINTTL}",\"proxied\":false}" --connect-timeout 30 -m 10 > /dev/null 2>&1 && UPDATENEWIPADDRESS=1 || UPDATENEWIPADDRESS=0; fi
    if [ "${UPDATENEWIPADDRESS}" = 1 ] ; then echo "Successfully updated domain name resolution address." >> "${OUTPUTLOG}" ; fi
    if [ "${UPDATENEWIPADDRESS}" = 0 ] ; then echo "Failed to updated domain name resolution address." >> "${OUTPUTLOG}" ; exit 1 ; fi
}

get_server_new_ip() {
    [ -z "${NEWIPADD}" ] && NEWIPADD=$( wget -qO- -t1 -T2 https://ipv4.icanhazip.com )
    [ -z "${NEWIPADD}" ] && NEWIPADD=$( wget -qO- -t1 -T2 https://api.ipify.org )
    [ -z "${NEWIPADD}" ] && NEWIPADD=$( wget -qO- -t1 -T2 ipv4.icanhazip.com )
    [ -z "${NEWIPADD}" ] && NEWIPADD=$( wget -qO- -t1 -T2 api.ipify.org )
    [ -z "${NEWIPADD}" ] && NEWIPADD=$( wget -qO- -t1 -T2 ipinfo.io/ip )
    if [[ ! "${NEWIPADD}" ]]; then echo "Failed to get server public network address from internet." >> "${OUTPUTLOG}"; exit 1; fi
}

check_ddns_info_file() {
    if [ -f "${OUTPUTINFO}" ]; then
        CHECKDDNSINFOFILE=1
        ZONERECORDS=$(cat < "${OUTPUTINFO}" | grep "ZONERECORDS=" | awk -F "=" '{print $2}' | sed 's/\"//g' | sed "s/\'//g" )
        DNSRECORDS=$(cat < "${OUTPUTINFO}" | grep "DNSRECORDS=" | awk -F "=" '{print $2}' | sed 's/\"//g' | sed "s/\'//g" )
        DOMAINIPADD=$(cat < "${OUTPUTINFO}" | grep "DOMAINIPADD=" | awk -F "=" '{print $2}' | sed 's/\"//g' | sed "s/\'//g" )
        if [[ ! "${ZONERECORDS}" ]]; then CHECKDDNSINFOFILE=0 ; fi
        if [[ ! "${DNSRECORDS}" ]]; then CHECKDDNSINFOFILE=0 ; fi
        if [[ ! "${DOMAINIPADD}" ]]; then CHECKDDNSINFOFILE=0 ; fi
    else 
        CHECKDDNSINFOFILE=0
    fi
    if [ "${CHECKDDNSINFOFILE}" = 0 ] ; then echo "Failed to check DDNS information file." >> "${OUTPUTLOG}" ; rm -f "${OUTPUTINFO}" ; exit 1 ; fi
}

make_ddns_info_file() {
    if [ -f "${OUTPUTINFO}" ] ; then rm -f "${OUTPUTINFO}" ; fi
    touch "${OUTPUTINFO}"
    echo Update Time is "${DATETIME}" >> "${OUTPUTINFO}"
    get_zone_records
    get_dns_records
    get_domain_ip
    echo -e "ZONERECORDS=\"${ZONERECORDS}\"\nDNSRECORDS=\"${DNSRECORDS}\"\nDOMAINIPADD=\"${DOMAINIPADD}\"" >> "${OUTPUTINFO}"
    echo "Successfully generated DDNS information." >> "${OUTPUTLOG}"
}

main() {
    check_environment
    check_selectAT
    echo "Running Time is ${DATETIME}" >> "${OUTPUTLOG}"
    get_server_new_ip
    if [ -f "${OUTPUTINFO}" ]; then
        check_ddns_info_file
    else
        make_ddns_info_file
    fi
    if [[ "${NEWIPADD}" == "${DOMAINIPADD}" ]]; then 
        echo "IP address has not changed." >> "${OUTPUTLOG}"
        exit 0
    else 
        update_new_ipaddress
        sleep 10s
        make_ddns_info_file
        if [[ "${NEWIPADD}" == "${DOMAINIPADD}" ]]; then 
            echo "IP address has been modified to \"${NEWIPADD}\"." >> "${OUTPUTLOG}"
            exit 0
        else
            echo "IP address modification failed." >> "${OUTPUTLOG}"
            exit 1
        fi
    fi
}

# ------------ End ------------

main


4、讲解

首先本文制作过程中参考过的脚本,在此表示感谢


4.1、脚本配置 Global API 版

我们需要将所需的内容(Cloudflare API  和 DDNS 域名)填入对应位置

# Select API(1) Or Token(2)
SelectAT="1"
# CloudFlare API " X-Auth-Email: *** " " X-Auth-Key: *** "
XAUTHEMAIL="[email protected]" #你的 Cloudflare 邮箱用户名
XAUTHKEY="123123123123" #你的 Cloudflare Global API Key
# Domain Name " example.com " " ddns.example.com "
ZONENAME="example.com" #你的二级域名
DOMAINNAME="ddns.example.com" #你的 DDNS 域名
DOMAINTTL="1" #你的域名 TTL 时间,默认 1 为 auto

4.2、脚本配置 Token 版

我们需要将所需的内容(Cloudflare Token 和 DDNS 域名)填入对应位置

# Select API(1) Or Token(2)
SelectAT="2"
# CloudFlare Token " Authorization: Bearer *** "
AuthorizationToken="YOURTOKEN"
# Domain Name " example.com " " ddns.example.com "
ZONENAME="example.com" #你的二级域名
DOMAINNAME="ddns.example.com" #你的 DDNS 域名
DOMAINTTL="1" #你的域名 TTL 时间,默认 1 为 auto

4.3、定时运行

如果需要定时运行,可以编辑/etc/crontab  实现定期运行,下例为 5min 运行一次
先 cd  进入目录是为了隔离不同 DDNS 脚本生成的数据和日志文件。否则默认放/root 目录下。

# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed

*/5 * * * * root cd /autoshell && bash cloudflare-ddns.sh

4.4、脚本输出

默认会在用户所在目录下生成两个文件 ddnsrun.data  和 ddnsrun.log ,前者是储存获取的 API 信息,后者是储存运行日志。

[[email protected] auto]# cat ddnsrun.data
Update Time 2018-12-02_11:43:01
ZONERECORDS=*
DNSRECORDS=*
OldIPAddress=*.*.*.*

[[email protected] auto]# cat ddnsrun.log
Running Time is 2018-12-02_11:43:01
IP address has been changed to *.*.*.*
Running Time is 2018-12-02_11:44:01
The IP address is the same
Running Time is 2018-12-02_11:45:01
The IP address is the same
Running Time is 2018-12-02_11:46:01
The IP address is the same

如果出现问题,可以在日志中查看问题原因。


4.5、获取 Cloudflare 的 API Tokens

首先进入 Cloudflare 的个人配置页面 [链接]

找到下面的 API Tokens  (Manage access and permissions for your accounts, sites, and products.)

然后点击右侧的 Create Token 创建新的 Token ( 相对 Global API 约束访问权限 )

新的 Token 需要配置权限,本次 DDNS 需要的权限分别为 Account.Dns Firewall.Read 和 Zone.Zone.Read 和 Zone.DNS.Edit 三条。配置好后确认

*** 提醒:2020/03/05 发现 Cloudflare 如果 Token 配置了 Zone Resources 限制区域,会导致无法获取 Zone Record 。
*** 现象:执行命令返回 “message”:”Actor ‘com.cloudflare.api.token.***’ requires permission ‘com.cloudflare.api.account.zone.list’ to list zones”
*** 暂时解决方式:配置为 All zones 。

 

最后核对好权限后再次确认,显示” *** API token was successfully updated “,此时你可以查看你的 Token ,并点击 Copy 即可复制。


4.6、获取 Cloudflare 的 Global API

首先进入 Cloudflare 的个人配置页面 [链接]

找到下面的 API Keys  (Keys used to access Cloudflare APIs.)

然后在 Global API Key 一行点击右侧的 View  查看你的 Global API Key

最后额外注意,Global API 需要搭配你的邮箱账户名才可以使用


5、后期修订

2019/11/05、经由 Sion 提醒,换行符在发表文章时丢失,现已提供下载地址。 同时支持 Token 方式管理。

2020/03/05、发现 #Cloudflare# 关于 #Token# 配置疑似 #Bug# ,已增加额外提醒。

2020/04/26、发现 Cloudflare 关于 List DNS Records 的返回结果有变化,额外增加判定

cera cloudiplc

相关推荐

Cloudflare Page Rules 设置解释

#Always Online# 打开或关闭永久在线缓存应用。 适用:All Always Use HTTPS 打开或关闭“始终使用https”,打开后所有http都自动301会转向到https 如果没有这个按钮,看看自己的证书有没有正常 适用:All Browser Cache TTL 控制缓存保留多长时间 适用:All Browser Integrity Check 检查访客的浏览器头有没有采集器和特定机器人的特征 适用:All Bypass Cache on Cookie 对指定规则内容不缓存,直接从源服务器调取 适用: Business Enterprise Cache By Device Type 根据访客的终端设备分别进行缓存 适用: Enterprise Cache Key 控制包含哪些变量的url需要被缓存 适用: Enterprise Cache Deception Armor 缓存欺骗攻击保护。验证url的扩展名是都符合其实际内容。 适用: All Cache Level 定义缓存的级别 适用: All Cache on Cookie 根据特定的cookie名称来确定需要缓存的内容 …

|教程|阿里云国际|流量包脚本监控 超流量自动关机

#教程# 阿里云国际 – 流量包脚本监控 超流量自动关机 很多同学在使用#阿里云##国际#的时候被无聊的人#刷流量#,导致很快#流量包#被用完,这里给出个 PHP 的#监控#,用定时 cron 实现超流量就自动关机。 把下面的文件保存为 datamonitoring.php { $canonicalizedQueryString .= ‘&’ . percentEncode($key) . ‘=’ . percentEncode($value); } // 生成用于计算签名的字符串 stringToSign $stringToSign = ‘GET&%2F&’ . percentencode(substr($canonicalizedQueryString, 1)); // 计算签名,注意 accessKeySecret 后面要加上字符’&’ $signature = base64_encode(hash_hmac(‘sha1’, $stringToSign, $accessKeySecret . ‘&’, true)); return $signature; } function get_action($data,$Version,$host){ date_default_timezone_set(“GMT”); $dateTimeFormat = ‘Y-m-d\TH:i:s\Z’; global $AccessKey_ID; …

|教程|Cloudflare|自定义缓存文件名后缀|音频.mp4 视频.m3u8|等

本文转自:www.yunloc.com Cloudflare 是全球知名的 CDN 服务商,提供免费和付费的加速和网站保护服务。百度云加速的国外节点就是和 cloudflare 合作使用的 cloudflare 的节点。只不过是因为中文网站接入他们家 CDN 后速度一般,所以我们国内网站接入的并不是很多。但是,一般海外网站如果需要用到 CDN 网站加速和安全的较多的会选择 Cloudflare CDN 服务。   Cloudflare 默认仅根据下面的文件扩展名缓存静态内容资源,是不会音频和视频文件的, 默认文件扩展名的缓存: bmp ejs jpeg pdf ps ttf class eot jpg pict svg webp css eps js pls svgz woff csv gif mid png swf woff2 doc ico midi ppt tif xls docx jar otf pptx tiff …

使用Censys 查询CDN|如Cloudflare后面的真实服务器IP地址 与对应防范

Censys是一个可恨又可爱的搜索联网设备信息的新型搜索引擎, 利用他可以搜索到很多有用的信息, 比如通过ssl证书查找到CDN后面背后的真实IP.   https://censys.io/ 以某论坛为例, (算了, 不截图了,自己查找吧) 防范: 1, 建议屏蔽所有Censys段 https://censys.io/ipv4?q=censys.io 搜索censys的ip段并屏蔽. 如下面两个段 198.108.0.0/16 141.212.0.0/16 2, 或者屏蔽除了CDN以外所有IP访问. (推荐, 但请注意操作, 别把自己给屏蔽了) 3, 如果是cloudflare用户, 也可以使用argo-tunnel https://www.cloudflare.com/zh-cn/products/argo-tunnel/ https://developers.cloudflare.com/argo-tunnel/quickstart/ 其他查询Cloudflare源IP的相关工具 http://www.crimeflare.org:82/ https://securitytrails.com

微信扫一扫,分享到朋友圈

cloudflare最新ddns脚本 2020.5.2号 解决老版本脚本无法更新ip