Azure DNSでDNSSECがGAしたので試してみた
はじめに
AzureでDNSSECサポートがGAされたので、DNSSECの仕組みを理解しながら試してみました!
DNSSECとは
DNSサーバーへの問い合わせ結果をデジタル署名を使って検証する技術で、真正性(正規のDNSサーバーが応答した値であること、値が改竄されていないこと)を確保することができます。
DNSキャッシュポイズニングなどの攻撃に対する対策となりうるものですが、サーバーとクライアントの両方がDNSSECに対応している必要があります。
試してみる
- まずはDNSSECの設定は行わず、Azure DNSでAレコードを登録して問い合わせ結果を確認します。
- Azure DNSでDNSSECの設定を有効化して動作を確認します。
- 最後にDNSSECによる署名の発行と検証の仕組みについて解説します。
PoC構成
Azure DNS Public Zoneでcontoso.com
ゾーンを作成します。
まずはDNSSECは設定せず、Aレコードだけ登録しておきます。
![]() |
---|
なお、ドメインはAWSのRoute53で購入しており、ネームサーバーとしてAzure DNSを使っています。
AzureでもApp Service Domainを使うとドメインの購入ができるのですが、DNSSECの設定で必須となるレジストラを通した上位ゾーン(例えば.com)へのDSレコード登録に対応していません。
AWSのRoute53は上位ゾーンへのDSレコード登録に対応しているので、ドメインだけ購入してAzure DNSのPublic ZoneでDNSレコードをホストするという形をとっています。
動作確認(DNSSEC設定なし)
digコマンドでAレコードの問い合わせを行うと、Azure DNSに設定している値(10.0.0.1)が取得されます。
$ dig contoso.com. @8.8.8.8
; <<>> DiG 9.16.50 <<>> contoso.com. @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 27054
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;contoso.com. IN A
;; ANSWER SECTION:
contoso.com. 60 IN A 10.0.0.1
;; Query time: 173 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Mar 30 11:04:28 UTC 2025
;; MSG SIZE rcvd: 55
まだDNSSECの設定は行なっていないので、digコマンドにDNSSECデータを要求する+dnssec
オプションをつけても、取得される内容に変化はありません。
$ dig +dnssec contoso.com. @8.8.8.8
; <<>> DiG 9.16.50 <<>> +dnssec contoso.com. @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35703
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;contoso.com. IN A
;; ANSWER SECTION:
contoso.com. 60 IN A 10.0.0.1
;; Query time: 5 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Mar 30 06:46:05 UTC 2025
;; MSG SIZE rcvd: 55
DNSSECの有効化
Azure DNSでDNSSECを有効化
Azure PortalでDNSゾーンを開き、DNSSEC を有効にする
をオンにします。Azure DNSの設定としてはこれだけでOKです。
![]() |
---|
有効化すると、署名の発行と検証に使用するキーペア(秘密鍵と公開鍵)が2組(ZSKとKSK)作成されます。(ZSKとKSKについては後で解説します)
親ゾーン(.com)にDSレコードとしてKSK公開鍵のハッシュを登録するまでは、状態表示が署名済みですが委任されていません
となります。(DSレコードについても最後に解説します)
![]() |
---|
親ゾーンのDSレコード登録に使用するKSK公開鍵も表示されているので、控えておきます。(Azure PortalのPublic key欄)
![]() |
---|
ドメインのレジストラで上位ゾーンにDSレコードを登録
親ゾーン(.com)にDSレコードとしてKSK公開鍵のハッシュを登録します。
今回はDSレコードの登録に対応しているレジストラのAmazon Route 53でドメインを購入しているので、AWS Management ConsoleでDSレコードの登録を行います。
ドメインはAWSのRoute53で購入しているので、AWSマネジメントコンソールのRoute53で取得したドメインを開き、DNSSECキーの追加を押下します。
![]() |
---|
Azure DNSでDNSSECを有効化した際に表示されていたKSK公開鍵の値をコピペして追加すると、そのハッシュ値が生成されDSレコードとして親ゾーン(.com)に登録されます。
![]() |
---|
digコマンドで親ゾーン(.com)のDSレコードを参照すると、KSK公開鍵のハッシュ値が登録されたことが確認できます。
$ dig @"$(dig +short com. NS | head -n 1)" +noall +answer +norecurse +nosplit contoso.com. DS
contoso.com. 86400 IN DS 55790 13 2 ED4E3A5BB244F5807CA5D2149EB69B29C3F71C386395C342E4461F483A1DD69B
Azure DNSでDNSSECの状態を確認
Route53でDSレコード登録後にAzure DNSのDNSSECパネルを開くと、状態が署名済みで、委任が確立されました
に変わったことが確認できます。
![]() |
---|
動作確認(DNSSEC設定あり)
digコマンドにDNSSECデータを要求する+dnssec
オプションをつけて実行してみると、flagsがflags: qr rd ra;
からflags: qr rd ra ad;
に変わっており、ad
が出力されるようになりました。
また、ANSWER SECTIONでRRSIGレコードも取得されています。
flagsのadはAuthentic Dataの略で署名の検証に成功したことを示します。
RRSIGレコードはリソースレコード(Aレコード)に対する署名で、これを用いて問い合わせ結果の真正性を検証しています。
$ dig +dnssec contoso.com. @8.8.8.8
; <<>> DiG 9.16.50 <<>> +dnssec contoso.com. @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 9055
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;contoso.com. IN A
;; ANSWER SECTION:
contoso.com. 60 IN A 10.0.0.1
contoso.com. 60 IN RRSIG A 13 2 60 20250331123603 20250329103603 41614 contoso.com. ud1TOqqskJpB3wpbyplhBqCT4npqrDbTqUpUWvitsYl/sV92UT6iaQyB PSOpF/sXWqCvj0DvYOJq/MOoe/4Kww==
;; Query time: 12 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Mar 30 11:36:21 UTC 2025
;; MSG SIZE rcvd: 161
権威DNSサーバーの応答がなりすまされている状態を再現するため、親ゾーン(.com)のDSレコードに不適切なハッシュを登録してみます。
その状態でdigコマンドを実行すると署名の検証に失敗するので、flagsにad
が出力されず、statusもSERVFAIL
となります。
$ dig +dnssec contoso.com. @8.8.8.8
; <<>> DiG 9.16.50 <<>> +dnssec contoso.com. @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 56059
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
; EDE: 9 (DNSKEY Missing): (No DNSKEY matches DS RRs of contoso.com)
;; QUESTION SECTION:
;contoso.com. IN A
;; Query time: 11 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Mar 30 11:56:55 UTC 2025
;; MSG SIZE rcvd: 83
DNSSECの動作解説
どのような仕組みで、署名の発行と検証が行われたのかを解説します。
DNSSECで使用されるDNSレコード
まず、DNSSECでは通常のリソースレコード以外に、RRSIGレコードとDNSKEYレコードが使用されます。
- リソースレコード
- 通常のDNS問い合わせで応答しているAレコードなどのDNSサーバーで管理しているレコード。
- RRSIGレコード(DNSSEC専用)
- リソースレコードの署名。
- 署名対象のレコードによって使用する秘密鍵が異なる。
- リソースレコードの署名にはZSK秘密鍵を使用する。
- DNSKEYレコードセットの署名にはKSK秘密鍵を使用する。
- DNSKEYレコード(DNSSEC専用)
- RRSIGレコードの検証に使用する公開鍵。
- DNSKEYレコードは、ZSK公開鍵とKSK公開鍵の2レコードある。
2種類(ZSK、KSK)のキーペア(秘密鍵と公開鍵)
ややこしいのですが、DNSSECでは2種類(ZSK、KSK)のキーペアが使用されます。
署名対象のレコードによって、使用するキーペアが異なります。
![]() |
---|
digコマンドでDNSKEYレコードの問い合わせを行うと、ZSKとKSKの公開鍵を確認することができます。
RRSIGレコードはDNSKEYレコードセットの署名です。KSKのDNSKEYレコードと、RRSIGレコードのkey id 55790
が一致しており、KSKで署名されていることが分かります。
$ dig +dnssec +multi contoso.com. dnskey @8.8.8.8
; <<>> DiG 9.16.50 <<>> +dnssec +multi contoso.com. dnskey @8.8.8.8
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48946
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 512
;; QUESTION SECTION:
;contoso.com. IN DNSKEY
;; ANSWER SECTION:
contoso.com. 3574 IN DNSKEY 256 3 13 (
yxTDuMTPR/m4KBQ98L9yg3f/bmDkINMTe1jvmvfd8TBi
PE3bE3Qqsq6umJm6wYmolGl88nj59z0EvVvUqTfcXQ==
) ; ZSK; alg = ECDSAP256SHA256 ; key id = 41614
contoso.com. 3574 IN DNSKEY 257 3 13 (
34FkYQ419KNiWyDWaNPEc7CxN6s3PWmtzTEw7UjnlOr4
XdCRFFBBSsVJm/hovlrk6FgaLeoX+IYSSPGaGqsyUQ==
) ; KSK; alg = ECDSAP256SHA256 ; key id = 55790
contoso.com. 3574 IN RRSIG DNSKEY 13 2 3600 (
20250529111749 20250330111749 55790 contoso.com.
+VQvvSfjsSo20xYRrCBBPcffcF7hExSQQSA4OxMYmJnr
6KQBNO/uNLPfAah0NZLy9brZ+DWOv6Ein54igfxFRg== )
;; Query time: 3 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Apr 04 23:19:01 UTC 2025
;; MSG SIZE rcvd: 305
DNSSECの流れ
- DNSSECを有効化すると、権威DNSサーバー(Azure DNS
contoso.com
ゾーン)上に2種類(ZSK、KSK)のキーペア(秘密鍵と公開鍵)が作成されます。 - フルサービスリゾルバ(キャッシュDNSサーバー)は、権威DNSサーバー(Azure DNS
contoso.com
ゾーン)にリソースレコード(Aレコードなど)の問い合わせを行います。 - 権威DNSサーバーは、ZSK秘密鍵を用いて問い合わせレコードの署名を作成し、署名をRRSIGレコードとして問い合わせ結果と併せて応答します。
- フルサービスリゾルバ(キャッシュDNSサーバー)は、権威DNSサーバー(Azure DNS
contoso.com
ゾーン)にDNSKEYレコードの問い合わせを行い、DNSSECのZSK公開鍵を取得します。 - フルサービスリゾルバ(キャッシュDNSサーバー)は、公開鍵を用いてRRSIGレコードの署名を検証します。
このような流れで、RRSIGレコードとDNSKEYレコードを組み合わせて、正規のDNSサーバーが応答した値であること、値が改竄されていないことを検証しています。
![]() |
---|
DNSKEYレコードの公開鍵の真正性
DNSKEYレコードで署名の検証に使用する公開鍵を受け取るのですが、RRSIGレコードもDNSKEYレコードもどちらも同じDNSサーバーから取得しています。
もし、偽装されたDNS応答であったとしても、DNSKEYレコードを用いたRRSIGレコードの検証は成功してしまうことになります。
そのため、公開鍵そのものも正規のものであるかを検証する必要があります。
ZSK公開鍵を含むDNSKEYレコードセットは、KSK秘密鍵で署名され、KSK公開鍵で検証されます。
KSK公開鍵の検証には、上位ゾーン(例えば.com)に登録しておいたDSレコードを使用します。
KSK公開鍵のハッシュを上位ゾーンにDSレコードとして登録しておき、DNSKEYレコードのKSK公開鍵がDSレコードのハッシュと一致していることを検証することによって、公開鍵の真正性を担保します。
![]() |
---|
親ゾーンのDSレコードもRRSIGレコードでまた検証して…と、これをルートゾーンまで遡って検証していく仕組みになっています。これを信頼の連鎖と言うそうです。
DNSSECのテスト
https://dnsviz.net を使うと、対象ドメインからルートゾーンまでのDNSSEC信頼チェーンが正しく構成できているかをテストすることができます。
![]() |
---|
最後に
DNSSECの仕組みを理解しながら、Azure DNSで実際に試してみました!
Azure PortalでDNSSECの有効化は簡単に行えますが、キーペアのロールオーバー、特にKSKを置き換える場合は親ゾーンのDSレコードの更新など、実際の運用で使うのは結構大変そうな印象を受けました。
Azure DNSにはまだ他にもいろいろな機能があるので、今後も試しながら更に理解を深めていきたいと思います!
Discussion