<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DNS &#8211; セキュリティエンジニアの雑多ブログ</title>
	<atom:link href="https://cybermemo.blog/tag/dns/feed" rel="self" type="application/rss+xml" />
	<link>https://cybermemo.blog</link>
	<description>セキュリティエンジニアの学習記録</description>
	<lastBuildDate>Sat, 12 Sep 2026 13:25:25 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1</generator>

<image>
	<url>https://cybermemo.blog/wp-content/uploads/2025/10/cropped-トップアイコン-32x32.jpg</url>
	<title>DNS &#8211; セキュリティエンジニアの雑多ブログ</title>
	<link>https://cybermemo.blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>DNSSEC検証 DNSSEC破壊・検証編</title>
		<link>https://cybermemo.blog/dnssec-lab-testing</link>
					<comments>https://cybermemo.blog/dnssec-lab-testing#respond</comments>
		
		<dc:creator><![CDATA[miyuki]]></dc:creator>
		<pubDate>Sat, 12 Sep 2026 13:24:46 +0000</pubDate>
				<category><![CDATA[セキュリティ]]></category>
		<category><![CDATA[検証]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[DNSSEC]]></category>
		<category><![CDATA[Unbound]]></category>
		<guid isPermaLink="false">https://cybermemo.blog/?p=802</guid>

					<description><![CDATA[<p><img src="https://cybermemo.blog/wp-content/uploads/2026/08/検証アイキャッチ-1024x768.png" class="webfeedsFeaturedVisual" /></p>はじめに 何をしたいか DNSSECの信頼の連鎖を実際に構築し、DNS応答がどのように署名・検証されるのかを確認する。また、DNSSECに関する設定や署名を意図的に破壊し、検証失敗時にフルリゾルバやクライアントからどのよ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://cybermemo.blog/wp-content/uploads/2026/08/検証アイキャッチ-1024x768.png" class="webfeedsFeaturedVisual" /></p>
<h2 class="wp-block-heading">はじめに</h2>



<h3 class="wp-block-heading">何をしたいか</h3>



<p class="wp-block-paragraph">DNSSECの信頼の連鎖を実際に構築し、DNS応答がどのように署名・検証されるのかを確認する。また、DNSSECに関する設定や署名を意図的に破壊し、検証失敗時にフルリゾルバやクライアントからどのように見えるのかを確認する。<br>前回の「DNSSEC構築編」では、Parent DNSとChild DNSにDNSSECを導入し、UnboundにTrust Anchorを設定することで、lab.test から child.lab.test までの信頼の連鎖を構築した。<br>本記事では、構築したDNSSEC環境を意図的に破壊し、署名の不整合や信頼の連鎖の破損が発生した際に、UnboundによるDNSSEC検証およびClientからの名前解決がどのような結果になるのかを確認する。</p>



<p class="wp-block-paragraph">準備・DNS構築編　<a href="https://cybermemo.blog/dnssec-lab-setup">https://cybermemo.blog/dnssec-lab-setup</a><br>DNSSEC構築編　<a href="https://cybermemo.blog/dnssec-lab-configuration">https://cybermemo.blog/dnssec-lab-configuration</a><br>DNSSEC破壊・検証編　本記事</p>



<h3 class="wp-block-heading">本記事で検証する構成</h3>



<p class="wp-block-paragraph">前回構築したDNSSEC環境を使用し、DNSSECに関する設定やDNSデータを意図的に変更して検証を行う。<br>正常な状態では、Unboundに設定した lab.test のTrust Anchorを起点として、Parent DNSのDNSKEY、Child DNSのDS・DNSKEY、各RRsetのRRSIGへと信頼の連鎖が成立している。<br>本記事では、この正常な状態を基準としてDNSSECを意図的に破壊し、正常時と異常時の応答を比較する。</p>



<pre class="wp-block-code"><code>              ┌─────────────┐
              │ Parent DNS  │　192.168.56.10/24
              │    BIND9    │　権威ゾーン: lab.test
              │             │　DNSKEY / RRSIG
              └──────┬──────┘
                     │
            child.lab.test を委任
              ＋ DSレコード
                     │
                     ▼
              ┌─────────────┐　192.168.56.20/24
              │  Child DNS  │　権威ゾーン: child.lab.test
              │    BIND9    │　DNSKEY / RRSIG
              │             │　└─ www.child.lab.test → 192.168.56.100
              └─────────────┘
                     ▲
                     │ DNS問い合わせ
                     │ ＋ DNSSEC署名情報
                     │
              ┌─────────────┐
              │  Resolver   │ 192.168.56.30/24
              │   Unbound   │ DNSSEC検証
              │             │ Trust Anchor: lab.test
              └──────┬──────┘
                     ▲
                     │ DNS問い合わせ
                     │
              ┌─────────────┐
              │   Client    │ 192.168.56.40/24
              └─────────────┘</code></pre>



<pre class="wp-block-code"><code>【正常時のDNSSECの信頼の連鎖】

Trust Anchor
（lab.test KSK / DNSKEY）
        │
        ▼
lab.test DNSKEY RRset
        │
        │ ParentのDSによってChild KSKを信頼
        ▼
child.lab.test DNSKEY RRset
        │
        │ Child ZSKの公開鍵でRRSIGを検証
        ▼
www.child.lab.test A</code></pre>



<h3 class="wp-block-heading">検証環境</h3>



<p class="wp-block-paragraph">仮想化ソフトウェア：Oracle VirtualBox<br>ゲストOS：Ubuntu Server 26.04.1 LTS（amd64）<br>権威DNS：BIND 9.20.24<br>フルリゾルバ：Unbound 1.24.2<br>DNS確認ツール：DiG 9.20.24<br>内部ネットワーク：192.168.56.0/24<br>検証ドメイン：lab.test / child.lab.test</p>



<h2 class="wp-block-heading">検証</h2>



<h3 class="wp-block-heading">検証1：署名済みAレコードを改ざんし、DNSSEC検証失敗を確認する</h3>



<p class="wp-block-paragraph">本検証では、攻撃者などによって署名済みDNSデータが改ざんされた状況を模擬するため、Child DNSのAレコードを変更し、A RRsetに対応するRRSIGは更新しない。これにより、RRsetとRRSIGが不整合となった際にUnboundがどのように検知するかを確認する。</p>



<h4 class="wp-block-heading">署名済みファイルのAレコードを直接変更</h4>



<p class="wp-block-paragraph">Child DNS で作業。</p>



<pre class="wp-block-code"><code># www.child.lab.test. 3600 IN A 192.168.56.<span class="swl-marker mark_orange">100</span> → www.child.lab.test. 3600 IN A 192.168.56.<span class="swl-marker mark_orange">200</span>
# Serialを変更
$ sudo vim /etc/bind/db.child.lab.test.signed
※一部抜粋
; File written on Wed Sep  9 13:25:36 2026
; dnssec-signzone version 9.20.24-1ubuntu0.3-Ubuntu
child.lab.test.         3600    IN SOA  ns.child.lab.test. dnsmaster.child.lab.test. (
                                        <span class="swl-marker mark_orange">2026091001</span> ; serial
（中略）
www.child.lab.test.     3600    IN A    192.168.56.<span class="swl-marker mark_orange">200</span>
                        3600    RRSIG   A 13 4 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        XX27GC+TFLVYuz+Jd8Ox7SyC5yxL1ifF+cuS
                                        mi+J8jcqgW8NQhR+Fi8sFaHbAEZuw691gEoZ
                                        22rXmWlCL5sbOQ== )</code></pre>



<p class="wp-block-paragraph">今回の検証の構成は下記。</p>



<pre class="wp-block-code"><code>署名時
www.child.lab.test A 192.168.56.100
              │
              └── ZSKで署名
                       ↓
                    RRSIG A

                ↓ Aレコードを改ざん

www.child.lab.test A 192.168.56.200
                    +
以前の192.168.56.100に対するRRSIG
                    ↓
                 不一致</code></pre>



<h4 class="wp-block-heading">BINDに改ざん後のゾーンを読み込ませる</h4>



<pre class="wp-block-code"><code># reload
$ sudo rndc reload child.lab.test

# Serialを確認
$ sudo rndc zonestatus child.lab.test
name: child.lab.test
type: primary
files: /etc/bind/db.child.lab.test.signed
<span class="swl-marker mark_orange">serial: 2026091001</span>
nodes: 3
last loaded: Thu, 10 Sep 2026 13:24:27 GMT
secure: yes
inline signing: no
key maintenance: none
next resign node: ns.child.lab.test/NSEC
next resign time: Fri, 02 Oct 2026 12:25:36 GMT
dynamic: no
reconfigurable via modzone: no

# Childが改ざん後のデータを配信していることを確認
$ dig +dnssec @192.168.56.20 www.child.lab.test A

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +dnssec @192.168.56.20 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 65390
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: 194a0690a20c4f2e010000006aa2b07b18a3ea84a17f5fad (good)
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; ANSWER SECTION:
www.child.lab.test.     3600    IN      A       <span class="swl-marker mark_orange">192.168.56.200</span>
<span class="swl-marker mark_orange">www.child.lab.test.     3600    IN      RRSIG   A 13 4 3600 20261009122536 20260909122536 7661 child.lab.test. XX27GC+TFLVYuz+Jd8Ox7SyC5yxL1ifF+cuSmi+J8jcqgW8NQhR+Fi8s FaHbAEZuw691gEoZ22rXmWlCL5sbOQ==</span>

;; Query time: 0 msec
;; SERVER: 192.168.56.20#53(192.168.56.20) (UDP)
;; WHEN: Thu Sep 10 13:28:27 UTC 2026
;; MSG SIZE  rcvd: 201</code></pre>



<h4 class="wp-block-heading">Client → Unbound で確認</h4>



<pre class="wp-block-code"><code># Resolverで作業。キャッシュ削除
$ sudo unbound-control flush_zone child.lab.test

# Clientで作業。
$ dig +dnssec @192.168.56.30 www.child.lab.test A

; &lt;&lt;>> DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;>> +dnssec @192.168.56.30 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER&lt;&lt;- opcode: QUERY, <span class="swl-marker mark_orange">status: SERVFAIL</span>, id: 32814　　# status: SERVFAIL,　ANSWER: 0 = 問い合わせ失敗
;; flags: <span class="swl-marker mark_orange">qr rd ra</span>; QUERY: 1, <span class="swl-marker mark_orange">ANSWER: 0</span>, AUTHORITY: 0, ADDITIONAL: 1　　# 正常時に存在していた ad フラグなし

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; Query time: 21 msec
;; SERVER: 192.168.56.30#53(192.168.56.30) (UDP)
;; WHEN: Thu Sep 10 13:32:32 UTC 2026
;; MSG SIZE  rcvd: 47

# ジャーナル確認
$ sudo journalctl -u unbound --since "2 minutes ago" > log
$ grep -E "validated DS|validated DNSKEY|signature mismatch|failed ANSWER|bad rrsets" log
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: validated DS child.lab.test. DS IN
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: validated DNSKEY child.lab.test. DNSKEY IN
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] debug: <span class="swl-marker mark_orange">verify: signature mismatch</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: <span class="swl-marker mark_orange">validator: response has failed ANSWER rrset: www.child.lab.test. A IN</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: Validate: message contains bad rrsets
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] debug: <span class="swl-marker mark_orange">verify: signature mismatch</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: <span class="swl-marker mark_orange">validator: response has failed ANSWER rrset: www.child.lab.test. A IN</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: Validate: message contains bad rrsets
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] debug: <span class="swl-marker mark_orange">verify: signature mismatch</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: <span class="swl-marker mark_orange">validator: response has failed ANSWER rrset: www.child.lab.test. A IN</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: Validate: message contains bad rrsets
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] debug: <span class="swl-marker mark_orange">verify: signature mismatch</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: <span class="swl-marker mark_orange">validator: response has failed ANSWER rrset: www.child.lab.test. A IN</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: Validate: message contains bad rrsets
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] debug: <span class="swl-marker mark_orange">verify: signature mismatch</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: <span class="swl-marker mark_orange">validator: response has failed ANSWER rrset: www.child.lab.test. A IN</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: Validate: message contains bad rrsets
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] debug: <span class="swl-marker mark_orange">verify: signature mismatch</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: <span class="swl-marker mark_orange">validator: response has failed ANSWER rrset: www.child.lab.test. A IN</span>
Sep 10 13:44:58 resolver unbound&#91;1538]: &#91;1538:0] info: <span class="swl-marker mark_orange">Validate: message contains bad rrsets</span></code></pre>



<p class="wp-block-paragraph">下記の流れでエラー発生。</p>



<pre class="wp-block-code"><code>Client
   │
   ▼
Unbound
   │
   │ www.child.lab.test A = 192.168.56.200
   │ RRSIG A = 以前の署名
   │
   ▼
Child ZSKの公開鍵（DNSKEY）でRRSIGを検証
   │
   └── ✕ 署名が一致しない
          │
          ▼
        Bogus
          │
          ▼
       SERVFAIL</code></pre>



<p class="wp-block-paragraph">ジャーナルから読み取れる挙動は下記。</p>



<pre class="wp-block-code"><code>validated DS
    ↓
ChildのDSは正常

validated DNSKEY
    ↓
ChildのDNSKEYも正常

signature mismatch
    ↓
AレコードとRRSIGが一致しない

