Amazon Route 53 パブリックホストゾーンのレコードを一括で出力したのち委任先のサブドメインが有効であるかを一括で確認してみた
コンバンハ、千葉(幸)です。
今回のシチュエーションは以下です。
- Amazon Route 53 パブリックホストゾーン(便宜上「親ホストゾーン」と呼称)を管理している
- 親ホストゾーンで管理しているドメインの一部サブドメインに対して、NSレコードによる委任設定を行っている
- 委任先のサブドメインは別の管理者がそれぞれのホストゾーン(便宜上「子ホストゾーン」と呼称)で管理している
ここで、子ホストゾーンが引き続き有効であるかを確認したいです。言い換えれば、子ホストゾーンがまだ存在するかどうかを確認したいです。
親ホストゾーンの管理者と子ホストゾーンの管理者が別な状況
社内で検証用のサブドメインを各個人に払い出しているようなケースを想定しています。親ホストゾーンの管理者の目線では親ホストゾーンに存在するNSレコードのみが確認できます。子ホストゾーンの管理者が自身が管理するホストゾーンを削除しても、親ホストゾーンの管理者では関知できない状態です。
今回は以下のアプローチで取り組んでみました。
- 親ホストゾーンのレコード一覧をAWS CLIで取得し、CSVファイルに出力
- 各NSレコードのネームサーバーにサブドメインのSOAレコードをクエリし結果を確認する
動作確認環境
- macOS Sonoma 14.6.1
- AWS CLI 2.15.61
- dig 9.10.6
- GNU bash, version 3.2.57(1)-release (arm64-apple-darwin23)
Amazon Route 53ホストゾーンのサブドメインの委任についておさらい
基本的な部分をおさらいしておきます。
Amazon Route 53でホストゾーンを作成すると以下のレコードが作成されます。
- SOAレコード
- Start Of Authority record。ドメインの権威の起点を表すもの。
- 例:
ns-xxx.awsdns-00.co.uk. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400
- NSレコード
- Name Server record。ドメインの権威DNSサーバーを表すもの。
- 例:
ns-xxx.awsdns-00.co.uk.
ns-yyy.awsdns-00.com.
ns-zzz.awsdns-00.org.
ns-aaa.awsdns-00.net.
子ホストゾーンのNSレコードを親ホストゾーンに登録することで、サブドメインの委任が行えます。
(なお、サブドメインの委任が行われたのちは、そのサブドメインに関するレコードは親ホストゾーンに登録されても意味を持ちません。)
今回は親ホストゾーンの管理者の目線で、サブドメインの委任に用いたNSレコードだけを手がかりに、子ホストゾーンが引き続き存在するかを確認していきたいです。
AWS CLIで Amazon Route 53ホストゾーンのレコード一覧を取得する
まずはホストゾーンのレコードを一括で出力します。以下のコマンドを使用します。
NSレコードに限定せず、すべてのレコードを取得します。エイリアスレコードの場合はそのターゲットを取得します。
% HOSTED_ZONE_ID=Zxxxxxxxxxxxx
% aws route53 list-resource-record-sets --hosted-zone-id $HOSTED_ZONE_ID | \
jq -r '.ResourceRecordSets[] |
[
.Name,
(if .ResourceRecords then (.ResourceRecords | map(.Value) | join(";"))
elif .AliasTarget then .AliasTarget.DNSName
else "" end),
.Type
] | @csv' > route53_records.csv
実行結果のCSVは以下のようなイメージで、ドメイン名、レコードタイプ、値が記載されています。
"example.com.","NS","ns-0000.awsdns-00.org.;ns-0000.awsdns-00.net.;ns-0000.awsdns-00.co.uk.;ns-0000.awsdns-00.com."
"example.com.","SOA","ns-0000.awsdns-00.org. hostmaster.example.com. 1 7200 900 1209600 86400"
"chiba.example.com.","NS","ns-0000.awsdns-00.org;ns-0000.awsdns-00.com;ns-0000.awsdns-00.co.uk;ns-0000.awsdns-00.net"
"saitama.example.com.","NS","ns-0000.awsdns-00.org;ns-0000.awsdns-00.com;ns-0000.awsdns-00.co.uk;ns-0000.awsdns-00.net"
"kanagawa.example.com.","NS","ns-0000.awsdns-00.net.;ns-0000.awsdns-00.org.;ns-0000.awsdns-00.co.uk.;ns-0000.awsdns-00.com."
"alb.example.com.","A","dualstack.dummy-lb.example.com."
...
委任したサブドメインのSOAレコードをDNSクエリする
例えばsaitama.example.com
にサブドメインの委任をしており、すでに当該サブドメインのホストゾーンは削除されているとします。
ネームサーバーを指定せずにsaitama.example.com
のSOAレコードをDNSクエリすると以下のような結果が返ってきます。
% dig SOA saitama.example.com.
; <<>> DiG 9.10.6 <<>> SOA saitama.example.com.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 5944
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;saitama.example.com. IN SOA
;; Query time: 438 msec
;; SERVER: (参照先DNSサーバーの情報)
;; WHEN: Mon Jun 30 15:39:03 JST 2025
;; MSG SIZE rcvd: 52
status: SERVFAIL
であることが読み取れます。ここではサーバー側で何らかの理由で失敗した、というレベルの情報にとどまります。
ネームサーバーを明示的に指定してクエリします。
% dig SOA saitama.example.com. @ns-0000.awsdns-00.org.
; <<>> DiG 9.10.6 <<>> SOA saitama.example.com. @ns-0000.awsdns-00.org.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 21874
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;saitama.example.com. IN SOA
;; Query time: 155 msec
;; SERVER: (参照先DNSサーバーの情報)
;; WHEN: Mon Jun 30 15:44:14 JST 2025
;; MSG SIZE rcvd: 41
status: REFUSED
であり、かつ WARNING: recursion requested but not available
であることが読み取れます。
権威DNSサーバーから応答の拒否がある、ということでより「サブドメインのホストゾーンが存在しない」可能性が高い結果です。
% dig SOA saitama.example.com. @ns-0000.awsdns-00.org. +short
%
+short
オプションをつけると何も結果が返ってきません。
今回はこの結果をもって「サブドメインのホストゾーンが存在しない」と判断することにします。
ホストゾーン内のNSレコードが示すサブドメインに一括でDNSクエリを行う
先ほど一覧出力したホストゾーンのレコードに対して、以下を行いたいです。
- NSレコードの場合、各ネームサーバーを指定してサブドメインのSOAレコードにDNSクエリ
- 結果が返ってくる場合、
OK
- ひとつ以上のネームサーバーで結果が返ってこない場合、
FAILED
- 結果が返ってくる場合、
- NSレコード以外のレコードに対しては処理をスキップ
上記を実施するスクリプトを作成しました。
#!/bin/bash
# Usage check
if [[ $# -ne 1 ]]; then
echo "Usage: $0 <CSV file path>"
exit 1
fi
INPUT_FILE="$1"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
OUTPUT_FILE="soa_check_results_$TIMESTAMP.csv"
# Validate file
if [[ ! -f "$INPUT_FILE" ]]; then
echo "File not found: $INPUT_FILE"
exit 1
fi
total_records=$(wc -l < "$INPUT_FILE")
echo "Name,Type,Result" > "$OUTPUT_FILE"
count=0
while IFS=',' read -r domain type ns_raw; do
domain=$(echo "$domain" | tr -d '"')
type=$(echo "$type" | tr -d '"')
ns_raw=$(echo "$ns_raw" | tr -d '"')
count=$((count + 1))
if (( count % 10 == 1 )); then
echo "Processing $count of $total_records..."
fi
if [[ "$type" != "NS" ]]; then
echo "$domain,$type,SKIPPED" >> "$OUTPUT_FILE"
continue
fi
IFS=';' read -ra ns_list <<< "$ns_raw"
all_ok=true
for ns in "${ns_list[@]}"; do
ns=$(echo "$ns" | xargs) # Trim whitespace
[[ -z "$ns" ]] && continue
if ! dig SOA "$domain" @"$ns" +short | grep -q .; then
all_ok=false
break
fi
done
result="FAILED"
$all_ok && result="OK"
echo "$domain,$type,$result" >> "$OUTPUT_FILE"
done < "$INPUT_FILE"
echo "Processing completed. Results have been saved to: $OUTPUT_FILE"
以下のようにCSVファイルを引数に指定して実行します。
% bash subdomain_checker.sh route53_records.csv
Processing 1 of 181...
Processing 11 of 181...
Processing 21 of 181...
Processing 31 of 181...
Processing 41 of 181...
Processing 51 of 181...
Processing 61 of 181...
Processing 71 of 181...
Processing 81 of 181...
Processing 91 of 181...
Processing 101 of 181...
Processing 111 of 181...
Processing 121 of 181...
Processing 131 of 181...
Processing 141 of 181...
Processing 151 of 181...
Processing 161 of 181...
Processing 171 of 181...
Processing 181 of 181...
Processing completed. Results have been saved to: soa_check_results_20250630_160036.csv
出力されたCSVファイルの内訳はこのようなイメージです。
Name,Type,Result
example.com.,NS,OK
example.com.,SOA,SKIPPED
example.com.,TXT,SKIPPED
chiba.example.com.,NS,FAILED
saitama.example.com.,NS,FAILED
kanagawa.example.com.,NS,FAILED
...
FAILEDとなっているサブドメインはすでに存在しないとみなせます。親ホストゾーンの管理者として、子ホストゾーンの状況を棚卸しできました。
終わりに
Amazon Route 53ホストゾーンのレコード一覧をAWS CLIを用いてCSV形式で出力し、NSレコードのサブドメインを対象に一括でDNSクエリを行いました。
社内の検証環境の管理主体がバラけていたので、親ホストゾーンで見える情報だけで整理ができたのはよかったです。
同じようなシチュエーションの方の参考になれば幸いです。
以上、チバユキ (@batchicchi)がお送りしました。