实时监测公网 IP 变化并自动更新域名解析
接着上回写的家里有动态公网ip,然后想利用这个公网ip实现对外提供服务,谈到了需要实现实时监测公网 IP 变化并自动更新域名解析。
要实现 “实时监测公网 IP 变化并自动更新域名解析”,可以通过 Shell 脚本 + 定时任务 实现,核心逻辑是:定期获取公网 IP → 与上次记录的 IP 对比 → 若变化则调用域名解析 API 更新。以下是具体实现方案(以阿里云域名为例,其他厂商思路类似):
一、准备工作
域名与解析平台:确保你有一个域名(如在阿里云、腾讯云、Cloudflare 等平台购买),并获取该平台的 API 密钥(用于调用接口更新解析)。
以阿里云为例:需在 阿里云 AccessKey 控制台 创建 AccessKey ID 和 Secret。
依赖工具:脚本需要 curl(获取公网 IP)和 jq(解析 JSON,可选),先安装:
# Ubuntu/Debian
apt install curl jq
# CentOS/RHEL
yum install curl jq
二、完整脚本实现(阿里云为例)
创建 update.sh 脚本,功能包括:获取公网 IP、对比 IP 变化、调用阿里云 API 更新解析。
公网IP动态解析自动更新脚本如下:
vim update.sh
#!/bin/bash
#配置信息(替换为你的参数)
ACCESS_KEY_ID="你的阿里云AccessKey ID"
ACCESS_KEY_SECRET="你的阿里云AccessKey Secret"
DOMAIN="example.com" # 你的域名(如:baidu.com)
RR="home" # 解析记录的主机记录(如:home → home.example.com)
TYPE="A" # 记录类型(A记录对应IPv4)
TTL=600 # 解析生效时间(秒,最小600)
#存储上次IP的文件路径
IP_FILE="/tmp/last_ip.txt"
#1. 获取当前公网IP(使用稳定的接口)
current_ip=$(curl -s 4.ipw.cn | tr -d '\n') # 去换行符
if [ -z "$current_ip" ]; then
echo "获取公网IP失败,请检查网络"
exit 1
fi
#2. 读取上次记录的IP(若文件不存在则创建)
last_ip=""
if [ -f "$IP_FILE" ]; then
last_ip=$(cat "$IP_FILE")
fi
# 3. 对比IP是否变化,未变化则退出
if [ "$current_ip" = "$last_ip" ]; then
echo "公网IP未变化:$current_ip"
exit 0
fi
# 4. IP已变化,调用阿里云API更新解析记录
echo "公网IP已更新:$last_ip → $current_ip,开始更新域名解析..."
#生成时间戳和签名(阿里云API要求)
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
signature_nonce=$(date +%s%N) # 随机数
# 构建请求参数(先获取记录ID,再更新)
params="AccessKeyId=$ACCESS_KEY_ID&Action=DescribeSubDomainRecords&DomainName=$DOMAIN&RRKeyWord=$RR&SignatureMethod=HMAC-SHA1&SignatureNonce=$signature_nonce&SignatureVersion=1.0&SubDomain=$RR.$DOMAIN&Timestamp=$timestamp&Type=$TYPE"
# 计算签名(阿里云签名算法)
encoded_params=$(echo -n "$params" | tr -d '\n' | perl -pe 's/([^A-Za-z0-9_.~-])/sprintf("%%%02X", ord($1))/seg')
string_to_sign="GET&%2F&${encoded_params}"
signature=$(echo -n "$string_to_sign" | openssl dgst -sha1 -hmac "${ACCESS_KEY_SECRET}&" -binary | base64)
encoded_signature=$(echo -n "$signature" | perl -pe 's/([^A-Za-z0-9_.~-])/sprintf("%%%02X", ord($1))/seg')
# 第一步:获取解析记录ID(RecordId)
record_response=$(curl -s "https://alidns.aliyuncs.com/?$params&Signature=$encoded_signature")
record_id=$(echo "$record_response" | jq -r '.DomainRecords.Record[0].RecordId')
if [ "$record_id" = "null" ]; then
echo "获取解析记录ID失败,响应:$record_response"
exit 1
fi
# 第二步:更新解析记录
update_params="AccessKeyId=$ACCESS_KEY_ID&Action=UpdateDomainRecord&RecordId=$record_id&RR=$RR&SignatureMethod=HMAC-SHA1&SignatureNonce=$signature_nonce&SignatureVersion=1.0&Timestamp=$timestamp&Type=$TYPE&Value=$current_ip&TTL=$TTL"
encoded_update_params=$(echo -n "$update_params" | tr -d '\n' | perl -pe 's/([^A-Za-z0-9_.~-])/sprintf("%%%02X", ord($1))/seg')
update_string_to_sign="GET&%2F&${encoded_update_params}"
update_signature=$(echo -n "$update_string_to_sign" | openssl dgst -sha1 -hmac "${ACCESS_KEY_SECRET}&" -binary | base64)
encoded_update_signature=$(echo -n "$update_signature" | perl -pe 's/([^A-Za-z0-9_.~-])/sprintf("%%%02X", ord($1))/seg')
update_response=$(curl -s "https://alidns.aliyuncs.com/?$update_params&Signature=$encoded_update_signature")
# 检查更新结果
if echo "$update_response" | jq -e '.RecordId' >/dev/null; then
echo "域名解析更新成功!新IP:$current_ip"
echo "$current_ip" > "$IP_FILE" # 记录当前IP
else
echo "更新失败,响应:$update_response"
exit 1
fi
三、脚本使用说明
3.1 配置参数:打开脚本,替换以下内容为你的实际信息:
- ACCESS_KEY_ID 和 ACCESS_KEY_SECRET:阿里云 AccessKey(需开启 “DNS 管理” 权限)。
- DOMAIN:你的域名(如 mydomain.com)。
- RR:主机记录(如 home → 最终解析 home.mydomain.com)。
3.2 添加执行权限:
chmod +x update.sh
3.3. 测试脚本:手动执行一次,检查是否能正常更新:
./update.sh
若输出 “域名解析更新成功”,说明配置正确。
四、设置定时任务
通过 crontab 定时执行脚本,实现 “每 5 分钟检查一次 IP 变化”:
- 编辑定时任务:
crontab -e
- 添加以下内容(每 5 分钟执行一次):
*/5 * * * * /path/to/update.sh >> /var/log/update.log 2>&1
(将 /path/to/ 替换为脚本实际路径,日志文件用于排查问题)
- 保存退出,定时任务会自动生效。
五、其他平台适配思路
如果你的域名在其他平台(如腾讯云、Cloudflare),核心逻辑不变,只需替换 “更新解析” 的 API 部分:
- 1.腾讯云:参考 腾讯云 DNS 解析 API,修改脚本中 “获取记录 ID” 和 “更新记录” 的 API 调用地址及参数。
- 2.Cloudflare:使用 Cloudflare API v4,通过 Token 认证更新解析。
2627

被折叠的 条评论
为什么被折叠?