failed ANSWER rrset
    ↓
www.child.lab.test のA RRsetを検証できない

bad rrsets
    ↓
DNSSEC検証失敗</code></pre>



<h4 class="wp-block-heading">検証結果</h4>



<p class="wp-block-paragraph">Resolverのキャッシュを削除した後、ClientからUnboundを経由して www.child.lab.test のAレコードを問い合わせた。結果は SERVFAIL となり、ANSWER SECTIONは0件だった。また、正常時に存在していた ad フラグも付与されていない。これにより、AレコードとRRSIGが不整合な状態では、UnboundがDNSSEC検証を正常に完了できないことを確認した。</p>



<h3 class="wp-block-heading">検証2：DSレコードを不整合にする</h3>



<p class="wp-block-paragraph">本検証では、Parent DNSに登録されている child.lab.test のDSレコードを意図的に変更し、Child DNSのKSKと不整合な状態を作成する。これにより、ParentからChildへの信頼の連鎖が成立しなくなった際に、Unboundがどのように検知するかを確認する。</p>



<h4 class="wp-block-heading">Parent DNSのDSレコードを変更</h4>



<p class="wp-block-paragraph">Parent DNS で作業。</p>



<pre class="wp-block-code"><code># 元ゾーンのDSを確認
$ grep " IN DS " /etc/bind/db.lab.test
child       IN DS 26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F6532742BF5D

# Serialを変更
# digestの最後の1文字だけ変更　D → E
$ sudo vim /etc/bind/db.lab.test
2026091201 ; Serial
child       IN DS 26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F6532742BF5<span class="swl-marker mark_orange">E</span>

# ファイル確認
$ cat /etc/bind/db.lab.test
<code>$TTL 3600

@   IN  SOA ns dnsmaster (
        2026091201 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN  NS  ns.lab.test.

ns  IN  A   192.168.56.10

child       IN NS ns.child
ns.child    IN A  192.168.56.20
child       IN DS 26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F6532742BF5E
; This is a key-signing key, keyid 25095, for lab.test.
; Created: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Publish: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Activate: 20260910122739 (Thu Sep 10 12:27:39 2026)
lab.test. IN DNSKEY 257 3 13 nzPV3+LMX633npZfI3Seu2cR8SrTegHIi1sCK2OtNTQyRZg/v6yVkRDl nmr52oumop7xFxsx6vcZk3emfTsFbQ==
; This is a zone-signing key, keyid 42600, for lab.test.
; Created: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Publish: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Activate: 20260910122712 (Thu Sep 10 12:27:12 2026)
lab.test. IN DNSKEY 256 3 13 XGx8XP7w7bqg8k9cBXoPvDLsZQFUOAuUbdr8Bd8ZSH25ip1Bq75BGFYO yZhxy0DNqEsEPPpDt2qHAW/kdlJs3g==</code></code></pre>



<p class="wp-block-paragraph">ここで作った状態は下記。</p>



<pre class="wp-block-code"><code>Child KSK
    │
    └─ 本来のSHA-256 digest
             ↓
        ...2742BF5<span class="swl-marker mark_orange">D</span>

Parentに登録したDS
             ↓
        ...2742BF5<span class="swl-marker mark_orange">E</span>
             ↑
          不一致</code></pre>



<h4 class="wp-block-heading">変更後のDSレコードを含むParentゾーンを再署名</h4>



<pre class="wp-block-code"><code># ゾーンファイルを確認
$ sudo named-checkzone lab.test /etc/bind/db.lab.test

# Parentゾーンを再署名
$ cd /etc/bind/keys/lab.test
$ sudo dnssec-signzone \
  -S \
  -o lab.test \
  -f /etc/bind/db.lab.test.signed \
  /etc/bind/db.lab.test
Verifying the zone using the following algorithms:
- ECDSAP256SHA256
Zone fully signed:
Algorithm: ECDSAP256SHA256: KSKs: 1 active, 0 stand-by, 0 revoked
                            ZSKs: 1 active, 0 stand-by, 0 revoked
/etc/bind/db.lab.test.signed</code></pre>



<p class="wp-block-paragraph">改ざん後のDSに対して新しいRRSIG DSが生成される。</p>



<pre class="wp-block-code"><code>偽DS
  │
  └─ Parent ZSKで正常に署名
             ↓
       RRSIG DSは正常

しかし

偽DS
  ↕　一致しない　　　　　　
Child KSK</code></pre>



<h4 class="wp-block-heading">BINDに再署名後のゾーンを読み込ませる</h4>



<pre class="wp-block-code"><code>$ sudo rndc reload lab.test
$ sudo rndc zonestatus lab.test
name: lab.test
type: primary
files: /etc/bind/db.lab.test.signed
<span class="swl-marker mark_orange">serial: 2026091201</span>
nodes: 4
last loaded: Sat, 12 Sep 2026 10:49:13 GMT
secure: yes
inline signing: no
key maintenance: none
next resign node: lab.test/DNSKEY
next resign time: Mon, 05 Oct 2026 09:49:13 GMT
dynamic: no
reconfigurable via modzone: no

# 変更後のDSレコードとRRSIGを確認
$ dig +dnssec +norecurse @192.168.56.10 child.lab.test DS

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +dnssec +norecurse @192.168.56.10 child.lab.test DS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 7197
;; flags: qr aa ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: c5bb3449b7fa9da2010000006aa53041466bb4c96a8f1c6c (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      DS

;; ANSWER SECTION:
child.lab.test.         3600    IN      DS      26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F653 2742BF5<span class="swl-marker mark_orange">E</span>　　# D → E に変更されている
child.lab.test.         3600    IN      RRSIG   DS 13 3 3600 20261012094913 20260912094913 42600 lab.test. BI3iajICF5rg6gHFcItF2XATrIZuHwPiGrBnNN/Bde02gBYnc8n62dI0 N8K3+/7d6wECpKNOjFcsUwBcnfhkQA==

;; Query time: 0 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Sat Sep 12 10:58:09 UTC 2026
;; MSG SIZE  rcvd: 223</code></pre>



<h4 class="wp-block-heading">Child KSKから生成されるDSとの不一致を確認する</h4>



<p class="wp-block-paragraph">Child DNS で作業。</p>



<pre class="wp-block-code"><code># Child KSK側の設定を確認
$ cd /etc/bind/keys/child.lab.test
$ dnssec-dsfromkey -2 Kchild.lab.test.+013+26145.key
child.lab.test. IN DS 26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F6532742BF5<span class="swl-marker mark_orange">D</span></code></pre>



<h4 class="wp-block-heading">Client → Unbound で確認</h4>



<pre class="wp-block-code"><code># キャッシュ削除(Resolverで作業)
$ sudo unbound-control flush_zone lab.test

# Clientから確認
$ dig +dnssec @192.168.56.30 www.child.lab.test A

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +dnssec @192.168.56.30 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: <span class="swl-marker mark_orange">SERVFAIL</span>, id: 62414
;; flags: <span class="swl-marker mark_orange">qr rd ra</span>; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; Query time: 17 msec
;; SERVER: 192.168.56.30#53(192.168.56.30) (UDP)
;; WHEN: Sat Sep 12 11:06:35 UTC 2026
;; MSG SIZE  rcvd: 47

# ジャーナル確認　※ログは一部抜粋
$ sudo journalctl -u unbound --since "2 minutes ago" &gt; log
$ grep -Ei "DS|DNSKEY|bogus|fail|mismatch|validate|bad|key" log
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] info: adding trusted key lab.test. DNSKEY IN
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] info: validator operate: query . DNSKEY IN
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] info: resolving . DNSKEY IN
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] debug: request has exceeded the maximum number of sends with 33
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] debug: return error response SERVFAIL
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] info: iterator operate: query . DNSKEY IN
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] info: processQueryTargets: . DNSKEY IN
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] debug: Failed to get a delegation, giving up
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] debug: return error response SERVFAIL
Sep 12 11:11:01 resolver unbound&#91;1661]: &#91;1661:0] info: validator operate: query . DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: generate keytag query _ta-6207.lab.test. NULL IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: validator operate: query lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: resolving lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: resolving (init part 2):  lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: resolving (init part 3):  lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: processQueryTargets: lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: sending query: lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: iterator operate: query lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: response for lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: finishing processing for lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: validator operate: query lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: validate keys with anchor(DS): sec_status_secure
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: Successfully primed trust anchor lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: <span class="swl-marker mark_orange">validated DS child.lab.test. DS IN</span>
(中略)
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: validator operate: query child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: resolving child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: resolving (init part 2):  child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: resolving (init part 3):  child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: processQueryTargets: child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: sending query: child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: iterator operate: query child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: response for child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: finishing processing for child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: validator operate: query child.lab.test. DNSKEY IN
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] debug: <span class="swl-marker mark_orange">DS fail: digest is different
</span>Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] debug: <span class="swl-marker mark_orange">Failed to match any usable DS to a DNSKEY.</span>
Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: <span class="swl-marker mark_orange">Did not match a DS to a DNSKEY, thus bogus.
</span>Sep 12 11:11:05 resolver unbound&#91;1661]: &#91;1661:0] info: <span class="swl-marker mark_orange">Could not establish a chain of trust to keys for child.lab.test. DNSKEY IN</span></code></pre>



<p class="wp-block-paragraph">下記の流れでエラー発生。</p>



<pre class="wp-block-code"><code>Unbound
  |
  | ParentのDSを取得
  v
DS RRset + RRSIG DS
  |
  +-- ○ Parent側の署名検証は成功
  |
  v
Child DNSKEYを取得
  |
  | DNSKEYからdigestを計算
  v
Parent DS     Child KSK由来
...BF5E       ...BF5D
     \         /
      \       /
       × 不一致
          |
          v
Failed to match any usable DS to a DNSKEY
          |
          v
Bogus
          |
          v
SERVFAIL</code></pre>



<p class="wp-block-paragraph">ジャーナルから読み取れる挙動は下記。</p>



<pre class="wp-block-code"><code>validated DS
    ↓
ParentのDS RRset自体の署名検証は成功

DS fail: digest is different
    ↓
DSのdigestとChild DNSKEYから算出したdigestが一致しない

Failed to match any usable DS to a DNSKEY.
    ↓
DSに対応するChild DNSKEYを確認できない

Did not match a DS to a DNSKEY, thus bogus.
    ↓
DNSSEC検証でBogusと判定

Could not establish a chain of trust to keys
    ↓
ParentからChildへの信頼の連鎖を構築できない</code></pre>



<h4 class="wp-block-heading">検証結果</h4>



<p class="wp-block-paragraph">Resolverのキャッシュを削除した後、ClientからUnboundを経由して www.child.lab.test のAレコードを問い合わせた。結果は SERVFAIL となり、ANSWER SECTIONは0件だった。また、正常時に存在していた ad フラグも付与されていない。これにより、Parent DNSのDSレコードとChild KSKが不整合な状態では、UnboundがDNSSEC検証を正常に完了できないことを確認した。</p>



<h3 class="wp-block-heading">検証3：DSレコードを削除し、Insecureになることを確認する</h3>



<p class="wp-block-paragraph">本検証では、Parent DNSに登録されている child.lab.test のDSレコードを削除し、ParentからChildへのDNSSECの信頼の連鎖が存在しない状態を作成する。DSレコードが存在するもののChild DNSKEYと不整合だった検証2とは異なり、DSレコードが正しく存在しない場合に、UnboundがChildゾーンをどのように扱うかを確認する。</p>



<h4 class="wp-block-heading">Parent DNSからDSレコードを削除する</h4>



<p class="wp-block-paragraph">Parent DNS で作業。</p>



<pre class="wp-block-code"><code># Serialを変更
# 元ゾーンファイルのDSレコードを削除
$ sudo vim /etc/bind/db.lab.test
<code>$TTL 3600

