DDNS域名转发

DDNS域名转发

DDNS域名转发

1.下载 DDNS 脚本:

curl https://raw.githubusercontent.com/aipeach/cloudflare-api-v4-ddns/master/cf-v4-ddns.sh > /root/cf-v4-ddns.sh && chmod +x /root/cf-v4-ddns.sh  #里面有写错误,可以直接使用下面的脚本

或直接复制编辑(注意修改脚本内中文标注的地方,上同)

#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

# 自动更新您的 CloudFlare DNS 记录到当前 IP,动态 DNS
# 可以检索 Cloudflare 域名 ID 和列出区域,因为,懒
# Sparkle 版本

# 放置在:
# sudo wget https://raw.githubusercontent.com/zanjie1999/cloudflare-api-v4-ddns/master/cf-v4-ddns.sh -O /usr/local/bin/cf-ddns.sh
# sudo chmod +x /usr/local/bin/cf-ddns.sh
# 在 `crontab -e` 中添加以下行:
# */2 * * * * /usr/local/bin/cf-ddns.sh >/dev/null 2>&1
# 或者如果需要日志:
# */2 * * * * /usr/local/bin/cf-ddns.sh >> /var/log/cf-ddns.log 2>&1

# 用法:
# cf-ddns.sh -k cloudflare-api-token \
#            -h host.example.com \     # 要更新的记录的完整域名
#            -z example.com \          # 如果忘记会显示所有区域,但你需要这个
#            -t A|AAAA                 # 指定 IPv4/IPv6,默认:IPv4
#            -p 缓存文件路径            # 默认 /$HOME/.cf

# 可选标志:
#            -f false|true \           # 强制 DNS 更新,不考虑本地存储的 IP

# 默认配置

# API 令牌,请参阅 https://dash.cloudflare.com/profile/api-tokens
# 填写 API 令牌,注意是 API 令牌,没有就通过上面链接创建一个,不是 Global API Key
CFTOKEN=${CFTOKEN:-""}

# 区域名称,例如: example.com
# 你的主域名,DNS 必须在 CloudFlare
CFZONE_NAME=${CFZONE_NAME:-""}

# 要更新的主机名,例如: homeserver.example.com 或 example.com
# 你要解析的子域名,需先在 CloudFlare 手动解析一条相同的 A 记录
CFRECORD_NAME=${CFRECORD_NAME:-""}

# 记录类型,A(IPv4)|AAAA(IPv6),默认 IPv4
# 解析类型,默认 A 记录
CFRECORD_TYPE=${CFRECORD_TYPE:-"A"}

# Cloudflare 记录的 TTL,介于 120 和 86400 秒之间
# TTL 值,填 0 为默认
CFTTL=${CFTTL:-120}

# 忽略本地文件,无论如何更新 IP
FORCE=${FORCE:-false}

# 缓存文件路径,默认 /$HOME/.cf
CFFILE_PATH=${CFFILE_PATH:-"$HOME/.cf"}

# 获取当前 WAN IP 的站点
WANIPSITE="http://ipv4.icanhazip.com"
ALT_WANIPSITES=("http://v4.ident.me" "https://api.ipify.org")

# 当前日期时间
NOW_DATE_TIME=$(date "+%Y-%m-%d %H:%M:%S")

# 如果记录类型为 AAAA,修改 IP 获取站点
if [ "$CFRECORD_TYPE" = "AAAA" ]; then
  WANIPSITE="http://ipv6.icanhazip.com"
  ALT_WANIPSITES=("http://v6.ident.me" "https://api6.ipify.org")
elif [ "$CFRECORD_TYPE" != "A" ]; then
  echo "$NOW_DATE_TIME $CFRECORD_TYPE 指定无效,CFRECORD_TYPE 只能是 A(用于 IPv4)或 AAAA(用于 IPv6)"
  exit 2
fi

# 获取参数
while getopts k:h:z:t:f:p: opts; do
  case ${opts} in
    k) CFTOKEN=${OPTARG} ;;
    h) CFRECORD_NAME=${OPTARG} ;;
    z) CFZONE_NAME=${OPTARG} ;;
    t) CFRECORD_TYPE=${OPTARG} ;;
    f) FORCE=${OPTARG} ;;
    p) CFFILE_PATH=${OPTARG} ;;
  esac
done

# 如果 CFFILE_PATH 不存在则创建
if [ ! -d "$CFFILE_PATH" ]; then
  mkdir -p "$CFFILE_PATH"
fi

# 如果缺少必要的设置,则退出
if [ -z "$CFTOKEN" ]; then
  echo "$NOW_DATE_TIME 缺少 API 令牌,请访问:https://dash.cloudflare.com/profile/api-tokens 创建"
  echo "$NOW_DATE_TIME 并在 ${0} 中保存或使用 -k 标志"
  exit 2
fi

