Synology は cloudflare の API 経由で DDNS を自動的に更新します
2025-01-23 18:32 ≈ 1.4k字 ≈ 6分

私は以前、freedns を ddns として使用していましたが、これは実は非常に便利です。freedns には dns を更新するための無料のインターフェイスがあり、curl を使用して直接更新できます。

curl http://sync.afraid.org/u/*******ですが、証明書の更新は面倒です。acme.sh実装することはできますが、freedns には標準インターフェースがないため、実装するのはあまり適切ではないように感じられます。さらに、freedns は常にセカンダリドメイン名を他人に渡してしまうため、私は歯を食いしばってドメイン名を cloudflare に移行して管理することにしました。

1. DDNSを実装する

cloudflare を使用して ddns を実装するのは、実は freedns よりも少し面倒です。sh ファイルも記述する必要がありますが、1 文だけで実行できる freedns とは異なり、標準インターフェイスを呼び出す必要があります。実際にはルーターに設置することをお勧めします。私のSynologyは実際には一年中プロキシをハングアップしているからです。理由はわかりません。システムプロキシの後、ip138にアクセスして実際のIPを見つけることができますが、スクリプトを使用するとIP を取得するには、常にプロキシ IP を取得します。したがって、最善のオプションはルーターに移動することです。もちろん、Synology のスケジュールされたタスクを引き続き使用したい場合は、スクリプトを Synology のどこかに配置して、スケジュールされたタスクを使用します。コマンドは、この sh ファイルを bash で実行することです。

スクリプトを書く前に、次の 4 つの値を取得します: API_TOKEN、ZONE_ID、RECORD_ID、RECORD_NAME

1.1. 4つのパラメータを取る

1.1.1. API_TOKEN

まずユーザープロファイルにDNSトークンを作成します

「権限の編集」を選択して保存します。このトークンは保存され、一度だけ表示されます。

1.1.2. Cloudflare Zone ID

これは、Web サイトの概要の右下隅にあります。ゾーン ID は通常、32 ビットの 16 進文字列です。例:0123456789abcdef0123456789abcdef

1.1.3. DNS レコード ID (更新が必要なレコード ID)

これは開発者ツールを使って確認することもできますが、APIを使って確認する方が簡単です。

1
2
3
curl -X GET "https://api.cloudflare.com/client/v4/zones/<你的Zone ID>/dns_records?name=<你的RECORD_NAME>" \
-H "X-Auth-Email: <你的Cloudflare邮箱>" \
-H "X-Auth-Key: <你的CloudflareAPI Token>"

DNS レコードの ID を見つけるには、ゾーン ID、電子メール、トークン、RECORD_NAME を置き換えるだけです。

1.1.4. レコード名

これは、IP を更新するドメイン名です。ルート ドメイン名でもサブドメイン名でもかまいません。いずれにしても、A レコードを更新するドメイン名です。

1.2. スクリプトの作成

上記の 4 つの値を取得したら、スクリプトを記述できます。ルーターにSSHでログインし、ルート権限を取得して、保存場所を選択します。私は/usrに保存しました。vi ddns.shを使用してエディターを開き、Iを押して編集モードに入り、次のスクリプトをコピーします。覚えておいてください4つの値を置き換える

スクリプトは次のとおりです。

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
#!/bin/sh
# Cloudflare API令牌
API_TOKEN=""
# Cloudflare Zone ID
ZONE_ID=""
# DNS记录ID(需要更新的记录ID)
RECORD_ID=""
# 需要更新的域名,subdomain.example.com
RECORD_NAME=""