@   IN  SOA ns dnsmaster (
        2026091201 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN  NS  ns.lab.test.

ns  IN  A   192.168.56.10

child       IN NS ns.child
ns.child    IN A  192.168.56.20
; This is a key-signing key, keyid 25095, for lab.test.
; Created: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Publish: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Activate: 20260910122739 (Thu Sep 10 12:27:39 2026)
lab.test. IN DNSKEY 257 3 13 nzPV3+LMX633npZfI3Seu2cR8SrTegHIi1sCK2OtNTQyRZg/v6yVkRDl nmr52oumop7xFxsx6vcZk3emfTsFbQ==
; This is a zone-signing key, keyid 42600, for lab.test.
; Created: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Publish: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Activate: 20260910122712 (Thu Sep 10 12:27:12 2026)
lab.test. IN DNSKEY 256 3 13 XGx8XP7w7bqg8k9cBXoPvDLsZQFUOAuUbdr8Bd8ZSH25ip1Bq75BGFYO yZhxy0DNqEsEPPpDt2qHAW/kdlJs3g==</code></code></pre>



<h4 class="wp-block-heading">DS削除後のParentゾーンを再署名する</h4>



<pre class="wp-block-code"><code># ゾーンファイルを確認
$ sudo named-checkzone lab.test /etc/bind/db.lab.test

# Parentゾーンを再署名
$ cd /etc/bind/keys/lab.test
$ sudo dnssec-signzone \
  -S \
  -o lab.test \
  -f /etc/bind/db.lab.test.signed \
  /etc/bind/db.lab.test
Verifying the zone using the following algorithms:
- ECDSAP256SHA256
Zone fully signed:
Algorithm: ECDSAP256SHA256: KSKs: 1 active, 0 stand-by, 0 revoked
                            ZSKs: 1 active, 0 stand-by, 0 revoked
/etc/bind/db.lab.test.signed</code></pre>



<h4 class="wp-block-heading">BINDに再署名後のゾーンを読み込ませる</h4>



<pre class="wp-block-code"><code>$ sudo rndc reload lab.test
$ sudo rndc zonestatus lab.test
name: lab.test
type: primary
files: /etc/bind/db.lab.test.signed
<span class="swl-marker mark_orange">serial: 2026091201</span>
nodes: 4
last loaded: Sat, 12 Sep 2026 11:42:06 GMT
secure: yes
inline signing: no
key maintenance: none
next resign node: lab.test/DNSKEY
next resign time: Mon, 05 Oct 2026 10:42:06 GMT
dynamic: no
reconfigurable via modzone: no

# DSがANSWER SECTIONに返らないことと、DNSSECによる不在証明に関係する情報が返ってくることを確認
$ dig +dnssec +norecurse @192.168.56.10 child.lab.test DS

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +dnssec +norecurse @192.168.56.10 child.lab.test DS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 10626
;; flags: qr aa ra; QUERY: 1, <span class="swl-marker mark_orange">ANSWER: 0</span>, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: 1a9ae6c7bc8bf2dc010000006aa53b4245473b3175ed38ac (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      DS

;; AUTHORITY SECTION:
lab.test.               3600    IN      SOA     ns.lab.test. dnsmaster.lab.test. 2026091201 3600 900 604800 86400
lab.test.               3600    IN      RRSIG   SOA 13 2 3600 20261012104206 20260912104206 42600 lab.test. 3+/zAO/gAc+/0RLsZz5+9bxCTlKo9CM8It0vjtxFVgNTl89h//QS0bs7 O7JqjCRdIkMLGTxKMyoygiKlvMEq3A==
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      NSEC    ns.lab.test. NS RRSIG NSEC</span>
child.lab.test.         3600    IN      RRSIG   NSEC 13 3 3600 20261012104206 20260912104206 42600 lab.test. JLf3igQqIgx0gh+uwOY/axOws/jSS+95NhlsvegrziN3Qn1bobeVLGcO iw66jM2zqD4ihBqS5IR4ga/reXh8/Q==

;; Query time: 0 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Sat Sep 12 11:45:06 UTC 2026
;; MSG SIZE  rcvd: 361</code></pre>



<p class="wp-block-paragraph">NSECとそれに付いたRRSIGによって、「child.lab.test にはDSレコードが存在しない」ことがDNSSECで認証されている。</p>



<pre class="wp-block-code"><code>Unbound
   |
   | child.lab.test のDSは？
   v
Parent DNS
   |
   | DSは存在しない
   v
NSEC
「child.lab.testには
 NS / RRSIG / NSEC はあるが
 DSはない」
   |
   | Parent ZSK 42600によるRRSIG
   v
認証されたDSの不在</code></pre>



<h4 class="wp-block-heading">Client → Unbound で確認</h4>



<pre class="wp-block-code"><code># キャッシュ削除(Resolverで作業)
$ sudo unbound-control flush_zone lab.test

# Clientから確認
$ dig +dnssec @192.168.56.30 www.child.lab.test A

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +dnssec @192.168.56.30 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: <span class="swl-marker mark_orange">NOERROR</span>, id: 20363
;; flags: <span class="swl-marker mark_orange">qr rd ra</span>; QUERY: 1, ANSWER: <span class="swl-marker mark_orange">2</span>, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; ANSWER SECTION:
www.child.lab.test.     3600    IN      A       192.168.56.100
www.child.lab.test.     3600    IN      RRSIG   A 13 4 3600 20261009122536 20260909122536 7661 child.lab.test. XX27GC+TFLVYuz+Jd8Ox7SyC5yxL1ifF+cuSmi+J8jcqgW8NQhR+Fi8s FaHbAEZuw691gEoZ22rXmWlCL5sbOQ==

;; Query time: 10 msec
;; SERVER: 192.168.56.30#53(192.168.56.30) (UDP)
;; WHEN: Sat Sep 12 11:54:26 UTC 2026
;; MSG SIZE  rcvd: 173

# ジャーナル確認　
$ sudo journalctl -u unbound --since "2 minutes ago" &gt; log
$ grep -Ei "DS|DNSKEY|secure|insecure|bogus|validate|NSEC|trust" log
Sep 12 11:54:17 resolver unbound&#91;1611]: &#91;1611:0] info: adding trusted key lab.test. DNSKEY IN
Sep 12 11:54:17 resolver unbound&#91;1611]: &#91;1611:0] info: validator operate: query . DNSKEY IN
Sep 12 11:54:17 resolver unbound&#91;1611]: &#91;1611:0] info: resolving . DNSKEY IN
Sep 12 11:54:17 resolver unbound&#91;1611]: &#91;1611:0] debug: request has exceeded the maximum number of sends with 33
Sep 12 11:54:17 resolver unbound&#91;1611]: &#91;1611:0] info: iterator operate: query . DNSKEY IN
Sep 12 11:54:17 resolver unbound&#91;1611]: &#91;1611:0] info: processQueryTargets: . DNSKEY IN
Sep 12 11:54:17 resolver unbound&#91;1611]: &#91;1611:0] info: validator operate: query . DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: prime trust anchor
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: validator operate: query lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: resolving lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: resolving (init part 2):  lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: resolving (init part 3):  lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: processQueryTargets: lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: sending query: lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: iterator operate: query lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: response for lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: finishing processing for lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: validator operate: query lab.test. DNSKEY IN
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: <span class="swl-marker mark_orange">validate keys with anchor(DS): sec_status_secure</span>
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: <span class="swl-marker mark_orange">Successfully primed trust anchor lab.test. DNSKEY IN</span>
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: <span class="swl-marker mark_orange">NSEC RRset for the referral proved no DS.</span>
Sep 12 11:54:26 resolver unbound&#91;1611]: &#91;1611:0] info: <span class="swl-marker mark_orange">Verified that response is INSECURE</span></code></pre>



<p class="wp-block-paragraph">本検証の流れは下記。</p>



<pre class="wp-block-code"><code>Parent
  |
  | DSなし
  | NSEC + RRSIG NSECで不在を証明
  v
Unbound
  |
  | 「このChildはDNSSECの信頼の連鎖に接続されていない」
  v
Insecure
  |
  | 名前解決は継続
  v
A = 192.168.56.100 を返す
  |
  v
adフラグは付かない</code></pre>



<p class="wp-block-paragraph">ジャーナルから読み取れる挙動は下記。</p>



<pre class="wp-block-code"><code>validate keys with anchor(DS): sec_status_secure
    ↓
lab.test のTrust Anchorは正常

Successfully primed trust anchor
    ↓
Parent側の信頼の起点を正常に確立

NSEC RRset for the referral proved no DS.
    ↓
child.lab.test にDSが存在しないことをNSECで確認

Verified that response is INSECURE
    ↓
ChildゾーンをInsecureとして扱う</code></pre>



<h3 class="wp-block-heading">検証結果</h3>



<p class="wp-block-paragraph">Resolverのキャッシュを削除した後、ClientからUnboundを経由して www.child.lab.test のAレコードを問い合わせた。結果は NOERROR となり、Aレコード 192.168.56.100 が正常に返された。一方、正常時に存在していた ad フラグは付与されていない。Unboundのログでは、NSECによってDSレコードが存在しないことが確認され、INSECURE と判定されていた。これにより、Parent DNSにDSレコードが存在しない場合、Childゾーンは Bogus ではなく Insecure として扱われ、DNSSECによる検証済みとはならないものの、名前解決自体は正常に行われることを確認した。</p>



<h3 class="wp-block-heading">疑問に思ったこと</h3>



<p class="wp-block-paragraph">「DNSSECによる検証ができていないのに、名前解決を成功させてしまってよいのか？」という疑問を持ったので調べてみた。</p>



<h4 class="wp-block-heading">なぜDNSSECが設定されていなくても名前解決ができるのか</h4>



<p class="wp-block-paragraph">DNSSECは、DNSSECを利用していないドメインの名前解決を拒否する仕組みではない。<br>インターネット上にはDNSSECを利用していないドメインも存在するため、DNSSECによる信頼の連鎖が存在しないという理由だけで名前解決を拒否してしまうと、DNSSECを利用していないドメインを名前解決できなくなってしまう。</p>



<h4 class="wp-block-heading">攻撃者がDSレコードを削除してDNSSECを回避できるのではないか</h4>



<p class="wp-block-paragraph">攻撃者がDNS応答からDSレコードを単純に削除しただけでは、Insecure にすることはできない。<br>DNSSECでは、DSレコードが存在しない場合、NSEC とその RRSIG によって「DSレコードが存在しないこと」自体を認証できている。つまりUnboundは、単に「DSが返ってこなかったから Insecure」と判断したのではなく、ParentゾーンのDNSSEC署名によってDSの不在が認証されたことを確認したうえで Insecure と判定している。</p>



<h2 class="wp-block-heading">実務との関連</h2>



<p class="wp-block-paragraph">今回の検証はDNSSECに関する攻撃そのものを再現したものではなく、攻撃や設定ミスによって発生し得るDNSSECの異常状態を意図的に作り、その際の挙動を確認したものである。</p>



<h3 class="wp-block-heading">検証1：DNSデータの改ざん</h3>



<p class="wp-block-paragraph">検証1では、署名済みのAレコードを変更し、A RRsetとRRSIGの不整合を発生させた。<br>実環境では、DNSキャッシュポイズニングや通信経路上でのDNS応答改ざんなどによって、攻撃者が正規のDNSデータとは異なる情報を返そうとする状況が考えられる。<br>DNSSECでは、攻撃者が正しい秘密鍵を持っていなければ改ざん後のデータに対する有効なRRSIGを生成できない。そのため、検証リゾルバはRRsetとRRSIGの不整合を検知し、改ざんされたDNSデータを正当な応答として扱わない。<br>今回の検証では、この状態がUnboundの signature mismatch として確認でき、最終的に SERVFAIL となった。</p>



<pre class="wp-block-code"><code>DNSデータの改ざん
        ↓
RRsetとRRSIGが不一致
        ↓
DNSSEC検証失敗
        ↓
Bogus
        ↓
SERVFAIL</code></pre>



<h3 class="wp-block-heading">検証2：DNSSECの設定・鍵管理の不整合</h3>



<p class="wp-block-paragraph">検証2では、Parent DNSに登録されたDSレコードのdigestを変更し、Child KSKと対応しない状態を作成した。<br>実環境では、KSKロールオーバー時のDS更新ミスなどにより、Parent側のDSとChild側のDNSKEYが対応しなくなる可能性がある。<br>この状態では、DSレコード自体の署名検証には成功しても、DSとChild DNSKEYを結び付けることができない。そのため、ParentからChildへの信頼の連鎖を構築できず、DNSSEC検証は失敗する。<br>今回の検証では、Unboundのログから DS fail: digest is different および Could not establish a chain of trust を確認し、最終的に SERVFAIL となった。</p>



<pre class="wp-block-code"><code>DSとChild DNSKEYの不整合
        ↓
DSに対応するDNSKEYを確認できない
        ↓
信頼の連鎖を構築できない
        ↓
Bogus
        ↓
SERVFAIL</code></pre>



<h3 class="wp-block-heading">検証3：DSレコードが存在しない状態</h3>



<p class="wp-block-paragraph">検証3では、Parent DNSからChildのDSレコードを削除し、ParentからChildへのDNSSECの信頼の連鎖が存在しない状態を作成した。<br>検証2との重要な違いは、「存在するDSとDNSKEYが不整合」なのか、「そもそもDSが存在しない」のかという点にある。<br>DSが存在するにもかかわらず対応するDNSKEYを確認できない場合は Bogus となり、名前解決は SERVFAIL となる。一方、DSが存在しないことをNSECとRRSIGによって正当に確認できる場合、そのChildゾーンは Insecure として扱われ、DNSSECによる検証済みではないものの、名前解決自体は継続される。<br>実環境では、DNSSECを廃止してDSレコードを削除した場合や、レジストラ側でDSレコードが削除された場合などに、このような状態が発生し得る。</p>



<pre class="wp-block-code"><code>ParentにDSが存在しない
        ↓
NSEC + RRSIGによって
DSの不在を正当に確認
        ↓
DNSSECの信頼の連鎖なし
        ↓
Insecure
        ↓
名前解決は可能
ただしDNSSECによる真正性の保証はない</code></pre>



<p class="wp-block-paragraph">なお、第三者がDNS応答から単純にDSレコードを除去するだけで Insecure にできるわけではない。DSレコードが存在しないこと自体もNSECとRRSIGによって認証されるためである。ただし、本来DNSSECで保護されるべきドメインから正規のDSレコードが削除された場合は、名前解決が継続していてもDNSSECによる保護が失われるため、運用上は注意が必要となる。</p>



<h2 class="wp-block-heading">まとめ</h2>



<p class="wp-block-paragraph">今回の検証では、DNSSECの正常な環境を意図的に破壊し、Unboundの挙動を確認した。AレコードとRRSIGが不整合な場合、およびParentのDSとChild DNSKEYが不整合な場合はBogusとなり、名前解決はSERVFAILとなった。一方、DSレコードが存在しないことをDNSSECによって正当に確認できる場合はInsecureとなり、DNSSECによる真正性は保証されないものの、名前解決自体は継続された。<br>今回の検証から、DNSSECでは単に「名前解決に成功するか、失敗するか」だけではなく、Secure、Bogus、Insecureの状態を区別し、信頼の連鎖のどの段階で問題が発生しているのかを確認することが重要だと分かった。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cybermemo.blog/dnssec-lab-testing/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DNSSEC検証 DNSSEC構築編</title>
		<link>https://cybermemo.blog/dnssec-lab-configuration</link>
					<comments>https://cybermemo.blog/dnssec-lab-configuration#respond</comments>
		
		<dc:creator><![CDATA[miyuki]]></dc:creator>
		<pubDate>Sat, 12 Sep 2026 13:12:39 +0000</pubDate>
				<category><![CDATA[セキュリティ]]></category>
		<category><![CDATA[検証]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[DNSSEC]]></category>
		<category><![CDATA[Unbound]]></category>
		<guid isPermaLink="false">https://cybermemo.blog/?p=779</guid>

					<description><![CDATA[<p><img src="https://cybermemo.blog/wp-content/uploads/2026/08/検証アイキャッチ-1024x768.png" class="webfeedsFeaturedVisual" /></p>はじめに 何をしたいか DNSSECの信頼の連鎖を実際に構築し、DNS応答がどのように署名・検証されるのかを確認する。また、DNSSECに関する設定や署名を意図的に破壊し、検証失敗時にフルリゾルバやクライアントからどのよ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://cybermemo.blog/wp-content/uploads/2026/08/検証アイキャッチ-1024x768.png" class="webfeedsFeaturedVisual" /></p>
<h2 class="wp-block-heading">はじめに</h2>



<h3 class="wp-block-heading">何をしたいか</h3>



<p class="wp-block-paragraph">DNSSECの信頼の連鎖を実際に構築し、DNS応答がどのように署名・検証されるのかを確認する。また、DNSSECに関する設定や署名を意図的に破壊し、検証失敗時にフルリゾルバやクライアントからどのように見えるのかを確認する。<br>前回の「準備・DNS構築編」では、DNSSECを使用しない通常のDNS環境を構築した。<br>本記事では、この環境にDNSSECを導入し、信頼の連鎖を構築する。</p>



<p class="wp-block-paragraph">準備・DNS構築編　<a href="https://cybermemo.blog/dnssec-lab-setup">https://cybermemo.blog/dnssec-lab-setup</a><br>DNSSEC構築編　本記事<br>DNSSEC破壊・検証編　<a href="https://cybermemo.blog/dnssec-lab-testing">https://cybermemo.blog/dnssec-lab-testing</a></p>



<h3 class="wp-block-heading">本記事で構築する構成</h3>



<p class="wp-block-paragraph">前回構築したDNS環境にDNSSECを導入する。</p>



<pre class="wp-block-code"><code>              ┌─────────────┐
              │ Parent DNS  │　192.168.56.10/24
              │    BIND9    │　権威ゾーン: lab.test
              │             │　DNSKEY / RRSIG
              └──────┬──────┘
                     │
            child.lab.test を委任
              ＋ DSレコード
                     │
                     ▼
              ┌─────────────┐　192.168.56.20/24
              │  Child DNS  │　権威ゾーン: child.lab.test
              │    BIND9    │　DNSKEY / RRSIG
              │             │　└─ www.child.lab.test → 192.168.56.100
              └─────────────┘
                     ▲
                     │ DNS問い合わせ
                     │ ＋ DNSSEC署名情報
                     │
              ┌─────────────┐
              │  Resolver   │ 192.168.56.30/24
              │   Unbound   │ DNSSEC検証
              │             │ Trust Anchor: lab.test
              └──────┬──────┘
                     ▲
                     │ DNS問い合わせ
                     │
              ┌─────────────┐
              │   Client    │ 192.168.56.40/24
              └─────────────┘</code></pre>



<pre class="wp-block-code"><code>【DNSSECの信頼の連鎖】

Trust Anchor
（lab.test KSK / DNSKEY）
        │
        ▼
lab.test DNSKEY RRset
        │
        │ ParentのDSによってChild KSKを信頼
        ▼
child.lab.test DNSKEY RRset
        │
        │ Child ZSKの公開鍵でRRSIGを検証
        ▼
www.child.lab.test A</code></pre>



<h3 class="wp-block-heading">検証環境</h3>



<p class="wp-block-paragraph">仮想化ソフトウェア：Oracle VirtualBox<br>ゲストOS：Ubuntu Server 26.04.1 LTS（amd64）<br>権威DNS：BIND 9.20.24<br>フルリゾルバ：Unbound 1.24.2<br>DNS確認ツール：DiG 9.20.24<br>内部ネットワーク：192.168.56.0/24<br>検証ドメイン：lab.test / child.lab.test</p>



<h2 class="wp-block-heading">構築</h2>



<h3 class="wp-block-heading">ChildゾーンをDNSSEC署名</h3>



<p class="wp-block-paragraph">Child DNS で作業。</p>



<h4 class="wp-block-heading">鍵生成</h4>



<pre class="wp-block-code"><code># ゾーンファイルを確認
$ sudo cat /etc/bind/db.child.lab.test
<code>$TTL 3600

@   IN SOA ns dnsmaster (
        2026090401 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN NS ns

ns  IN A 192.168.56.20
www IN A 192.168.56.100</code>

# DNSSEC鍵を置くディレクトリを作る
$ sudo mkdir -p /etc/bind/keys/child.lab.test

# ZSKを生成
$ cd /etc/bind/keys/child.lab.test
$ sudo dnssec-keygen -a ECDSAP256SHA256 -n ZONE child.lab.test
Generating key pair.
Kchild.lab.test.+013+07661

# KSKを生成
$ sudo dnssec-keygen -a ECDSAP256SHA256 -f KSK -n ZONE child.lab.test
Generating key pair.
Kchild.lab.test.+013+26145

# 生成ファイルを確認
$ sudo ls -l /etc/bind/keys/child.lab.test
total 16
-rw-r--r-- 1 root bind 347 Sep  9 12:59 Kchild.lab.test.+013+07661.key
-rw------- 1 root bind 187 Sep  9 12:59 Kchild.lab.test.+013+07661.private
-rw-r--r-- 1 root bind 347 Sep  9 13:00 Kchild.lab.test.+013+26145.key
-rw------- 1 root bind 187 Sep  9 13:00 Kchild.lab.test.+013+26145.private

# 公開鍵の中身を確認　
$ sudo cat Kchild.lab.test.+013+07661.key &amp;&amp; sudo cat Kchild.lab.test.+013+26145.key
; This is a zone-signing key, keyid 7661, for child.lab.test.
; Created: 20260909125923 (Wed Sep  9 12:59:23 2026)
; Publish: 20260909125923 (Wed Sep  9 12:59:23 2026)
; Activate: 20260909125923 (Wed Sep  9 12:59:23 2026)
child.lab.test. IN DNSKEY 256 3 13 of3bj/PGoJ9JAF2HN02sQ4xKhSjPBt8c0iLmok/IcnloBP0A+Wm+vqj6 ZM7v1/HXQmi6odv+eJ/+O4lfOMEkiQ==
; This is a key-signing key, keyid 26145, for child.lab.test.
; Created: 20260909130016 (Wed Sep  9 13:00:16 2026)
; Publish: 20260909130016 (Wed Sep  9 13:00:16 2026)
; Activate: 20260909130016 (Wed Sep  9 13:00:16 2026)
child.lab.test. IN DNSKEY 257 3 13 RfvhGg1akSrUMv7Ub87SsXXHUJt0NRWW7hUtG8rS0x6gLM9b8+vpx0A1 qNvm10S/hEEPaa9SAz/7Hrq87Rcyiw==</code></pre>



<h4 class="wp-block-heading">Childのゾーンファイルを署名</h4>



<pre class="wp-block-code"><code># ディレクトリ移動
$ cd /etc/bind

# バックアップ取得
$ sudo cp db.child.lab.test db.child.lab.test.bak

# 2つの.keyをゾーンファイルへ追加
$ sudo sh -c 'cat keys/child.lab.test/*.key >> db.child.lab.test'　　

# Serialを変更
$ sudo vim /etc/bind/db.child.lab.test　　
<code>$TTL 3600

@   IN SOA ns dnsmaster (
        2026090901 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN NS ns

ns  IN A 192.168.56.20
www IN A 192.168.56.100
; This is a zone-signing key, keyid 7661, for child.lab.test.
; Created: 20260909125923 (Wed Sep  9 12:59:23 2026)
; Publish: 20260909125923 (Wed Sep  9 12:59:23 2026)
; Activate: 20260909125923 (Wed Sep  9 12:59:23 2026)
child.lab.test. IN DNSKEY 256 3 13 of3bj/PGoJ9JAF2HN02sQ4xKhSjPBt8c0iLmok/IcnloBP0A+Wm+vqj6 ZM7v1/HXQmi6odv+eJ/+O4lfOMEkiQ==
; This is a key-signing key, keyid 26145, for child.lab.test.
; Created: 20260909130016 (Wed Sep  9 13:00:16 2026)
; Publish: 20260909130016 (Wed Sep  9 13:00:16 2026)
; Activate: 20260909130016 (Wed Sep  9 13:00:16 2026)
child.lab.test. IN DNSKEY 257 3 13 RfvhGg1akSrUMv7Ub87SsXXHUJt0NRWW7hUtG8rS0x6gLM9b8+vpx0A1 qNvm10S/hEEPaa9SAz/7Hrq87Rcyiw==</code>

# 構文チェック
$ sudo named-checkzone child.lab.test /etc/bind/db.child.lab.test
zone child.lab.test/IN: loaded serial 2026090901
OK

# ディレクトリ移動
$ cd /etc/bind/keys/child.lab.test

# dnssec-signzoneで署名
$ sudo dnssec-signzone \　　
  -S \
  -o child.lab.test \
  -f /etc/bind/db.child.lab.test.signed \
  /etc/bind/db.child.lab.test
Verifying the zone using the following algorithms:
- ECDSAP256SHA256
Zone fully signed:
Algorithm: ECDSAP256SHA256: KSKs: 1 active, 0 stand-by, 0 revoked
                            ZSKs: 1 active, 0 stand-by, 0 revoked
/etc/bind/db.child.lab.test.signed

# 署名済みゾーンファイルが生成されたことを確認
$ sudo ls -l /etc/bind/db.child.lab.test*　　
-rw-r--r-- 1 root bind  947 Sep  9 13:22 /etc/bind/db.child.lab.test
-rw-r--r-- 1 root bind  253 Sep  9 13:18 /etc/bind/db.child.lab.test.bak
-rw-r--r-- 1 root bind 2726 Sep  9 13:25 /etc/bind/db.child.lab.test.signed

# 署名済みゾーンを確認
$ sudo cat /etc/bind/db.child.lab.test.signed
<code>; File written on Wed Sep  9 13:25:36 2026
; dnssec-signzone version 9.20.24-1ubuntu0.3-Ubuntu
child.lab.test.         3600    IN SOA  ns.child.lab.test. dnsmaster.child.lab.test. (
                                        2026090901 ; serial
                                        3600       ; refresh (1 hour)
                                        900        ; retry (15 minutes)
                                        604800     ; expire (1 week)
                                        86400      ; minimum (1 day)
                                        )
                        3600    RRSIG   SOA 13 3 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        lPLC99bWrcmgzGCGwL20o7A8yPGr/w7wMtIo
                                        9XVRflFmyorQ01L1PHOj1n/s6ZG3DwtYsgjE
                                        1Uklg/WEIQdbPA== )
                        3600    NS      ns.child.lab.test.
                        3600    RRSIG   NS 13 3 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        U2708D42QzU3kgqX0gcaoOLQD9H7pNVG8/IH
                                        VnrNK5InPpyeNCRyq5sSa1oxdXuVITovo+eB
                                        QSkKU/OAlGeM+Q== )
                        3600    NSEC    ns.child.lab.test. NS SOA RRSIG NSEC DNSKEY
                        3600    RRSIG   NSEC 13 3 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        Gt28Z9fQT56l0ONZa1YpEL7+22gH7RgxT178
                                        n5Zf3/4TH7UPSSx0lQE5nWpUb52A7+VlF5ix
                                        8K1v9MX31Psl/w== )
                        3600    DNSKEY  256 3 13 (
                                        of3bj/PGoJ9JAF2HN02sQ4xKhSjPBt8c0iLm
                                        ok/IcnloBP0A+Wm+vqj6ZM7v1/HXQmi6odv+
                                        eJ/+O4lfOMEkiQ==
                                        ) ; ZSK; alg = ECDSAP256SHA256 ; key id = 7661
                        3600    DNSKEY  257 3 13 (
                                        RfvhGg1akSrUMv7Ub87SsXXHUJt0NRWW7hUt
                                        G8rS0x6gLM9b8+vpx0A1qNvm10S/hEEPaa9S
                                        Az/7Hrq87Rcyiw==
                                        ) ; KSK; alg = ECDSAP256SHA256 ; key id = 26145
                        3600    RRSIG   DNSKEY 13 3 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        FgbLJ9v+yNnKLs6sMEWIk8smobeazyZoFiPm
                                        XA0HU4EAHnthv8olg7KmNGjgm/tcuPvUQgMs
                                        f7lK3BgevwukFQ== )
                        3600    RRSIG   DNSKEY 13 3 3600 (
                                        20261009122536 20260909122536 26145 child.lab.test.
                                        NYOgC1JsircR22X5nwPl1S+XfF4hhRlWBiEA
                                        MYhf0gKxJcupAUy1rMSj25VMcbvx0jurFW76
                                        VVjxFmMXOrfGIg== )
ns.child.lab.test.      3600    IN A    192.168.56.20
                        3600    RRSIG   A 13 4 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        f6r7LraRZm76e0HcFZAP1sxMXz+FdGdNHZ1I
                                        R/58BloWPWrIxYtVorV7Yj5jYDHkGqsiB10W
                                        FItH0NhA3S2+FA== )
                        3600    NSEC    www.child.lab.test. A RRSIG NSEC
                        3600    RRSIG   NSEC 13 4 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        nI9GreBE6XjqVVTljaicF804VAnZS53p0hpr
                                        TU4h7qMdLL2frKJF5nEtZr1hH803Tw5MT0F8
                                        jE6nCtQBDmfZhA== )
