#!/bin/bash
#完善授权信息之后的几个变量内容
#用法: bash cfddns.sh 二级域名
which jq >/dev/null 2>&1 || yum install jq -y >/dev/null 2>&1
which jq >/dev/null 2>&1 || yum install jq -y >/dev/null 2>&1
path0="/cfddns"
function messageSend() {
message=$1
#your messageSend code
}
###################### 监测日志格式 ########################
# 监测日志保存位置
log_file="$path0/cloudflare.log"
#日志开关,touch这个文件以打开日志查看脚本执行反馈
logSwitch="$path0/logon"
if [ ! -f "$log_file" ];then touch "$log_file";fi
log() {
if [ -f "$logSwitch" ];then
if [ "$1" ]; then
echo -e "[$(date)] - $1" >> $log_file
fi
fi
}
# 告警文件位置
# 连续多少次失败后发送告警,每分钟检测就是30分钟连续失败则告警一次
alertTime=30
alert_file="$path0/alert"
if [ ! -f "$alert_file" ];then touch "$alert_file";fi
function AlertLog(){
alertMessage=$1
echo -e "[$(date)] - $1" >> "${alert_file}"
if [ "$(grep -w "$alertMessage" "${alert_file}" | wc -l)" == "${alertTime}" ];then
messageSend "$HOSTNAME #cfddns $alertMessage 已经连续30分钟出现!"
log "ALERT !!!!!!!!!! $alertMessage 已经连续30分钟出现!!!!!!!!!!!"
fi
}
function AlertClear(){
alertMessage=$1
if [ "$alertMessage" != "" ];then sed -i "/$alertMessage/d;/^$/d" "${alert_file}";fi
}
#获取结果ip
function printResult(){
if $(grep -q total_count "${tmpFile}");then
jq .result[].$1 "${tmpFile}" | sed 's#"##g'
else
jq .result.$1 "${tmpFile}" | sed 's#"##g'
fi
}
############### 授权信息(需修改成你自己的) ################
#APIurl
APIurl="https://api.cloudflare.com/client/v4/zones"
# CloudFlare 注册邮箱
auth_email=""
if [ 123"$auth_email" == 123 ];then
AlertLog '脚本内置参数 auth_email :注册邮箱未填入'
exit 1
fi
AlertClear '脚本内置参数 auth_email'
# CloudFlare Global API Key,
auth_key=""
if [ 123"$auth_key" == 123 ];then
AlertLog '脚本内置参数 auth_key :Global API Key未填入'
exit 1
fi
AlertClear '脚本内置参数 auth_key'
# 做 DDNS 的根域名
zone_name=""
if [ 123"$zone_name" == 123 ];then
AlertLog '脚本内置参数 zone_name :根域名未填入'
exit 1
fi
AlertClear '脚本内置参数 zone_name'
# 根域名id
zone_identifier=""
if [ 123"$zone_identifier" == 123 ];then
AlertLog '脚本内置参数 zone_identifier :根域名id未填入'
exit 1
fi
AlertClear '脚本内置参数 zone_identifier'
# 做 DDNS 的域名,二级域名,比如 www.cloudflare.com 的 www
record_name="$1"
if [ 123"$record_name" == 123 ];then
AlertLog '脚本参数1:二级域名缺失'
exit 1
fi
AlertClear '脚本参数1'
# 域名类型,IPv4 为 A,IPv6 则是 AAAA
record_type="A"
#二级域名id
record_identifier_file="$path0/record_identifier.ids"
###################### 修改配置信息 #######################
# IPv6 检测服务,本站检测服务仅在大陆提供
#ip=$(curl -s https://ipv6.vircloud.net)
# IPv4 检测服务 curl -s http://ipv4.icanhazip.com
ipAPI1="https://ipv4.icanhazip.com"
ipAPI2="http://ifconfig.me"
# 变动前的公网 IP 保存位置
if [ ! -f "$path0" ];then mkdir -p "$path0" ;fi
ip_file="$path0/ip.txt"
if [ ! -f "$ip_file" ];then touch "$ip_file";fi
# api返回信息结果临时文件
tmpFile="$path0/tmp"
log "检测开始……"
ip=$(curl -s "$ipAPI1")
if ! $(echo "${ip}" | egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$');then
log "获取外网ip错误,接口爲 $ipAPI1 ,尝试从服务器获取……"
ip=$(curl -s "$ipAPI2")
if ! $(echo "${ip}" | egrep -q '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$');then
AlertLog "获取外网IP"
exit 1
fi
fi
AlertClear "获取外网IP"
function getResult(){
action=$1
log "操作类型:$action\tAPI结果处理……"
#检测结果文件
if [ ! -f "$tmpFile" ];then log "操作类型:$action\t获取结果文件丢失,等待下次处理";return 1;fi
#api错误类
log "操作类型:$action\tAPI结果数据处理1……"
success=$(jq .success "${tmpFile}" | sed 's#"##g')
total_count=$(jq .result_info.total_count "${tmpFile}" | sed 's#"##g')
#检测api返回结果,success 或 total_count 爲空则返回
if [ "${success}" == "null" ] || [ "${success}" != "true" ];then
errorCode=$(jq .errors[].code "${tmpFile}" | sed 's#"##g')
errorMessage=$(jq .errors[].message "${tmpFile}" | sed 's#"##g')
APIErrors="errors\tcode:${errorCode}\tmessage:${errorMessage}"
log "操作类型:$action\t获取结果:\t${APIErrors},获取失败,分析错误代码……"
case "${errorCode}" in
"81044")
log "操作类型:$action\t线上不存在记录"
return 0
;;
*)
log "操作类型:$action\t${errorMessage}"
;;
esac
AlertLog "API请求错误 ${APIErrors}"
return 1
fi
AlertClear "API请求错误"
#检测返回个数
log "操作类型:$action\tAPI结果数据处理2……"
if [ "${total_count}" == "0" ];then log "操作类型:$action\t获取结果:\t0,没有查询到信息";return 0;fi
#超过一个结果
if [ "${total_count}" != "null" ] && [ "${total_count}" -gt "1" ];then
if [ "$action" == "recheck" ];then #检测操作 爲cf线上错误,直接返回
log "操作类型:$action\t获取结果:\t爲CF线上错误,id ${total_count} 个数爲 ${total_count}"
messageSend "$HOSTNAME #cfddns CF线上错误 id $2 查询到了2个记录!"
return 1
elif [ "$action" == "search" ];then #搜索操作 只保留一个
log "操作类型:$action\t获取结果:查询域名解析个数爲 ${total_count} 个"
record_id=""
for record in $(printResult id) ;do
if [ "$record_id" == "" ];then #获取一个id
record_id=$record
log "操作类型:$action\t获取结果:保留 id 爲 ${total_count} 的解析"
else #其馀删除
log "操作类型:$action\t获取结果:删除 id 爲 ${total_count} 的解析"
curl -s -X DELETE "$APIurl/${zone_identifier}/dns_records/${record}" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" >/dev/null 2>&1
fi
done
echo "$record_id"
return 0
fi
fi
#返回结果
log "操作类型:$action\tAPI结果数据处理完成……"
printResult id
return 0
}
function getrecord_id(){
log "本地数据检测……"
record_identifier=""
if [ -f "$record_identifier_file" ];then
#获取本地解析id
log "尝试获取本地记录id……"
record_identifier=$(cat "$record_identifier_file")
record_count=$(echo $record_identifier | sed 's# #\n#g' | wc -l)
if [ "$record_count" != "1" ];then #本地数据 异常:爲空;多个数值
log "本地数据错误……"
log "本地id信息错误,重置本地数据"
record_identifier="" #重置数据
cd . > "$record_identifier_file"
elif [ "$record_identifier" != "" ];then #本地数据 正常
#验证线上数据
log "以本地数据检测线上数据……"
curl -s -X GET "$APIurl/${zone_identifier}/dns_records/${record_identifier}" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" >"${tmpFile}" 2>&1
#再次获取id
record_identifier=$(getResult recheck "${record_identifier}")
if [ $? == 1 ];then
log "线上数据获取错误,等待下次检测";return 1
fi
if [ "$(printResult name)" != "${record_name}.${zone_name}" ];then
log "本地数据和待处理域名不匹配,重置本地数据……"
record_identifier="" #重置数据
cd . > "$record_identifier_file"
fi
fi
fi
#如果异常
if [ "${record_identifier}" == "" ];then #本地数据爲空
log "id爲空,尝试搜索线上是否存在域名解析数据……"
#搜索线上解析鬱闷
curl -s -X GET "$APIurl/${zone_identifier}/dns_records?name=${record_name}.${zone_name}&proxied=false&type=$record_type" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" > "${tmpFile}" 2>&1
record_identifier=$(getResult search)
if [ $? == 0 ];then
if [ "$record_identifier" != "" ];then #搜索到了
log "线上id获取成功!写入本地记录……"
echo "$record_identifier" > $record_identifier_file
return 0
else #没有搜索到记录 则新增
log "没有查询到记录,尝试新增……"
curl -s -X POST "$APIurl/$zone_identifier/dns_records" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"type\":\"$record_type\",\"name\":\"${record_name}.${zone_name}\",\"content\":\"$ip\",\"ttl\":120,\"proxied\":false}" > "${tmpFile}" 2>&1
record_identifier=$(getResult recheck)
if [ $? == 0 ] && [ "${record_identifier}" != "" ];then
log "新增成功!写入本地记录……"
messageSend "$HOSTNAME #cfddns $1 新增解析成功,当前IP:$ip!"
echo "$record_identifier" > $record_identifier_file
return 0
fi
fi
fi
return 1
fi
#如果查询到了
return 0
}
###################### 获取域名授权及新增 ######################
getrecord_id
if [ $? == 1 ];then exit 1;fi
log "数据获取成功……"
if [ "$ipOnline" == "" ];then
ipOnline=$(printResult content)
fi
###################### 判断 IP 是否变化 ####################
if [ -f "$ip_file" ]; then
old_ip=$(cat "$ip_file")
#如果查询ip等于本地存储ip
if [ "$ip" == "$old_ip" ] && [ "$ip" == "$ipOnline" ]; then
log "IP has not changed."
exit 0
fi
if [ "$ip" == "$ipOnline" ] && [ "$ip" != "$old_ip" ];then
log "ip正常,修正本地数据……"
echo "$ip" > "$ip_file"
exit 0
fi
fi
###################### 更新 DNS 记录 ######################
log "ip变动,修正线上数据……"
curl -s -X PUT "$APIurl/$zone_identifier/dns_records/$record_identifier" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"type\":\"$record_type\",\"name\":\"${record_name}.${zone_name}\",\"content\":\"$ip\",\"ttl\":120,\"proxied\":false}" >/dev/null 2>&1
record_identifier=$(getResult recheck "${record_identifier}")
if [ $? == 0 ];then
result_ip=$(printResult content)
if [ "$ip" == "$result_ip" ];then
log "修正线上数据成功,写入本地……"
messageSend "$HOSTNAME #cfddns $1 解析修改成功,当前IP:$ip!"
echo "$ip" > "$ip_file"
exit 0
fi
fi
log "处理完成!"
© 著作权归作者所有
下一篇: cnbeta rss 内容解析
文章评论(0)