note/tech/动态IP情况下如何绑定域名.md
2025-11-19 10:16:05 +08:00

150 lines
5.2 KiB
Markdown
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 动态IP情况下如何绑定域名
[toc]
## 使用场景
主要是用在家庭宽带等每次重启都会自动获取动态IP的场景下。这时候如果需要访问我们的NAS或者内部服务器则需要实时的将IP与域名重新绑定。
## 使用工具
1. 域名在cloudflare上。如果不在那个上面则需要重新写脚本
2. 获取到域名的global key我们在[5.v2ray和trojan的翻墙配置](:/e80ad79f492c4c3d91bd85aa014bfc78)里也提到了这一点;
3. 一台在内部的服务器/电脑linux系统。
## 开始制作
1. 获取你在cloudflare上面的key在这个链接里找https://www.cloudflare.com/a/account/my-account 大概是这样子的c8729fd0febf3f59a0102a047558ac07f1d51
2. 确保内部电脑可以正常上网;下载脚本:
3. 打开脚本,填入参数:
```bash
#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail
# API key, see https://www.cloudflare.com/a/account/my-account,
# incorrect api-key results in E_UNAUTH error
CFKEY="cc729fd0febf3f59a0102a047558aa07f1d51" #这是你的global key
# Username, eg: user@example.com
CFUSER="maxwellxzy@gmail.com" #你在cloudflare的账号
# Zone name, eg: example.com
CFZONE_NAME="disbaidu.com" #你要更新的域名的主域名根域名不带www
# Hostname to update, eg: homeserver.example.com
CFRECORD_NAME="read.disbaidu.com" #这是你要更新的dns的域名
# Record type, A(IPv4)|AAAA(IPv6), default IPv4
CFRECORD_TYPE=A #ipv4是这个
# Cloudflare TTL for record, between 120 and 86400 seconds
CFTTL=3600
# Ignore local file, update ip anyway
FORCE=false
WANIPSITE="http://ipv4.icanhazip.com"
# Site to retrieve WAN ip, other examples are: bot.whatismyipaddress.com, https://api.ipify.org/ ...
if [ "$CFRECORD_TYPE" = "A" ]; then
:
elif [ "$CFRECORD_TYPE" = "AAAA" ]; then
WANIPSITE="http://ipv6.icanhazip.com"
else
echo "$CFRECORD_TYPE specified is invalid, CFRECORD_TYPE can only be A(for IPv4)|AAAA(for IPv6)"
exit 2
fi
# get parameter
while getopts k:u:h:z:t:f: opts; do
case ${opts} in
k) CFKEY=${OPTARG} ;;
u) CFUSER=${OPTARG} ;;
h) CFRECORD_NAME=${OPTARG} ;;
z) CFZONE_NAME=${OPTARG} ;;
t) CFRECORD_TYPE=${OPTARG} ;;
f) FORCE=${OPTARG} ;;
esac
done
# If required settings are missing just exit
if [ "$CFKEY" = "" ]; then
echo "Missing api-key, get at: https://www.cloudflare.com/a/account/my-account"
echo "and save in ${0} or using the -k flag"
exit 2
fi
if [ "$CFUSER" = "" ]; then
echo "Missing username, probably your email-address"
echo "and save in ${0} or using the -u flag"
exit 2
fi
if [ "$CFRECORD_NAME" = "" ]; then
echo "Missing hostname, what host do you want to update?"
echo "save in ${0} or using the -h flag"
exit 2
fi
# If the hostname is not a FQDN
if [ "$CFRECORD_NAME" != "$CFZONE_NAME" ] && ! [ -z "${CFRECORD_NAME##*$CFZONE_NAME}" ]; then
CFRECORD_NAME="$CFRECORD_NAME.$CFZONE_NAME"
echo " => Hostname is not a FQDN, assuming $CFRECORD_NAME"
fi
# Get current and old WAN ip
WAN_IP=`curl -s ${WANIPSITE}`
WAN_IP_FILE=$HOME/.cf-wan_ip_$CFRECORD_NAME.txt
if [ -f $WAN_IP_FILE ]; then
OLD_WAN_IP=`cat $WAN_IP_FILE`
else
echo "No file, need IP"
OLD_WAN_IP=""
fi
# If WAN IP is unchanged an not -f flag, exit here
if [ "$WAN_IP" = "$OLD_WAN_IP" ] && [ "$FORCE" = false ]; then
echo "WAN IP Unchanged, to update anyway use flag -f true"
exit 0
fi
# Get zone_identifier & record_identifier
ID_FILE=$HOME/.cf-id_$CFRECORD_NAME.txt
if [ -f $ID_FILE ] && [ $(wc -l $ID_FILE | cut -d " " -f 1) == 4 ] \
&& [ "$(sed -n '3,1p' "$ID_FILE")" == "$CFZONE_NAME" ] \
&& [ "$(sed -n '4,1p' "$ID_FILE")" == "$CFRECORD_NAME" ]; then
CFZONE_ID=$(sed -n '1,1p' "$ID_FILE")
CFRECORD_ID=$(sed -n '2,1p' "$ID_FILE")
else
echo "Updating zone_identifier & record_identifier"
CFZONE_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=$CFZONE_NAME" -H "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -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 "X-Auth-Email: $CFUSER" -H "X-Auth-Key: $CFKEY" -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
# If WAN is changed, update cloudflare
echo "Updating DNS to $WAN_IP"
RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CFZONE_ID/dns_records/$CFRECORD_ID" \
-H "X-Auth-Email: $CFUSER" \
-H "X-Auth-Key: $CFKEY" \
-H "Content-Type: application/json" \
--data "{\"id\":\"$CFZONE_ID\",\"type\":\"$CFRECORD_TYPE\",\"name\":\"$CFRECORD_NAME\",\"content\":\"$WAN_IP\", \"ttl\":$CFTTL}")
if [ "$RESPONSE" != "${RESPONSE%success*}" ] && [ "$(echo $RESPONSE | grep "\"success\":true")" != "" ]; then
echo "Updated succesfuly!"
echo $WAN_IP > $WAN_IP_FILE
exit
else
echo 'Something went wrong :('
echo "Response: $RESPONSE"
exit 1
fi
```
4. 接下来,就要让它执行:
```
$sudo chmod +x cf-v4-ddns.sh
```
5. 加入定时任务:
```
sudo crontab -e
```
```ini
5 * * * * bash /opt/cf-ddns/cf-v4-ddns.sh >> /var/log/cf-ddns.log
```