最近入手了一些家宽和动态ip的小鸡,刚好完整的记录一下ddns的流程弥补一下以往大多数帖子只有脚本没有完整过程的问题
需要准备的有
一个在CloudFlare解析的域名
一台需要ddns的小鸡
一个CloudFlare账户
获取Global API Key
首先登陆CloudFlare官网,并找到Profile按钮
随后进入API Token页面
找到页面中的Global API Key选项
进入查看并接受验证码,得到的密码就是Global API Key
创建目标解析
进入CloudFlare域名解析页面,为目标域名添加”A”或者”AAAA”记录,并关闭小黄云
其中A记录对应ipv4地址,AAAA记录对应ipv6地址
保存后记下这里的记录”test.xxxxxx.xxx”为RECORD_NAME
找到ZONE_ID
一般来说ZONE_ID在域名页面右侧栏的最下方如图位置
找到后将其机为ZONE_ID
开始配置
👋手动配置
在必要的信息收集完毕后,即可进入目标小鸡开始配置,首先运行如下命令
sudo apt update
随后安装必要的依赖
sudo apt install curl jq cron -y
随后开始编辑运行文件
sudo nano /usr/local/bin/cloudflare-ddns.sh
在目标文件中输入如下脚本
#!/usr/bin/env bash
set -euo pipefail
GLOBAL_API_KEY="your_new_global_api_key_here"
EMAIL="your_cf_email" # CF账户邮箱地址
ZONE_ID="zone_id"
RECORD_NAME="test.xxxxxx.xxx"
RECORD_TYPE="A" # Use "A" for IPv4 or "AAAA" for IPv6
IP_SERVICE_V4="https://icanhazip.com" # 国内小鸡用https://4.ipw.cn
IP_SERVICE_V6="https://icanhazip.com" # 国内小鸡用https://6.ipw.cn
for cmd in curl jq; do
if ! command -v "$cmd" &>/dev/null; then
echo "Error: Required command '$cmd' is not installed." >&2
exit 1
fi
done
case "$RECORD_TYPE" in
A) CURRENT_IP=$(curl -s -4 --fail --connect-timeout 10 "$IP_SERVICE_V4" | tr -d '[:space:]') || true ;;
AAAA) CURRENT_IP=$(curl -s -6 --fail --connect-timeout 10 "$IP_SERVICE_V6" | tr -d '[:space:]') || true ;;
*)
echo "Error: Invalid RECORD_TYPE '$RECORD_TYPE'. Must be 'A' or 'AAAA'." >&2
exit 1
;;
esac
if [[ -z "$CURRENT_IP" ]]; then
echo "Error: Failed to fetch public IP. Check your network connection." >&2
exit 1
fi
CF_RESPONSE=$(curl -s --connect-timeout 10 \
-H "X-Auth-Email: $EMAIL" \
-H "X-Auth-Key: $GLOBAL_API_KEY" \
-H "Content-Type: application/json" \
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${RECORD_NAME}&type=${RECORD_TYPE}") || true
RECORD_ID=$(echo "$CF_RESPONSE" | jq -r '.result[0].id // empty')
DNS_IP=$(echo "$CF_RESPONSE" | jq -r '.result[0].content // empty')
if [[ -z "$RECORD_ID" ]]; then
echo "Error: Failed to fetch RECORD_ID. Check your API credentials, ZONE_ID, and RECORD_NAME." >&2
exit 1
fi
# Skip update if IP has not changed
if [[ "$CURRENT_IP" == "$DNS_IP" ]]; then
echo "No update needed: $RECORD_NAME is already set to $CURRENT_IP"
exit 0
fi
echo "Updating $RECORD_NAME ($RECORD_TYPE): $DNS_IP -> $CURRENT_IP"
# Update the DNS record using jq to safely construct the JSON payload
UPDATE_RESULT=$(curl -s --connect-timeout 10 -X PUT \
-H "X-Auth-Email: $EMAIL" \
-H "X-Auth-Key: $GLOBAL_API_KEY" \
-H "Content-Type: application/json" \
--data "$(jq -n \
--arg type "$RECORD_TYPE" \
--arg name "$RECORD_NAME" \
--arg content "$CURRENT_IP" \
'{type: $type, name: $name, content: $content, proxied: false}')" \
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}") || true
if echo "$UPDATE_RESULT" | jq -e '.success == true' > /dev/null; then
echo "Success: $RECORD_NAME ($RECORD_TYPE) updated to $CURRENT_IP"
else
echo "Error: Update failed. Cloudflare API response:" >&2
echo "$UPDATE_RESULT" | jq '.' >&2
exit 1
fi
把前面几步获取的信息后填入脚本,而后运行
chmod +x /usr/local/bin/cloudflare-ddns.sh
之后运行脚本
bash /usr/local/bin/cloudflare-ddns.sh
可以查看CF后台是否正确更新,接下来配置定时更新任务,运行如下命令
sudo tee /etc/cron.d/cloudflare-ddns > /dev/null <<EOF
# Cloudflare DDNS - runs every 5 minutes
*/5 * * * * root /usr/local/bin/cloudflare-ddns.sh >> /var/log/cloudflare-ddns.log 2>&1
EOF
并设置正确的文件权限
sudo chmod 644 /etc/cron.d/cloudflare-ddns
至此手动配置ddns已经完成
🚀一键配置
省流,直接运行
curl -fsSL https://raw.githubusercontent.com/xhhcn/ddns/main/setup.sh | sudo bash
输入对应信息即可
之后就可以通过绑定的域名登陆ssh啦,例如
ssh root@test.xxxxxx.xx
结束语
当前ddns有许多合适且有力的工具,但是对于我这样追求简约和手搓的极简主义者而言或许一步一步配置下来才会更有意思
完结撒花🎉
脚本开源地址
