作 ▸
自宅サーバーのグローバルIPが変わったらRoute 53のAレコードを自動更新する
個人用途で自宅にWebサーバー立ててるのだが、IP固定するプロバイダ契約はしてないので、ケチってDDNSもどきの仕組みを作った。
なおドメインをAWSのRoute 53でホストしてる前提。
Fedora 39
前提
当該サーバーでAWS CLIを使えるようにしておくこと。また、必要なIAMポリシーは以下。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "route53:ChangeResourceRecordSets",
"Resource": "arn:aws:route53:::hostedzone/{対象のホストゾーンID}",
"Effect": "Allow"
},
{
"Action": "sns:Publish",
"Resource": "arn:aws:sns:{リージョン}:{アカウントID}:{エラー通知先のSNSトピック名}",
"Effect": "Allow"
}
]
}
エラー通知しなくていいならSNSのポリシーは不要。
本題
以下はマシンのグローバルIPを確認して、前回チェック時から変化していればRoute 53のAレコードを更新するbashスクリプト。
エラー処理は正直よくわかってないので、もっと良い方法があれば教えてほしい。ここではSNSトピックにエラー内容を投げてる。
#!/bin/bash
set -euo pipefail
LF=$'\n'
# AWS CLIのパスを通す (cronで実行する時に必要)
PATH=$PATH:/usr/local/bin
# Route 53のホストゾーンID
HOSTED_ZONE_ID=ZZZZZZZZZZZZZZZZZZZZ
# Route 53のレコード名
RECORD_NAME=hogehoge.example.com
# AWS CLIでdefault以外のプロファイルを使う場合はプロファイル名を指定
export AWS_PROFILE=piyopiyo
# エラー通知先のSNSトピックARN
NOTIFICATION_TOPIC_ARN=arn:aws:sns:ap-northeast-1:123456789012:hogehoge
# エラー出力の一時保存ファイル
ERROR_LOG=$(mktemp)
# 終了時に実行する処理
cleanup() {
# エラーログが空でない場合、内容をSNSで送信する
if [ -s "${ERROR_LOG}" ]; then
echo "DNS自動更新でエラーが発生しました。通知を送信します。"
echo "エラー詳細 ->"
cat "${ERROR_LOG}"
local error_message=$(cat "${ERROR_LOG}")
aws sns publish --topic-arn "${NOTIFICATION_TOPIC_ARN}" --message "DNS自動更新でエラー ->${LF}${error_message}"
fi
rm -f "$ERROR_LOG"
}
trap cleanup EXIT
# エラー出力をエラーログファイルにリダイレクト
exec 2> "$ERROR_LOG"
# 現在のグローバルIP取得
CURRENT_IP=$(curl -s http://checkip.amazonaws.com)
# 前回のグローバルIP取得
PREVIOUS_IP_FILE=/tmp/previous_ip
if [ -f $PREVIOUS_IP_FILE ]; then
PREVIOUS_IP=$(cat $PREVIOUS_IP_FILE)
else
PREVIOUS_IP=""
fi
# IPアドレスが変わっていたら…
if [ "$CURRENT_IP" != "$PREVIOUS_IP" ]; then
# AWS CLI用の入力ファイル作成
cat <<EOF > /tmp/change-batch.json
{
"Comment": "Update My Home IP Address",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "$RECORD_NAME",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{"Value": "$CURRENT_IP"}]
}
}
]
}
EOF
# Route53のレコードセット更新
aws route53 change-resource-record-sets \
--hosted-zone-id $HOSTED_ZONE_ID \
--change-batch file:///tmp/change-batch.json
# 現在のIPアドレスを保存
echo $CURRENT_IP > $PREVIOUS_IP_FILE
fi
上記のファイルを作成したら、実行権限を付与しておく。
chmod +x ~/scripts/update-dns.sh
これをcronで毎日5時に実行するように設定。必要ならもっと頻繁に実行してもよいと思うが、グローバルIPの確認は外部のURLに頼ってるので、あんまり叩いていいものか迷う。
(crontab -l 2>/dev/null; echo "0 5 * * * /bin/bash ~/scripts/update-dns.sh") | crontab -
なお、ここでは作業用ユーザーのcrontabに追加しているので、実行ユーザーはrootではなく作業用ユーザーとなる。