www.child.lab.test.     3600    IN A    192.168.56.100
                        3600    RRSIG   A 13 4 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        XX27GC+TFLVYuz+Jd8Ox7SyC5yxL1ifF+cuS
                                        mi+J8jcqgW8NQhR+Fi8sFaHbAEZuw691gEoZ
                                        22rXmWlCL5sbOQ== )
                        3600    NSEC    child.lab.test. A RRSIG NSEC
                        3600    RRSIG   NSEC 13 4 3600 (
                                        20261009122536 20260909122536 7661 child.lab.test.
                                        QHkt5+ujPGQ/3UTapTfDNMUzvzt6C9LdBVJL
                                        xv/isAyQWFphEK/pkbAmTIMDBLKIoBRMyb4i
                                        LUpi1qvRa0CplA== )</code></code></pre>



<h4 class="wp-block-heading">BINDが署名済みファイルを使うよう変更</h4>



<pre class="wp-block-code"><code># 署名済みファイルを読み込むよう設定変更
# db.child.lab.test → db.child.lab.test.signed
$ sudo vim /etc/bind/named.conf.local
<code>//
// Do any local configuration here
//

zone "child.lab.test" {
    type primary;
    file "/etc/bind/db.child.lab.test.signed";
};</code>

# 設定をチェックして再読み込み
$ sudo named-checkconf
$ sudo named-checkzone child.lab.test /etc/bind/db.child.lab.test.signed
zone child.lab.test/IN: loaded serial 2026090901 (DNSSEC signed)
OK
$ sudo rndc reconfig
$ sudo rndc zonestatus child.lab.test
$ systemctl status bind9
● named.service - BIND Domain Name Server
     Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: <span class="swl-marker mark_orange">active (running)</span> since Wed 2026-09-09 12:39:27 UTC; 1h 0min ago</code></pre>