# 获取当前公网IP
CURRENT_IP=$(curl -s http://ipv4.icanhazip.com)
echo "当前公网IP: $CURRENT_IP"

# 获取现有的DNS记录IP
DNS_RECORD_RESPONSE=$(curl -s -k -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json")

# 提取现有DNS记录的IP地址
DNS_RECORD_IP=$(echo "$DNS_RECORD_RESPONSE" | sed -n 's/.*"content":"\([^"]*\)".*/\1/p')
echo "提取到的DNS记录IP: $DNS_RECORD_IP"


# 检查IP是否需要更新
if [ "$CURRENT_IP" == "$DNS_RECORD_IP" ]; then
echo "IP地址未改变,无需更新"
else
echo "IP地址已改变,开始更新DNS记录"

# 更新DNS记录
RESPONSE=$(curl -s -k -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"${RECORD_NAME}\",\"content\":\"${CURRENT_IP}\",\"ttl\":120,\"proxied\":false}")

# 检查更新结果
if echo "$RESPONSE" | grep -q "\"success\":true"; then
echo "DNS记录已成功更新为新IP: ${CURRENT_IP}"
else
echo "更新DNS记录失败:$RESPONSE"
fi
fi

**追記: **他の場所からコピーしたスクリプトがXiaomiルーターで実行できない場合、またはcurlでhttpsアドレスにアクセスしたときにXiaomiルーターが値を返さない場合は、curlの後に-kパラメータを追加することを忘れないでください。

1.3. スケジュールされたタスク

スクリプトを書いたら、crontab -eでスケジュールされたタスクを追加するだけです。

*/10 * * * * /usr/ddns.sh

10 分ごとに実行されます。動的 IP が週に 1 回更新される場合は、スケジュールされたタスクを適宜調整できます。

2. acme.shを使用してSynologyの証明書を自動的に更新する

docker を使用せずに Synology に acme.sh を直接インストールすることをお勧めします。これにより、証明書を更新する際の検証プロセスが大幅に簡素化されます。

まず SSH ポートを開き、任意のツールを使用して Synology にログインします。私は Termius を使用していますが、これは Mac に適したアプリだと思います。

1
2
3
4
5
6
7
sudo su
cd ~
curl https://get.acme.sh | sh -s [email protected] --force
cd .acme.sh
./acme.sh --install --nocron --home /usr/local/share/acme.sh --accountemail "[email protected]"
source ~/.profile
cd /usr/local/share/acme.sh

値を1行ずつ入力し、Account_IDとTokenを取得します。上記と同じTokenを使用できます。同じである必要があります。Account_IDはZone IDと同じページにあります。これら2つで値を変更するには、次の手順に進みます。

1
2
3
4
5
6
export CF_Account_ID="*****************" 
export CF_Token="*****************"
# 申请证书,--server letsencrypt 指定申请 letsencrypt 证书
# -d example.com 指定要申请证书的域名是 example.com
# -d *.example.com 说明申请的证书是泛域名证书
./acme.sh --issue --server letsencrypt --home . -d example.com --dns dns_cf --keylength 2048

通常、ここで証明書を取得しています。次に、証明書を展開します。ローカルコンピューターに直接展開する場合は、一時的な管理者ユーザーを使用して直接展開できます。そのため、Docker にインストールすることは推奨されません。リモートサーバーに証明書を展開する必要がある場合は、より複雑になります。こちら を参照してください。

デプロイする際は、IPでログインしてHTTPでアクセスする場合は追加の操作は必要ありません。私のようにドメイン名アクセスを使用し、同時にSSLを有効にする場合は、2つの環境変数を追加する必要があります。

1
2
3
4
5
6
7
# 设置使用临时管理员账户
export SYNO_USE_TEMP_ADMIN=1
export SYNO_SCHEME="https"
# 这里的端口号需要改成你设置的https的端口号,默认是5001
export SYNO_PORT="9530"
# 最后就是部署证书了,使用写好的hook直接搞定
./acme.sh --deploy --insecure --home . -d nas.igerm.ee --deploy-hook synology_dsm

2.1 自動更新

実際、DDNS を自動的に更新するのと同じように、カスタム cronjob を使用することも可能です。ただし、Synologyでcronjobを使用すると、Synologyのセキュリティアドバイザーから重大な警告が表示されます。これは自分で追加したものですが、この警告を見るのは気分がよくないので、Synologyのスケジュールされたタスクに直接追加することができます。更新する。

DSM コントロール パネルで、タスク スケジューラを開き、ユーザー定義スクリプトの新しいスケジュールされたタスクを作成します。

ユーザー アカウントを root として選択し、タスク設定にカスタム ユーザー スクリプトを入力します。

開始時間を毎月第 1 月曜日に設定していますが、自分で設定することもできます。

1
2
# renew certificates 
/usr/local/share/acme.sh/acme.sh --cron --home /usr/local/share/acme.sh