Cloudflare Ddns 脚本

常见的方案都是定时运行,有网友给出更好的方案,监听接口的变化,有变化时才执行

参考:

https://appscross.com/blog/one-click-ddns6-for-linux.html

openwrt

api: https://developers.cloudflare.com/api/operations/dns-records-for-a-zone-update-dns-record

钩子脚本

1
2
3
4
5
6
7
vim /etc/hotplug.d/iface/99-custom-script
===
#!/bin/sh
/root/cloudflare.sh
===

chmdod +x /etc/hotplug.d/iface/99-custom-script

更新脚本

更新单个域名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
vim /root/cloudflare.sh
===
#!/bin/sh
# 监测的网络接口,例如 eth0
# 查看所有接口
# ifconfig -a 
interface="br-lan"

ZoneID="YOUR_ZONE_ID"
RecordID="YOUR_RECORD_ID"
Email="YOUR_EMAIL"
Token="YOUR_API_TOKEN"
Fullname="YOUR_FULL_DOMAIN_NAME"

current_ipv6=$(ip -6 addr show dev $interface | awk '/inet6 .* global/  && !/deprecated/  { print $2 }' | awk -F "/" '{ print $1 }')
echo "当前的ipv6地址: $current_ipv6"

updatedns(){
  response=$(curl -s -o /dev/null -w %{http_code} --request PUT \
  --url "https://api.cloudflare.com/client/v4/zones/${ZoneID}/dns_records/${RecordID}" \
  --header "Content-Type: application/json" \
  --header "X-Auth-Email: ${Email}" \
  --header "Authorization: Bearer ${Token}" \
  --data "{
  \"type\": \"AAAA\",
  \"name\": \"${Fullname}\",
  \"content\": \"${current_ipv6}\",
  \"proxied\": false
  }")
  if [ "$response" == "200" ]; then
    echo "DNS记录更新成功"
    echo "$current_ipv6" > /tmp/previous_ipv6
  else
    echo "DNS记录更新失败,HTTP状态码: $response"
  fi
}

# 检查是否获取到了有效的IPv6地址
if [ -n "$current_ipv6" ]; then
    # 保存之前的IPv6地址,如果为空则是第一次运行
    if [ -f /tmp/previous_ipv6 ]; then
        previous_ipv6=$(cat /tmp/previous_ipv6)
    else
        previous_ipv6=""
    fi

    # 检查当前IPv6地址是否和之前保存的不同
    if [ "$current_ipv6" != "$previous_ipv6" ]; then
        echo "开始更新"
        updatedns
    else
        echo "ipv6地址未发生变化,不需要更新"
    fi
else
    # 在没有有效IPv6地址的情况下执行的操作,或者可以选择跳过
    echo "当前未获取到有效的IPv6地址"
fi

===

chmod +x /root/cloudflare.sh

更新多个域名

关联数组只支持在bash中运行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#!/bin/bash

# 监测的网络接口,例如 eth0
interface="br-lan"

# 共享的 Cloudflare 帐户信息
Email="YOUR_EMAIL"
Token="YOUR_API_TOKEN"
ZoneID="YOUR_ZONE_ID"

# Cloudflare 域名信息数组
# 每个域名的信息包括:Fullname 和 RecordID
declare -A domains=(
  ["YOUR_FULL_DOMAIN_NAME1"]="YOUR_RECORD_ID1"
  ["YOUR_FULL_DOMAIN_NAME2"]="YOUR_RECORD_ID2"
  # 可以根据需要添加更多 Fullname 和 RecordID
)

current_ipv6=$(ip -6 addr show dev $interface | awk '/inet6 .* global/ && !/deprecated/  { print $2 }' | awk -F "/" '{ print $1 }')
echo "当前的ipv6地址: $current_ipv6"

updatedns(){
  for Fullname in "${!domains[@]}"; do
    RecordID="${domains[$Fullname]}"

    # 在这里可以继续进行域名更新的操作
    response=$(curl -s -o /dev/null -w %{http_code} --request PUT \
      --url "https://api.cloudflare.com/client/v4/zones/${ZoneID}/dns_records/${RecordID}" \
      --header "Content-Type: application/json" \
      --header "X-Auth-Email: ${Email}" \
      --header "Authorization: Bearer ${Token}" \
      --data "{
        \"type\": \"AAAA\",
        \"name\": \"${Fullname}\",
        \"content\": \"${current_ipv6}\",
        \"proxied\": false
      }")

    if [ "$response" == "200" ]; then
      echo "${Fullname} DNS记录更新成功"
    else
      echo "${Fullname} DNS记录更新失败,HTTP状态码: $response"
    fi
  done
}

# 检查是否获取到了有效的IPv6地址
if [ -n "$current_ipv6" ]; then
    # 保存之前的IPv6地址,如果为空则是第一次运行
    if [ -f /tmp/previous_ipv6 ]; then
        previous_ipv6=$(cat /tmp/previous_ipv6)
    else
        previous_ipv6=""
    fi

    # 检查当前IPv6地址是否和之前保存的不同
    if [ "$current_ipv6" != "$previous_ipv6" ]; then
        echo "开始更新"
        updatedns
        echo "$current_ipv6" > /tmp/previous_ipv6
    else
        echo "ipv6地址未发生变化,不需要更新"
    fi
else
    # 在没有有效IPv6地址的情况下执行的操作,或者可以选择跳过
    echo "当前未获取到有效的IPv6地址"
fi

查询 RecordID

1
2
3
4
5
6
7
#!/bin/bash
ZONE_ID="你的 Zone ID"
API_TOKEN="你的API Token"
read -p "请输入子域名: " NAME
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$NAME" \
-H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json"

ubuntu/debian

使用 NetworkManager 的派发器

https://networkmanager.dev/docs/api/latest/NetworkManager-dispatcher.html

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
vim /etc/NetworkManager/dispatcher.d/99-ip6-address-change

===

#!/bin/bash
IFACE="$1"
REASON="$2"
# 调试打印
# echo "$(date) : iface: $IFACE, reason: $REASON" >> /tmp/ipv6change.log
if [ "$IFACE" = "wlan0" ] && [ "$REASON" = "dhcp6-change" ]; then
    # 调用 DNS 记录更新脚本
    /root/cloudflare.sh
fi

===

chmod +x /etc/NetworkManager/dispatcher.d/99-ip6-address-change

==但是实测上级路由重新分配ipv6的时候, 并没有触发==

build with Hugo, theme Stack, visits 0