<h4 class="wp-block-heading">DNSKEYを問い合わせる</h4>



<pre class="wp-block-code"><code>$ dig +dnssec @192.168.56.20 child.lab.test DNSKEY

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +dnssec @192.168.56.20 child.lab.test DNSKEY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 43976
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: 69581b200025ce68010000006aa1633aa773dd222721ebe1 (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      DNSKEY

;; ANSWER SECTION:　　# DNSKEY RRsetに対する署名が応答に含まれている
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      DNSKEY  257 3 13 RfvhGg1akSrUMv7Ub87SsXXHUJt0NRWW7hUtG8rS0x6gLM9b8+vpx0A1 qNvm10S/hEEPaa9SAz/7Hrq87Rcyiw==
child.lab.test.         3600    IN      DNSKEY  256 3 13 of3bj/PGoJ9JAF2HN02sQ4xKhSjPBt8c0iLmok/IcnloBP0A+Wm+vqj6 ZM7v1/HXQmi6odv+eJ/+O4lfOMEkiQ==
child.lab.test.         3600    IN      RRSIG   DNSKEY 13 3 3600 20261009122536 20260909122536 7661 child.lab.test. FgbLJ9v+yNnKLs6sMEWIk8smobeazyZoFiPmXA0HU4EAHnthv8olg7Km NGjgm/tcuPvUQgMsf7lK3BgevwukFQ==
child.lab.test.         3600    IN      RRSIG   DNSKEY 13 3 3600 20261009122536 20260909122536 26145 child.lab.test. NYOgC1JsircR22X5nwPl1S+XfF4hhRlWBiEAMYhf0gKxJcupAUy1rMSj 25VMcbvx0jurFW76VVjxFmMXOrfGIg=</span>=

;; Query time: 0 msec
;; SERVER: 192.168.56.20#53(192.168.56.20) (UDP)
;; WHEN: Wed Sep 09 13:46:34 UTC 2026
;; MSG SIZE  rcvd: 451

$ dig +dnssec @192.168.56.20 www.child.lab.test A

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +dnssec @192.168.56.20 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 6047
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: 2b33bf67976af0a4010000006aa1633f561edffaee841791 (good)
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; ANSWER SECTION:　　# RRsetに対する署名が応答に含まれている
<span class="swl-marker mark_orange">www.child.lab.test.     3600    IN      A       192.168.56.100
www.child.lab.test.     3600    IN      RRSIG   A 13 4 3600 20261009122536 20260909122536 7661 child.lab.test. XX27GC+TFLVYuz+Jd8Ox7SyC5yxL1ifF+cuSmi+J8jcqgW8NQhR+Fi8s FaHbAEZuw691gEoZ22rXmWlCL5sbOQ==</span>

;; Query time: 0 msec
;; SERVER: 192.168.56.20#53(192.168.56.20) (UDP)
;; WHEN: Wed Sep 09 13:46:39 UTC 2026
;; MSG SIZE  rcvd: 201</code></pre>



<h3 class="wp-block-heading">Child DNSのKSKからDSレコードを生成し、Parent DNSに登録</h3>



<h4 class="wp-block-heading">Child DNSのKSKでDSレコードを生成</h4>



<pre class="wp-block-code"><code># 生成した鍵を確認
$ cd /etc/bind/keys/child.lab.test
$ ls -l
total 20
-rw-r--r-- 1 root bind 347 Sep  9 12:59 Kchild.lab.test.+013+07661.key
-rw------- 1 root bind 187 Sep  9 12:59 Kchild.lab.test.+013+07661.private
-rw-r--r-- 1 root bind 347 Sep  9 13:00 Kchild.lab.test.+013+26145.key
-rw------- 1 root bind 187 Sep  9 13:00 Kchild.lab.test.+013+26145.private
-rw-r--r-- 1 root bind 100 Sep  9 13:25 dsset-child.lab.test.

# KSKからDSレコードを生成
$ dnssec-dsfromkey -2 Kchild.lab.test.+013+26145.key
child.lab.test. IN DS 26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F6532742BF5D

# Parent DNSへDSを登録(Parent DNSで作業)
# Serialを変更、DSレコードを追記
$ sudo vim /etc/bind/db.lab.test
<code>$TTL 3600

@   IN  SOA ns dnsmaster (
        2026091001 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN  NS  ns.lab.test.

ns  IN  A   192.168.56.10

child       IN NS ns.child
ns.child    IN A  192.168.56.20
child       IN DS 26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F6532742BF5D</code>

# 設定をチェックして再読み込み
$ sudo named-checkzone lab.test /etc/bind/db.lab.test
$ sudo rndc reload lab.test

# 設定が反映されているか確認
$ dig +norecurse @192.168.56.10 child.lab.test DS

; &lt;&lt;>> DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;>> +norecurse @192.168.56.10 child.lab.test DS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 51525
;; flags: qr aa ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 575f15af146df5dc010000006aa2a1275fb9a529e926c9cf (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      DS

;; ANSWER SECTION:
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      DS      26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F653 2742BF5D</span>

;; Query time: 0 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Thu Sep 10 12:23:03 UTC 2026
;; MSG SIZE  rcvd: 119</code></pre>



<h3 class="wp-block-heading">Parent DNSをDNSSEC署名</h3>



<p class="wp-block-paragraph">Parent DNS で作業。</p>



<pre class="wp-block-code"><code># ディレクトリ作成
$ sudo mkdir -p /etc/bind/keys/lab.test
$ cd /etc/bind/keys/lab.test

# ParentのZSKを生成
$ sudo dnssec-keygen -a ECDSAP256SHA256 -n ZONE lab.test
Generating key pair.
Klab.test.+013+42600

# ParentのKSKを生成
$ sudo dnssec-keygen -a ECDSAP256SHA256 -f KSK -n ZONE lab.test
Generating key pair.
Klab.test.+013+25095

# 生成結果を確認
$ ls -l /etc/bind/keys/lab.test
total 16
-rw-r--r-- 1 root bind 335 Sep 10 12:27 Klab.test.+013+25095.key
-rw------- 1 root bind 187 Sep 10 12:27 Klab.test.+013+25095.private
-rw-r--r-- 1 root bind 336 Sep 10 12:27 Klab.test.+013+42600.key
-rw------- 1 root bind 187 Sep 10 12:27 Klab.test.+013+42600.private

# 公開鍵を確認
$ cat /etc/bind/keys/lab.test/*.key
; This is a key-signing key, keyid 25095, for lab.test.
; Created: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Publish: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Activate: 20260910122739 (Thu Sep 10 12:27:39 2026)
lab.test. IN DNSKEY 257 3 13 nzPV3+LMX633npZfI3Seu2cR8SrTegHIi1sCK2OtNTQyRZg/v6yVkRDl nmr52oumop7xFxsx6vcZk3emfTsFbQ==
; This is a zone-signing key, keyid 42600, for lab.test.
; Created: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Publish: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Activate: 20260910122712 (Thu Sep 10 12:27:12 2026)
lab.test. IN DNSKEY 256 3 13 XGx8XP7w7bqg8k9cBXoPvDLsZQFUOAuUbdr8Bd8ZSH25ip1Bq75BGFYO yZhxy0DNqEsEPPpDt2qHAW/kdlJs3g==

# ParentのDNSKEYをゾーンファイルへ追加
$ sudo sh -c 'cat keys/lab.test/*.key >> db.lab.test'

# Serialを変更
$ sudo vim /etc/bind/db.lab.test　　
<code>$TTL 3600

@   IN  SOA ns dnsmaster (
        2026091002 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN  NS  ns.lab.test.

ns  IN  A   192.168.56.10

child       IN NS ns.child
ns.child    IN A  192.168.56.20
child       IN DS 26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F6532742BF5D
; This is a key-signing key, keyid 25095, for lab.test.
; Created: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Publish: 20260910122739 (Thu Sep 10 12:27:39 2026)
; Activate: 20260910122739 (Thu Sep 10 12:27:39 2026)
lab.test. IN DNSKEY 257 3 13 nzPV3+LMX633npZfI3Seu2cR8SrTegHIi1sCK2OtNTQyRZg/v6yVkRDl nmr52oumop7xFxsx6vcZk3emfTsFbQ==
; This is a zone-signing key, keyid 42600, for lab.test.
; Created: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Publish: 20260910122712 (Thu Sep 10 12:27:12 2026)
; Activate: 20260910122712 (Thu Sep 10 12:27:12 2026)
lab.test. IN DNSKEY 256 3 13 XGx8XP7w7bqg8k9cBXoPvDLsZQFUOAuUbdr8Bd8ZSH25ip1Bq75BGFYO yZhxy0DNqEsEPPpDt2qHAW/kdlJs3g==</code>

# 構文チェック
$ sudo named-checkzone lab.test /etc/bind/db.lab.test

# Parentゾーンを署名
$ cd /etc/bind/keys/lab.test
$ sudo dnssec-signzone \
  -S \
  -o lab.test \
  -f /etc/bind/db.lab.test.signed \
  /etc/bind/db.lab.test
Verifying the zone using the following algorithms:
- ECDSAP256SHA256
Zone fully signed:
Algorithm: ECDSAP256SHA256: KSKs: 1 active, 0 stand-by, 0 revoked
                            ZSKs: 1 active, 0 stand-by, 0 revoked
/etc/bind/db.lab.test.signed

# 署名済みファイルを読み込むよう設定変更
# db.lab.test → db.lab.test.signed
$ sudo vim /etc/bind/named.conf.local
<code>//
// Do any local configuration here
//

zone "lab.test" {
    type primary;
    file "/etc/bind/db.lab.test.signed";
};</code>

# 設定をチェックして再読み込み
$ sudo named-checkconf
$ sudo rndc reconfig

# 本当に署名済みゾーンを読んでいるか確認
$ sudo rndc zonestatus lab.test
name: lab.test
type: primary
<span class="swl-marker mark_orange">files: /etc/bind/db.lab.test.signed</span>
serial: 2026091002
nodes: 4
last loaded: Thu, 10 Sep 2026 12:32:37 GMT
secure: yes
inline signing: no
key maintenance: none
next resign node: lab.test/DNSKEY
next resign time: Sat, 03 Oct 2026 11:32:37 GMT
dynamic: no
reconfigurable via modzone: no

# ParentのDNSKEYを直接確認
$ dig +dnssec @192.168.56.10 lab.test DNSKEY

; &lt;&lt;>> DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;>> +dnssec @192.168.56.10 lab.test DNSKEY
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 61863
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: 3ad54fc7b29e4940010000006aa2a4c8a84d54b456af230d (good)
;; QUESTION SECTION:
;lab.test.                      IN      DNSKEY

;; ANSWER SECTION:
<span class="swl-marker mark_orange">lab.test.               3600    IN      DNSKEY  256 3 13 XGx8XP7w7bqg8k9cBXoPvDLsZQFUOAuUbdr8Bd8ZSH25ip1Bq75BGFYO yZhxy0DNqEsEPPpDt2qHAW/kdlJs3g==
lab.test.               3600    IN      DNSKEY  257 3 13 nzPV3+LMX633npZfI3Seu2cR8SrTegHIi1sCK2OtNTQyRZg/v6yVkRDl nmr52oumop7xFxsx6vcZk3emfTsFbQ==
lab.test.               3600    IN      RRSIG   DNSKEY 13 2 3600 20261010113237 20260910113237 25095 lab.test. m/UN/LdqgXsjAQTzPkqY/72gzpJyLH5THJlrhrwhnXzvYPqZ29UIK7Dg yyR4y2kbghbxg2bsePGxUngUUoz4rw==
lab.test.               3600    IN      RRSIG   DNSKEY 13 2 3600 20261010113237 20260910113237 42600 lab.test. +c+NJo2m+DDpeUGVRfYZQxXKDe3MT/LfWspon14H8PTlJH+Z/JgH4XZG OIPaDr26IwXsqMt+lzPB809OeQ+SzA==</span>

;; Query time: 0 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Thu Sep 10 12:38:32 UTC 2026
;; MSG SIZE  rcvd: 433

# ParentのDSを直接確認
$ dig +dnssec +norecurse @192.168.56.10 child.lab.test DS

; &lt;&lt;>> DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;>> +dnssec +norecurse @192.168.56.10 child.lab.test DS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 42626
;; flags: qr aa ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
; COOKIE: 5ab6af9666fe5062010000006aa2a50259f77941809ff655 (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      DS

;; ANSWER SECTION:
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      DS      26145 13 2 C0F99483CDF9CE53B7EFBCE8607A73DCAA7B6FA728F24ECFEB01F653 2742BF5D
child.lab.test.         3600    IN      RRSIG   DS 13 3 3600 20261010113237 20260910113237 42600 lab.test. nAmsL7wGWZzUk27uPO/aSFuwSOwC1oQPrbsvkuJbKjHgvh1QZ6EN4x0v CTTAopk9zi9kDC1d/c++aNfBZYwSOA==</span>

;; Query time: 0 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Thu Sep 10 12:39:30 UTC 2026
;; MSG SIZE  rcvd: 223</code></pre>



<h3 class="wp-block-heading">Unboundに lab.test のTrust Anchorを設定して、DNSSEC検証を有効化</h3>



<p class="wp-block-paragraph">Resolver で作業。</p>



<h4 class="wp-block-heading">Trust Anchor用のUnbound設定ファイルを作成する</h4>



<pre class="wp-block-code"><code># 専用ファイルを作成
# lab.test のDNSKEYは最初から信頼してよい と設定
$ sudo vim /etc/unbound/unbound.conf.d/lab-test-trust-anchor.conf
<code>server:
    trust-anchor: "lab.test. IN DNSKEY 257 3 13 nzPV3+LMX633npZfI3Seu2cR8SrTegHIi1sCK2OtNTQyRZg/v6yVkRDl nmr52oumop7xFxsx6vcZk3emfTsFbQ=="</code>

# domain-insecure: "lab.test." を削除
$ sudo vim /etc/unbound/unbound.conf.d/dns-lab.conf
<code>server:
    interface: 192.168.56.30
    access-control: 192.168.56.0/24 allow

    local-zone: "test." transparent

stub-zone:
    name: "lab.test."
    stub-addr: 192.168.56.10</code>

# Unboundの設定をチェックし、再読み込み
$ sudo unbound-checkconf
$ sudo systemctl restart unbound
$ sudo systemctl status unbound
● unbound.service - Unbound DNS server
     Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled; preset: enabled)
     Active: <span class="swl-marker mark_orange">active (running)</span> since Thu 2026-09-10 12:53:24 UTC; 4s ago

# Resolver自身からDNSSEC検証
$ dig +dnssec @192.168.56.30 www.child.lab.test A

; &lt;&lt;>> DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;>> +dnssec @192.168.56.30 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 41055
;; flags: qr rd ra <span class="swl-marker mark_orange">ad</span>; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1　　# ad = Authenticated Data(UnboundがDNSSEC検証に成功し、応答をSecureとして扱った)

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; ANSWER SECTION:
www.child.lab.test.     3600    IN      A       192.168.56.100
<span class="swl-marker mark_orange">www.child.lab.test.     3600    IN      RRSIG   A 13 4 3600 20261009122536 20260909122536 7661 child.lab.test. XX27GC+TFLVYuz+Jd8Ox7SyC5yxL1ifF+cuSmi+J8jcqgW8NQhR+Fi8s FaHbAEZuw691gEoZ22rXmWlCL5sbOQ==</span>　　# ChildのZSK(7661)によって署名されている

;; Query time: 13 msec
;; SERVER: 192.168.56.30#53(192.168.56.30) (UDP)
;; WHEN: Thu Sep 10 12:53:57 UTC 2026
;; MSG SIZE  rcvd: 173</code></pre>



<h3 class="wp-block-heading">Client → Unboundまで含めて正常に動作することを確認</h3>



<p class="wp-block-paragraph">Client で作業。</p>



<pre class="wp-block-code"><code>$ dig +dnssec @192.168.56.30 www.child.lab.test A

; &lt;&lt;>> DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;>> +dnssec @192.168.56.30 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 50729
;; flags: qr rd ra <span class="swl-marker mark_orange">ad</span>; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1　　# Authenticated Data

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 1232
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; ANSWER SECTION:
www.child.lab.test.     3334    IN      A       192.168.56.100
<span class="swl-marker mark_orange">www.child.lab.test.     3334    IN      RRSIG   A 13 4 3600 20261009122536 20260909122536 7661 child.lab.test. XX27GC+TFLVYuz+Jd8Ox7SyC5yxL1ifF+cuSmi+J8jcqgW8NQhR+Fi8s FaHbAEZuw691gEoZ22rXmWlCL5sbOQ==</span>

;; Query time: 3 msec
;; SERVER: 192.168.56.30#53(192.168.56.30) (UDP)
;; WHEN: Thu Sep 10 12:58:23 UTC 2026
;; MSG SIZE  rcvd: 173</code></pre>



<h2 class="wp-block-heading">まとめ</h2>



<p class="wp-block-paragraph">以上で、UnboundのTrust Anchorを起点として、Parent DNSの lab.test からChild DNSの child.lab.test、最終的に www.child.lab.test のAレコードまでDNSSECによる信頼の連鎖を構築できた。Unboundからの応答には ad フラグが付与され、DNSSEC検証に成功していることも確認できた。次回は、この正常な状態を基準として、署名やDSレコードを意図的に破壊し、DNSSEC検証がどのように失敗するかを確認する。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cybermemo.blog/dnssec-lab-configuration/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>DNSSEC検証 準備・DNS構築編</title>
		<link>https://cybermemo.blog/dnssec-lab-setup</link>
					<comments>https://cybermemo.blog/dnssec-lab-setup#respond</comments>
		
		<dc:creator><![CDATA[miyuki]]></dc:creator>
		<pubDate>Sat, 12 Sep 2026 12:50:49 +0000</pubDate>
				<category><![CDATA[セキュリティ]]></category>
		<category><![CDATA[検証]]></category>
		<category><![CDATA[BIND]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[DNSSEC]]></category>
		<category><![CDATA[Unbound]]></category>
		<guid isPermaLink="false">https://cybermemo.blog/?p=737</guid>

					<description><![CDATA[<p><img src="https://cybermemo.blog/wp-content/uploads/2026/08/検証アイキャッチ-1024x768.png" class="webfeedsFeaturedVisual" /></p>はじめに 何をしたいか DNSSECの信頼の連鎖を実際に構築し、DNS応答がどのように署名・検証されるのかを確認する。また、DNSSECに関する設定や署名を意図的に破壊し、検証失敗時にフルリゾルバやクライアントからどのよ [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><img src="https://cybermemo.blog/wp-content/uploads/2026/08/検証アイキャッチ-1024x768.png" class="webfeedsFeaturedVisual" /></p>
<h2 class="wp-block-heading">はじめに</h2>



<h3 class="wp-block-heading">何をしたいか</h3>



<p class="wp-block-paragraph">DNSSECの信頼の連鎖を実際に構築し、DNS応答がどのように署名・検証されるのかを確認する。また、DNSSECに関する設定や署名を意図的に破壊し、検証失敗時にフルリゾルバやクライアントからどのように見えるのかを確認する。本記事では検証前の準備を記載。</p>



<p class="wp-block-paragraph">準備・DNS構築編　本記事<br>DNSSEC構築編　<a href="https://cybermemo.blog/dnssec-lab-configuration">https://cybermemo.blog/dnssec-lab-configuration</a><br>破壊・検証編　<a href="https://cybermemo.blog/dnssec-lab-testing">https://cybermemo.blog/dnssec-lab-testing</a></p>



<h3 class="wp-block-heading">本記事で構築する構成</h3>



<p class="wp-block-paragraph">下記の通り、本記事ではDNSSECを使わず、普通のDNS名前解決を成立させることを目的とする。</p>



<pre class="wp-block-code"><code>              ┌─────────────┐
              │ Parent DNS  │　192.168.56.10/24
              │    BIND9    │　権威ゾーン: lab.test
              └──────┬──────┘
                     │
            child.lab.test を委任
                     │
                     ▼
              ┌─────────────┐　192.168.56.20/24
              │  Child DNS  │　権威ゾーン: child.lab.test
              │    BIND9    │　　　　　　　└─ www.child.lab.test → 192.168.56.100
              └─────────────┘
                     ▲
                     │ DNS問い合わせ
                     │
              ┌─────────────┐
              │  Resolver   │ 192.168.56.30/24
              │   Unbound   │
              └──────┬──────┘
                     ▲
                     │ DNS問い合わせ
              ┌─────────────┐
              │   Client    │ 192.168.56.40/24
              └─────────────┘</code></pre>



<h3 class="wp-block-heading">検証環境</h3>



<p class="wp-block-paragraph">仮想化ソフトウェア：Oracle VirtualBox<br>ゲストOS：Ubuntu Server 26.04.1 LTS（amd64）<br>権威DNS：BIND 9.20.24<br>フルリゾルバ：Unbound 1.24.2<br>DNS確認ツール：DiG 9.20.24<br>内部ネットワーク：192.168.56.0/24<br>検証ドメイン：lab.test / child.lab.test</p>



<h2 class="wp-block-heading">構築</h2>



<h3 class="wp-block-heading">IP設定とシステムインストール</h3>



<h4 class="wp-block-heading">共通設定</h4>



<p class="wp-block-paragraph">IP設定</p>



<pre class="wp-block-code"><code># IP情報確認(一部結果を抜粋)
$ ip addr

3: enp0s8: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

#設定ファイルの確認
$ sudo cat /etc/netplan/00-installer-config.yaml
# This is the network config written by 'subiquity'
network:
  ethernets:
    enp0s3:
      dhcp4: true
      dhcp6: true
      match:
        macaddress: mac
      set-name: enp0s3
  version: 2

#バックアップ
$ sudo cp /etc/netplan/00-installer-config.yaml \
/etc/netplan/00-installer-config.yaml.bak

#編集
$ sudo vim /etc/netplan/00-installer-config.yaml

# This is the network config written by 'subiquity'
network:
  ethernets:
    enp0s3:
      dhcp4: true
      dhcp6: true
      match:
        macaddress: mac
      set-name: enp0s3

<span class="swl-marker mark_orange">    enp0s8:
      dhcp4: false
      addresses:
        - 192.168.56.10(20,30,40)/24

  version: 2</span>

#構文チェック
$ sudo netplan generate

#接続チェック
$ sudo netplan try
Do you want to keep these settings?


Press ENTER before the timeout to accept the new configuration


Changes will revert in  xxx seconds
Configuration accepted.

#IP確認(一部結果を抜粋)
$ ip route
192.168.56.0/24 dev enp0s8 proto kernel scope link src 192.168.56.10</code></pre>



<h4 class="wp-block-heading">BIND（Parent DNS/Child DNS）のインストール</h4>



<p class="wp-block-paragraph">BINDと関連ツールのインストール</p>



<pre class="wp-block-code"><code># システムのパッケージリストを更新
$ sudo apt update

# システムのインストール
$ sudo apt install bind9 bind9-utils dnsutils

# BINDのバージョンを確認
$ named -v
BIND 9.20.24-1ubuntu0.3-Ubuntu (Stable Release) &lt;id:&gt;

# サービスの状態を確認
$ systemctl status bind9
● named.service - BIND Domain Name Server
     Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: <span class="swl-marker mark_orange">active (running)</span> since Wed 2026-09-02 13:32:41 UTC; 10min ago</code></pre>



<p class="is-style-icon_pen wp-block-paragraph">bind9 → DNSサーバー本体（named）<br>bind9-utils → BIND/DNSSEC管理用ツール<br>dnsutils → digなどのDNS調査ツール</p>



<h4 class="wp-block-heading">Unbound（Resolver）のインストール</h4>



<p class="wp-block-paragraph">フルリゾルバーのインストール</p>



<pre class="wp-block-code"><code># システムのパッケージリストを更新
$ sudo apt update
# システムのインストール
$ sudo apt install unbound dnsutils
# サービスの状態を確認
$ systemctl status unbound
● unbound.service - Unbound DNS server
     Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled; preset: enabled)
     <span class="swl-marker mark_orange">Active: active (running)</span> since Fri 2026-09-04 12:07:41 UTC; 1min 19s ago</code></pre>



<h4 class="wp-block-heading">dnsutils（Client）のインストール</h4>



<p class="wp-block-paragraph">DNS調査ツールのインストール</p>



<pre class="wp-block-code"><code># システムのパッケージリストを更新
$ sudo apt update
# システムのインストール
$ sudo apt install dnsutils
# バージョン確認
$ dig -v
DiG 9.20.24-1ubuntu0.3-Ubuntu</code></pre>



<h3 class="wp-block-heading">DNS設定</h3>



<h4 class="wp-block-heading">Parent DNS の基本設定</h4>



<pre class="wp-block-code"><code># BINDの設定ファイルを確認
$ ls -l /etc/bind/
total 20
-rw-r--r-- 1 xxxx yyyy 455 Jul 10 20:52 named.conf
-rw-r--r-- 1 xxxx yyyy  42 Jul 10 20:52 named.conf.local
-rw-r--r-- 1 xxxx yyyy  43 Jul 10 20:52 named.conf.options
-rw-r--r-- 1 xxxx yyyy 116 Jul 10 20:52 named.conf.root-hints
-rw-r----- 1 xxxx yyyy 100 Sep  2 13:32 rndc.key

# named.conf.local のバックアップ
sudo cp /etc/bind/named.conf.local /etc/bind/named.conf.local.bak

# ゾーンを定義
# 「lab.test について聞かれたら、/etc/bind/db.lab.test を見て答えます」という設定を記載
$ sudo vim /etc/bind/named.conf.local

<code>zone "lab.test" {
    type primary;
    file "/etc/bind/db.lab.test";
};</code>

# Parentのゾーンファイルを作成
$ sudo vim /etc/bind/db.lab.test

<code>$TTL 3600

@   IN  SOA ns dnsmaster (
        2026090401 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN  NS  ns.lab.test.

ns  IN  A   192.168.56.10</code>

# BIND全体の設定チェック
$ sudo named-checkconf

# ゾーンファイルをチェック
$ sudo named-checkzone lab.test /etc/bind/db.lab.test
zone lab.test/IN: loaded serial 2026090401
OK

# BINDを再読み込み
$ sudo systemctl reload bind9

# サービスの状態を確認
$ systemctl status bind9
● named.service - BIND Domain Name Server
     Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: <span class="swl-marker mark_orange">active (running)</span> since Fri 2026-09-04 12:25:10 UTC; 41min ago

# Parent自身に直接問い合わせる
$ dig @192.168.56.10 lab.test SOA

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.10 lab.test SOA
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, <span class="swl-marker mark_orange">status: NOERROR</span>, id: 12120　　# エラーなし
;; flags: qr <span class="swl-marker mark_orange">aa</span> rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1　　# aa = Authoritative Answer。権威回答であることを示す

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: a277f9c47bc5fcc9010000006a9ac27bfc5d5131662f9b64 (good)
;; QUESTION SECTION:
<span class="swl-marker mark_orange">;lab.test.                      IN      SOA</span>　　# lab.test.のSOAレコード要求

;; ANSWER SECTION:
<span class="swl-marker mark_orange">lab.test.               3600    IN      SOA     ns.lab.test. dnsmaster.lab.test. 2026090401 3600 900 604800 86400</span>　　# 設定したSOAレコードが反映されている

;; Query time: 0 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Fri Sep 04 13:07:07 UTC 2026
;; MSG SIZE  rcvd: 114

$ dig @192.168.56.10 lab.test NS

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.10 lab.test NS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 63569
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 0a6d1db6342fb2d1010000006a9ac29ddae1218c4b0305b2 (good)
;; QUESTION SECTION:
<span class="swl-marker mark_orange">;lab.test.                      IN      NS</span>　　# lab.test.のNSレコード要求

;; ANSWER SECTION:
<span class="swl-marker mark_orange">lab.test.               3600    IN      NS      ns.lab.test.</span>　　# 設定したNSレコードが反映されている

;; ADDITIONAL SECTION:
<span class="swl-marker mark_orange">ns.lab.test.            3600    IN      A       192.168.56.10</span>　　# 追加情報 → ちなみに ns.lab.test. のIPアドレスは 192.168.56.10

<span class="swl-marker mark_orange">;; Query time: 0 msec</span>　　# 同じVMから同じラボ内のDNSへ問い合わせているので非常に高速
<span class="swl-marker mark_orange">;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)</span>　　# 意図したParent BINDに問い合わせられている
;; WHEN: Fri Sep 04 13:07:41 UTC 2026
;; MSG SIZE  rcvd: 98</code></pre>



<h4 class="wp-block-heading">Child DNS の基本設定</h4>



<pre class="wp-block-code"><code># BINDの設定ファイルを確認
$ ls -l /etc/bind/
total 20
-rw-r--r-- 1 xxxx yyyy 455 Jul 10 20:52 named.conf
-rw-r--r-- 1 xxxx yyyy  42 Jul 10 20:52 named.conf.local
-rw-r--r-- 1 xxxx yyyy  43 Jul 10 20:52 named.conf.options
-rw-r--r-- 1 xxxx yyyy 116 Jul 10 20:52 named.conf.root-hints
-rw-r----- 1 xxxx yyyy 100 Sep  2 13:32 rndc.key

# named.conf.local のバックアップ
sudo cp /etc/bind/named.conf.local /etc/bind/named.conf.local.bak

# ゾーンを定義
# 「child.lab.test について聞かれたら、/etc/bind/db.child.lab.test を見て答えます」という設定を記載
$ sudo vim /etc/bind/named.conf.local

<code>zone "child.lab.test" {
    type primary;
    file "/etc/bind/db.child.lab.test";
};</code>

# Childのゾーンファイルを作成
$ sudo vim /etc/bind/db.child.lab.test

<code>$TTL 3600

@   IN SOA ns dnsmaster (
        2026090401 ; Serial
        3600       ; Refresh
        900        ; Retry
        604800     ; Expire
        86400      ; Negative Cache TTL
)

    IN NS ns

ns  IN A 192.168.56.20
www IN A 192.168.56.100</code>

# BIND全体の設定チェック
$ sudo named-checkconf

# ゾーンファイルをチェック
$ sudo named-checkzone child.lab.test /etc/bind/db.child.lab.test
zone child.lab.test/IN: loaded serial 2026090401
OK

# BINDを再読み込み
$ sudo systemctl reload bind9

# サービスの状態を確認
$ systemctl status bind9
● named.service - BIND Domain Name Server
     Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: <span class="swl-marker mark_orange">active (running)</span> since Fri 2026-09-04 12:25:13 UTC; 1h 15min ago

# Child自身に直接問い合わせる
$ dig @192.168.56.20 child.lab.test SOA

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.20 child.lab.test SOA
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 45719
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 2235b8f90298a6ac010000006a9aca9e4d064bf9ef5ff1fb (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      SOA

;; ANSWER SECTION:
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      SOA     ns.child.lab.test. dnsmaster.child.lab.test. 2026090401 3600 900 604800 86400</span>　　# 設定したSOAレコードが反映されている

;; Query time: 0 msec
;; SERVER: 192.168.56.20#53(192.168.56.20) (UDP)
;; WHEN: Fri Sep 04 13:41:50 UTC 2026
;; MSG SIZE  rcvd: 120

$ dig @192.168.56.20 child.lab.test NS

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.20 child.lab.test NS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 22244
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 18cc501e70a95b5a010000006a9acaad689bc4f2bd82ac21 (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      NS

;; ANSWER SECTION:
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      NS      ns.child.lab.test.</span>　　# 設定したNSレコードが反映されている

;; ADDITIONAL SECTION:
<span class="swl-marker mark_orange">ns.child.lab.test.      3600    IN      A       192.168.56.20</span>　　# 追加情報 → ちなみに ns.child.lab.test. のIPアドレスは 192.168.56.20

;; Query time: 0 msec
;; SERVER: 192.168.56.20#53(192.168.56.20) (UDP)
;; WHEN: Fri Sep 04 13:42:05 UTC 2026
;; MSG SIZE  rcvd: 104

<span class="swl-marker mark_orange">$ dig @192.168.56.20 www.child.lab.test A</span>　　# ここが ParentDNS と違う部分

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.20 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 38021
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 572e7d93946f04eb010000006a9acbc2c6834dc08c91a8ae (good)
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; ANSWER SECTION:
<span class="swl-marker mark_orange">www.child.lab.test.     3600    IN      A       192.168.56.100</span>　　# 設定したwwwのAレコードが反映されている

;; Query time: 0 msec
;; SERVER: 192.168.56.20#53(192.168.56.20) (UDP)
;; WHEN: Fri Sep 04 13:46:42 UTC 2026
;; MSG SIZE  rcvd: 91</code></pre>



<h4 class="wp-block-heading">Parent DNS に child.lab.test の委任を設定</h4>



<pre class="wp-block-code"><code># ゾーンファイルをバックアップ
$ sudo cp /etc/bind/db.lab.test /etc/bind/db.lab.test.bak

$ sudo vim /etc/bind/db.lab.test        
<code>2026090402 ; Serial</code>　　　　　　　　# ゾーンファイルのシリアルを更新
<code>child       IN NS ns.child
ns.child    IN A  192.168.56.20</code>　　# ゾーンファイルの最下部に以下設定を追加

# BIND全体の設定チェック
$ sudo named-checkconf

# ゾーンファイルをチェック
$ sudo named-checkzone lab.test /etc/bind/db.lab.test
zone lab.test/IN: getaddrinfo(ns.child.lab.test) failed: Temporary failure in name resolution
zone lab.test/IN: loaded serial 202609040<span class="swl-marker mark_orange">2</span>
OK

# BINDを再読み込み
$ sudo systemctl reload bind9

# サービスの状態を確認
$ systemctl status bind9
● named.service - BIND Domain Name Server
     Loaded: loaded (/usr/lib/systemd/system/named.service; enabled; preset: enabled)
     Active: <span class="swl-marker mark_orange">active (running)</span> since Fri 2026-09-04 12:25:10 UTC; 1h 40min ago

# Parent自身に直接問い合わせる(再帰問い合わせを要求する)　→　再帰処理では名前解決に失敗しSERVFAILとなった
dig @192.168.56.10 child.lab.test NS
; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.10 child.lab.test NS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, <span class="swl-marker mark_orange">status: SERVFAIL</span>, id: 19522　　# SERVFAIL(サーバー側の異常で名前解決に失敗)
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: fe9a881e33cb98ad010000006a9ad0c464bcd0c3c80d2cfc (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      NS

;; Query time: 3 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Fri Sep 04 14:08:04 UTC 2026
;; MSG SIZE  rcvd: 71

# Parent自身に直接問い合わせる(再帰問い合わせを要求しない)
$ dig +norecurse @192.168.56.10 child.lab.test NS

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +norecurse @192.168.56.10 child.lab.test NS
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 27945
;; flags: <span class="swl-marker mark_orange">qr ra</span>; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 2　　## aa = Authoritative Answer のフラグなしなので、権威回答ではなく参照応答

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: 79d7c1aedd81ea0e010000006a9ad0ba20d4d76f47b1c251 (good)
;; QUESTION SECTION:
;child.lab.test.                        IN      NS

;; AUTHORITY SECTION:　　# child.lab.test については ns.child.lab.test に聞いてください。と返答されている
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      NS      ns.child.lab.test.</span>　　# 設定したNSレコードが反映されている

;; ADDITIONAL SECTION:
<span class="swl-marker mark_orange">ns.child.lab.test.      3600    IN      A       192.168.56.20</span>　　# 追加情報 → ちなみに ns.child.lab.test. のIPアドレスは 192.168.56.20(グルーレコード)

;; Query time: 5 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Fri Sep 04 14:07:54 UTC 2026
;; MSG SIZE  rcvd: 104

$ dig +norecurse @192.168.56.10 www.child.lab.test A

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; +norecurse @192.168.56.10 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 7879
;; flags: qr ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: d24b4a0ee76a5063010000006a9ad5a7cc24a0022b2a437a (good)
;; QUESTION SECTION:
;www.child.lab.test.            IN      A

;; AUTHORITY SECTION:　　# child.lab.test については ns.child.lab.test に聞いてください。と返答されている
<span class="swl-marker mark_orange">child.lab.test.         3600    IN      NS      ns.child.lab.test.</span>　　# 設定したNSレコードが反映されている

;; ADDITIONAL SECTION:
<span class="swl-marker mark_orange">ns.child.lab.test.      3600    IN      A       192.168.56.20</span>　# 追加情報 → ちなみに ns.child.lab.test. のIPアドレスは 192.168.56.20(グルーレコード)。child.lab.test はChildDNSへ委任されているため、Parentは www.child.lab.test のAレコードを権威回答せず、委任先の情報を返す

;; Query time: 0 msec
;; SERVER: 192.168.56.10#53(192.168.56.10) (UDP)
;; WHEN: Fri Sep 04 14:28:55 UTC 2026
;; MSG SIZE  rcvd: 108</code></pre>



<h3 class="wp-block-heading">Resolver の設定</h3>



<pre class="wp-block-code"><code># 設定ファイルを確認
$ sudo cat /etc/unbound/unbound.conf
$ sudo find /etc/unbound -maxdepth 2 -type f -print

# ラボ用設定ファイルを新規作成
$ sudo vim /etc/unbound/unbound.conf.d/dns-lab.conf
<code>server:
    interface: 192.168.56.30
    access-control: 192.168.56.0/24 allow

    local-zone: "test." transparent
    domain-insecure: "lab.test."

stub-zone:
    name: "lab.test."
    stub-addr: 192.168.56.10</code>

# 構文チェック
$ sudo unbound-checkconf

# Unboundを再起動
$ sudo systemctl restart unbound

# サービスの状態を確認
$ systemctl status unbound
● unbound.service - Unbound DNS server
     Loaded: loaded (/usr/lib/systemd/system/unbound.service; enabled; preset: enabled)
     Active: <span class="swl-marker mark_orange">active (running)</span> since Tue 2026-09-08 13:27:42 UTC; 36s ago

$ dig @192.168.56.30 www.child.lab.test A

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.30 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 62746
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
<span class="swl-marker mark_orange">;www.child.lab.test.            IN      A</span>　　# www.child.lab.test のAレコードを問い合わせ

;; ANSWER SECTION:
<span class="swl-marker mark_orange">www.child.lab.test.     3600    IN      A       192.168.56.100</span>　　# 名前解決できている

;; Query time: 8 msec
;; SERVER: 192.168.56.30#53(192.168.56.30) (UDP)
;; WHEN: Tue Sep 08 13:36:29 UTC 2026
;; MSG SIZE  rcvd: 63</code></pre>



<h3 class="wp-block-heading">Client で名前解決ができるか確認</h3>



<pre class="wp-block-code"><code>$ dig @192.168.56.30 www.child.lab.test A

; &lt;&lt;&gt;&gt; DiG 9.20.24-1ubuntu0.3-Ubuntu &lt;&lt;&gt;&gt; @192.168.56.30 www.child.lab.test A
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 63459
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
<span class="swl-marker mark_orange">;www.child.lab.test.            IN      A</span>　　# www.child.lab.test のAレコードを問い合わせ

;; ANSWER SECTION:
<span class="swl-marker mark_orange">www.child.lab.test.     3187    IN      A       192.168.56.100</span>　　# 名前解決できている

;; Query time: 3 msec
;; SERVER: 192.168.56.30#53(192.168.56.30) (UDP)
;; WHEN: Tue Sep 08 13:43:22 UTC 2026
;; MSG SIZE  rcvd: 63</code></pre>



<h2 class="wp-block-heading">おまけ</h2>



<h3 class="wp-block-heading">SERVFAIL エラーの検証</h3>



<p class="wp-block-paragraph">「Parent DNS に child.lab.test の委任を設定」で +norecurse（再帰問い合わせを要求しない）をつけないとSERVFAIL（サーバー側の異常で名前解決に失敗）となる原因を調査した。</p>



<h4 class="wp-block-heading">検証</h4>



<p class="wp-block-paragraph">ターミナル1</p>



<pre class="wp-block-code"><code># パケットキャプチャ(Parent DNS)
~$ sudo tcpdump -ni any port 53
tcpdump: WARNING: any: That device doesn't support promiscuous mode
(Promiscuous mode not supported on the "any" device)
tcpdump: verbose output suppressed, use -v&#91;v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
12:12:22.481102 lo    In  IP 192.168.56.10.45482 &gt; 192.168.56.10.53: 40442 &#91;1au] NS? child.lab.test. (55)
12:12:22.481720 lo    In  IP 192.168.56.10.53 &gt; 192.168.56.10.45482: 40442 0/1/2 (104)
12:12:32.346678 lo    In  IP 192.168.56.10.37116 &gt; 192.168.56.10.53: 65160+ &#91;1au] NS? child.lab.test. (55)
12:12:32.347314 enp0s8 Out IP 192.168.56.10.33827 &gt; 192.168.56.20.53: 15920 &#91;1au] NS? child.lab.test. (55)
12:12:32.348661 enp0s8 In  IP 192.168.56.20.53 &gt; 192.168.56.10.33827: 15920* 1/0/2 NS ns.child.lab.test. (104)
12:12:32.350616 lo    In  IP 192.168.56.10.53 &gt; 192.168.56.10.37116: 65160 ServFail 0/0/1 (71)</code></pre>



<p class="wp-block-paragraph">ターミナル2</p>



<pre class="wp-block-code"><code>$ dig +norecurse @192.168.56.10 child.lab.test NS
$ dig @192.168.56.10 child.lab.test NS</code></pre>



<h4 class="wp-block-heading">検証結果</h4>



<p class="is-style-sticky_box wp-block-paragraph">+norecurse で問い合わせたとき</p>



<pre class="wp-block-code"><code>12:12:22.481102 lo    In  IP 192.168.56.10.45482 &gt; 192.168.56.10.53: 40442 &#91;1au] NS? child.lab.test. (55)</code></pre>



<p class="wp-block-paragraph">が 問い合わせ。</p>



<ul class="wp-block-list">
<li>Parent自身 → ParentのDNS(53番ポート)</li>



<li>「child.lab.test のNSを教えてください」</li>



<li>+norecurseなので「他のDNSへ問い合わせに行かなくていいです」</li>
</ul>



<pre class="wp-block-code"><code>12:12:22.481720 lo    In  IP 192.168.56.10.53 &gt; 192.168.56.10.45482: 40442 0/1/2 (104)</code></pre>



<p class="wp-block-paragraph">が回答。</p>



<ul class="wp-block-list">
<li>Parent DNS → Parent DNS(dig)</li>



<li>0/1/2 = ANSWER 0件 / AUTHORITY 1件 / ADDITIONAL 2件</li>
</ul>



<p class="wp-block-paragraph">この 0/1/2 は、以前 dig で見た、</p>



<pre class="wp-block-code"><code>ANSWER: 0
AUTHORITY: 1
ADDITIONAL: 2</code></pre>



<p class="wp-block-paragraph">と同じもの。</p>



<p class="wp-block-paragraph">このログから読み取れる全体の動きは下記。</p>



<pre class="wp-block-code"><code>dig
 │
 │「child.lab.testのNSは？」
 │「再帰しなくていいよ」
 ▼
Parent
 │
 │ 自分が持っている委任情報を見る
 │
 │「ns.child.lab.testに聞いて」
 ▼
dig</code></pre>



<p class="is-style-big_icon_point wp-block-paragraph">重要なのは、<strong>この通信にParent→Childの通信がないこと</strong>。<br>これが +norecurse の動き。</p>



<p class="is-style-sticky_box wp-block-paragraph">+norecurse なし</p>



<pre class="wp-block-code"><code>12:12:32.346678 lo    In  IP 192.168.56.10.37116 &gt; 192.168.56.10.53: 65160+ &#91;1au] NS? child.lab.test. (55)</code></pre>



<p class="wp-block-paragraph">が問い合わせ。</p>



<ul class="wp-block-list">
<li>Parent自身 → Parent DNS</li>



<li>「child.lab.test のNSを教えてください」</li>



<li>今回は再帰要求あり</li>
</ul>



<p class="is-style-big_icon_point wp-block-paragraph">+norecurse とよく似たログだが、65160+ の + がポイント。<br>tcpdumpのDNS表示では、この + はRD（Recursion Desired）が立っていることを示す。<br><br>※tcpdump 公式GitHubリポジトリを参照<br><a href="https://github.com/the-tcpdump-group/tcpdump/blob/master/print-domain.c" data-type="link" data-id="https://github.com/the-tcpdump-group/tcpdump/blob/master/print-domain.c">https://github.com/the-tcpdump-group/tcpdump/blob/master/print-domain.c</a><br><code>else {<br>/* this is a request */<br>ND_PRINT("%u%s%s%s", GET_BE_U_2(np-&gt;id),<br>ns_ops[DNS_OPCODE(flags)],<br>DNS_RD(flags) ? "+" : "",<br>DNS_CD(flags) ? "%" : "");</code></p>



<pre class="wp-block-code"><code>12:12:32.347314 enp0s8 Out IP 192.168.56.10.33827 &gt; 192.168.56.20.53: 15920 &#91;1au] NS? child.lab.test. (55)</code></pre>



<p class="wp-block-paragraph">が Child DNS への問い合わせ。</p>



<ul class="wp-block-list">
<li>Parent DNS → Child DNS</li>



<li>Parentが「child.lab.test のNSを教えてください」とChildへ問い合わせた</li>
</ul>



<pre class="wp-block-code"><code>12:12:32.348661 enp0s8 In  IP 192.168.56.20.53 &gt; 192.168.56.10.33827: 15920* 1/0/2 NS ns.child.lab.test. (104)</code></pre>



<p class="wp-block-paragraph">が Child DNS からの回答。</p>



<ul class="wp-block-list">
<li>Child DNS → Parent DNS</li>



<li>「child.lab.test のNSは ns.child.lab.test です」と回答</li>



<li>* はAA(Authoritative Answer)が立っていることを示す(上述のGitHubリポジトリを参照)</li>
</ul>



<pre class="wp-block-code"><code>12:12:32.350616 lo    In  IP 192.168.56.10.53 &gt; 192.168.56.10.37116: 65160 ServFail 0/0/1 (71)</code></pre>



<p class="wp-block-paragraph">が最終回答。</p>



<ul class="wp-block-list">
<li>Parent DNS → Parent DNS(dig)</li>



<li>なぜか最終的に「名前解決に失敗しました(SERVFAIL)」と回答</li>
</ul>



<p class="wp-block-paragraph">このログから読み取れる全体の動きは下記。</p>



<pre class="wp-block-code"><code>dig
 │
 │ child.lab.test NS?
 │ RD=1「必要なら代わりに調べて」
 ▼
Parent
 │
 │ 委任情報を確認
 │
 ▼
Child
 │
 │「NSはns.child.lab.testです」
 │ AA=1
 ▼
Parent
 │
 │ ここまでは成功
 │
 ▼
dig

SERVFAIL(?)</code></pre>



<p class="is-style-sticky_box wp-block-paragraph">tcpdump だけでは分からないので追加調査</p>



<pre class="wp-block-code"><code># ジャーナル確認
journalctl -n 20
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving 'test/DS/IN': 199.7.91.13#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 199.7.91.13#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving 'test/DS/IN': 192.203.230.10#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 198.97.190.53#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving 'test/DS/IN': 192.112.36.4#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 192.203.230.10#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving 'test/DS/IN': 192.36.148.17#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 192.112.36.4#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving 'test/DS/IN': 193.0.14.129#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 192.36.148.17#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving 'test/DS/IN': 170.247.170.2#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 193.0.14.129#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving 'test/DS/IN': 192.33.4.12#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 170.247.170.2#53
Sep 08 12:55:33 dns-parent named&#91;962]: network unreachable resolving './NS/IN': 192.33.4.12#53
Sep 08 12:55:33 dns-parent named&#91;962]: broken trust chain resolving 'child.lab.test/NS/IN': 192.168.56.20#53
Sep 08 12:55:33 dns-parent named&#91;962]: resolver priming query complete: failure</code></pre>



<ul class="wp-block-list">
<li>ルートDNSサーバーへの test/DS や ./NS の問い合わせが network unreachable となっている</li>



<li>broken trust chain resolving から信頼の連鎖を築けなかったことが判明</li>
</ul>



<p class="wp-block-paragraph">このログから読み取れる全体の動きは下記。</p>



<pre class="wp-block-code"><code>RD=1
 ↓
Parentが再帰処理開始
 ↓
自分の委任情報を利用
 ↓
192.168.56.20のChildへ問い合わせ
 ↓
Childが正常な権威回答
 ↓
Parentの再帰処理でDNSSEC検証を行おうとする
 ↓
test/DSなどを確認しようとする
 ↓
外部DNSへ到達できない
 ↓
broken trust chain
 ↓
SERVFAIL</code></pre>



<h3 class="wp-block-heading">結論</h3>



<p class="wp-block-paragraph">検証サーバーを外部ネットワークに接続していなかったため、Parent DNSがDNSSEC検証に必要な外部DNSへの問い合わせを完了できず、信頼の連鎖を構築できなかった。その結果、再帰問い合わせは SERVFAIL となった。</p>



<h2 class="wp-block-heading">まとめ</h2>



<p class="wp-block-paragraph">今回は、Parent DNS、Child DNS、Unbound、Clientを構築し、DNSSECを使用しない通常のDNS名前解決が正常に行えることを確認した。<br>次回は、この環境にDNSSECを導入し、Parent DNSとChild DNSの署名、DSレコードの登録、UnboundへのTrust Anchor設定を行い、DNSSECによる信頼の連鎖を構築する。</p>
]]></content:encoded>
					
					<wfw:commentRss>https://cybermemo.blog/dnssec-lab-setup/feed</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