if [ -z "$CFRECORD_NAME" ]; then
  echo "$NOW_DATE_TIME 缺少主机名,要更新哪个主机?"
  echo "$NOW_DATE_TIME 在 ${0} 中保存或使用 -h 标志"
  exit 2
fi

# 如果主机名不是完整域名
if [ "$CFRECORD_NAME" != "$CFZONE_NAME" ] && [[ "$CFRECORD_NAME" != *".$CFZONE_NAME" ]]; then
  CFRECORD_NAME="$CFRECORD_NAME.$CFZONE_NAME"
  echo "$NOW_DATE_TIME => 主机名不是完整域名,假定为 $CFRECORD_NAME"
fi

# 获取当前和旧的 WAN IP
WAN_IP=$(curl -s --max-time 10 "$WANIPSITE" || for alt_site in "${ALT_WANIPSITES[@]}"; do curl -s --max-time 10 "$alt_site" && break; done)

WAN_IP_FILE="$CFFILE_PATH/.cf-wan_ip_$CFRECORD_NAME.txt"
if [ -f "$WAN_IP_FILE" ]; then
  OLD_WAN_IP=$(cat "$WAN_IP_FILE")
else
  echo "$NOW_DATE_TIME 没有文件,需要 IP"
  OLD_WAN_IP=""
fi

# 如果 WAN IP 未更改且未使用 -f 标志,则退出
if [ "$WAN_IP" = "$OLD_WAN_IP" ] && [ "$FORCE" = false ]; then
  echo "$NOW_DATE_TIME WAN IP 未更改,要强制更新请使用 -f true 标志"
  exit 0
fi

# 获取 zone_identifier 和 record_identifier
ID_FILE="$CFFILE_PATH/.cf-id_$CFRECORD_NAME.txt"
if [ -f "$ID_FILE" ] && [ $(wc -l < "$ID_FILE") -eq 4 ] \
  && [ "$(sed -n '3p' "$ID_FILE")" = "$CFZONE_NAME" ] \
  && [ "$(sed -n '4p' "$ID_FILE")" = "$CFRECORD_NAME" ]; then
    CFZONE_ID=$(sed -n '1p' "$ID_FILE")
    CFRECORD_ID=$(sed -n '2p' "$ID_FILE")
else
    echo "$NOW_DATE_TIME 更新 zone_identifier 和 record_identifier"
    CFZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$CFZONE_NAME" -H "Authorization: Bearer $CFTOKEN" -H "Content-Type: application/json" | grep -Po '(?<="id":")[^"]*' | head -1 )
    CFRECORD_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records?name=$CFRECORD_NAME" -H "Authorization: Bearer $CFTOKEN" -H "Content-Type: application/json"  | grep -Po '(?<="id":")[^"]*' | head -1 )
    echo "$CFZONE_ID" > "$ID_FILE"
    echo "$CFRECORD_ID" >> "$ID_FILE"
    echo "$CFZONE_NAME" >> "$ID_FILE"
    echo "$CFRECORD_NAME" >> "$ID_FILE"
fi

# 如果 WAN IP 已更改,更新 Cloudflare
echo "$NOW_DATE_TIME 更新 DNS 到 $WAN_IP"

RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records/$CFRECORD_ID" \
  -H "Authorization: Bearer $CFTOKEN" \
  -H "Content-Type: application/json" \
  --data "{\"type\":\"$CFRECORD_TYPE\",\"name\":\"$CFRECORD_NAME\",\"content\":\"$WAN_IP\", \"ttl\":$CFTTL}")

if [[ "$RESPONSE" == *"\"success\":true"* ]]; then
  echo "$NOW_DATE_TIME 更新成功!"
  echo "$WAN_IP" > "$WAN_IP_FILE"
  exit 0
else
  echo "$NOW_DATE_TIME 出现错误 :("
  echo "$NOW_DATE_TIME 响应: $RESPONSE"
  exit 1
fi

2.修改 DDNS 脚本并补充相关信息

vi cf-v4-ddns.sh
或者直接打开/root/cf-v4.ddns.sh文件编辑修改后保存

3.运行脚本

./cf-v4-ddns.sh #你设置脚本名字

首次运行脚本,输出内容会显示当前 IP,进入 cloudflare 查看 确保 IP 已变更为当前 IP

4.设置定时任务

将命令添加到系统级别的crontab:将该命令添加到/etc/crontab文件中。要编辑系统级别的crontab,您可以使用以下命令:

sudo nano /etc/crontab

在文件中添加类似于以下内容的行(假设脚本每2分钟执行一次):

*/2 * * * * root /root/cf-v4-ddns.sh >/dev/null 2>&1

另外,确保/root/cf-v4-ddns.sh脚本具有可执行权限,否则cron任务将无法执行该脚本。您可以使用以下命令为脚本添加可执行权限:

chmod +x /root/cf-v4-ddns.sh
LICENSED UNDER CC BY-NC-SA 4.0