【DNS入門 第8回】コマンドで調べる ― dig・nslookup・Resolve-DnsName・resolvectlの読み方

DNS サーバー
スポンサーリンク
スポンサーリンク

「nslookupでは新しいIPが返るのに、ブラウザーでは古いサーバーにつながるんです」
「digだとSERVFAILなんですが、何から見ればいいですか?」

DNSのトラブルでは、どのコマンドで、どこに、何を聞いたかで見えるものが変わります。コマンドの癖を知らないと、正しい結果を見ているのに、間違った結論を出してしまうこともあります。

第7回までで、DNSの仕組みと運用をひととおり見てきました。第8回では、それを実際に調べるための道具として、dig・nslookup・PowerShellのResolve-DnsName・Linuxのresolvectlの使い方と、出力の読み方をまとめます。


digの出力の全体像

まずはdig www.example.jp Aの出力です(抜粋)。digはBINDに付属し、Linux・Macで使えます。

;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 37473
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;www.example.jp.                IN      A

;; ANSWER SECTION:
www.example.jp.         245     IN      A       203.0.113.10

;; Query time: 12 msec
;; SERVER: 192.0.2.53#53(192.0.2.53) (UDP)
;; MSG SIZE  rcvd: 59

;で始まる行は説明、;の無い行がレコードそのものです。

  • HEADER:応答コード(status)、フラグ、各セクションの件数。まずここを見る
  • OPT PSEUDOSECTION:EDNSの情報。拡張エラー(EDE)もここに出る
  • QUESTION/ANSWER:何を聞いて何が返ったか。ANSWERの2列目が残りのTTL(秒)
  • 最後の4行:所要時間、答えたサーバーと通信方式(UDP/TCP)、応答の大きさ
digのANSWERの1行が名前・TTL(残り秒)・クラス・型・値の5列からなることと、読む順が①HEADER(status)②ANSWER③SERVERの行であることを示す図

読む順は、① HEADER(status)→ ② ANSWER → ③ SERVERの行です。どの型のレコードも、名前・TTL・クラス・型・値の5列の並びは同じです。


ヘッダーとフラグの読み方

項目表示の例意味
statusNOERROR/NXDOMAIN/SERVFAIL応答コード(RCODE)。最初に確認する
flags: qrqr応答であることを示す
flags: aaaa権威DNSサーバー自身の回答。キャッシュからの回答には付かない
flags: rd/rard rard=再帰を依頼した、ra=このサーバーは再帰に応じられる
flags: ad/cdadad=リゾルバーがDNSSECで検証済み、cd=検証しないよう依頼した
flags: tctc応答が切り詰められた。TCPで問い合わせ直す(第4回)
件数ANSWER: 1, AUTHORITY: 0各セクションのレコード数。ANSWER: 0 は「答えが無い」
OPT の行udp: 1232、flags: do、COOKIE、EDEEDNSのバッファーサイズ、DNSSEC要求(do)、DNS Cookie、拡張エラー

status: NOERRORでもANSWER: 0なら答えはありません(NODATA)。また、権威DNSサーバーにrd付きで問い合わせると;; WARNING: recursion requested but not availableと表示されます。再帰に応じないサーバーという意味で、異常ではありません。


セクション・TTL・所要時間

  • ANSWER:答え(CNAMEをたどった場合は、その途中も)
  • AUTHORITY:委任先のNSや、答えが無いときのSOA
  • ADDITIONAL:NSのIPアドレス(グルー)など
権威DNSのTTLは設定値の300のまま、キャッシュDNSのTTLは時間とともに減り0で消えたら権威から取り直すことと、Query timeが0〜1 msecならキャッシュ、数十〜数百msecなら権威まで問い合わせたことを示す図

レコードの2列目の数値は、TTL(キャッシュしてよい残り秒数)です。

  • 権威DNSサーバーに聞くと設定値そのもの
  • キャッシュDNSサーバーに聞くと時間とともに減った値

2回引いてTTLが減っていれば、キャッシュからの答えです。

Query timeも手がかりになります。0〜1 msecならキャッシュから、数十〜数百msecなら権威DNSサーバーまで問い合わせたと推測できます。SERVERの行は実際に答えたサーバーで、127.0.0.53ならLinuxのsystemd-resolvedが答えています。


digの主なオプション

オプション意味使いどころ
@192.0.2.53問い合わせ先のサーバーを指定する社内DNSと外部DNS、権威DNSを直接比べる
MX・AAAA・TXT 等レコード型を指定する(既定は A)型の登録漏れを確かめる
+short答えの値だけを表示するスクリプト、複数サーバーの比較
+norec再帰を依頼しない(rd を付けない)権威DNSへの確認、キャッシュの中身を見る
+traceルートから委任を順にたどる委任・グルーの誤りを探す
-x 203.0.113.10逆引き(PTR)を問い合わせる逆引きの登録を確かめる
+tcpTCPで問い合わせるTCP/53が通るかを確かめる
+dnssecDOビットを付け、RRSIGも表示する署名の有無と有効期限を確かめる
$ dig @198.51.100.53 example.jp MX +norec +noall +answer
$ dig @192.0.2.53 www.example.jp +dnssec +bufsize=1232 +nsid
PS> Resolve-DnsName example.jp -Type MX -NoRecursion -Server 198.51.100.53   # 1行目と同じ

ほかに、+nsid(エニーキャストのどの拠点が答えたか)、+bufsize=N(EDNSのバッファーサイズ。大きな応答が落ちる問題の確認)、+cd(DNSSECの検証を止めて取得)、+noall +answer(答えだけ表示)もよく使います。


dig +traceの読み方

+traceは、ルートから委任を順にたどって、各段階の応答を表示します。

$ dig +trace www.example.jp
.                  81000   IN  NS   a.root-servers.net.
(略:ルートサーバーの NS と RRSIG)
;; Received 525 bytes from 192.0.2.53#53(192.0.2.53) in 3 ms

jp.                172800  IN  NS   a.dns.jp.
(略:jp の NS と DS・RRSIG)
;; Received 834 bytes from 199.7.83.42#53(l.root-servers.net) in 12 ms

example.jp.        86400   IN  NS   ns1.example.jp.
example.jp.        86400   IN  NS   ns2.example.jp.
;; Received 120 bytes from 203.119.1.1#53(a.dns.jp) in 8 ms

www.example.jp.    300     IN  A    203.0.113.10
;; Received 59 bytes from 198.51.100.53#53(ns1.example.jp) in 5 ms
  • ブロックごとに「誰に聞いて(Received … from)、どこへ委任されたか」を読む。最初のブロックだけは、手元のリゾルバーからルートの一覧を得ている
  • dig自身が反復問い合わせをするため、キャッシュDNSを通らない。通常の問い合わせと結果が違えば、キャッシュやリゾルバーの設定を疑う
  • 途中で止まる、親のNSと子のNSが違う、グルーのIPが古い、といった委任の誤りが見つかる(第2回)

dig 9.20ではDS・RRSIGの行も表示されます。なお、社内から外部のDNS(UDP/TCP 53)へ直接出られないネットワークでは、+traceは失敗します。PowerShellに同じ機能は無く、-NoRecursionでルート・TLD・権威と順に聞きます。


delvでDNSSECの検証結果を見る

delvは、BINDに付属する、DNSSECの検証を自分で行うdigです。リゾルバーから受け取った応答を、内蔵のルートの信頼アンカーから検証します(第9回)。

$ delv www.example.jp A
; fully validated
www.example.jp.   300  IN  A      203.0.113.10
www.example.jp.   300  IN  RRSIG  A 13 3 300 20261009000000 20260925000000 12345 example.jp. (略)

$ delv www.unsigned.example.jp A
; unsigned answer
www.unsigned.example.jp. 300 IN A 203.0.113.20

$ delv @192.0.2.53 +cd www.bad.example.com A
;; validating bad.example.com/DNSKEY: no valid signature found (DS)
;; no valid RRSIG resolving 'bad.example.com/DNSKEY/IN': 192.0.2.53#53
;; broken trust chain resolving 'www.bad.example.com/A/IN': 192.0.2.53#53
;; resolution failed: broken trust chain
delvの1行目の判定がfully validated(署名を検証できた)、unsigned answer(署名の無いゾーンで失敗ではない)、broken trust chain(親のDSと子のDNSKEYの間で連鎖が切れている)のどれかを示し、検証するとSERVFAILになるキャッシュDNSから+cdで取り寄せてdelvで検証することを示す図

1行目で結果が分かります。

  • fully validated:検証成功
  • unsigned answer:署名の無いゾーン。検証の対象外で、失敗ではない
  • negative response, fully validated:「無い」ことを検証済み

検証するリゾルバーは失敗時にSERVFAILしか返さないため、+cdを付けて中身を取り寄せ、delvに検証させます。検証の過程を詳しく見るには+vtraceを付けます。「署名なし」と「検証失敗」を取り違えないことが大事です。


nslookup(ワンライナー・対話モード)

Windowsでおなじみのnslookupです。

C:\> nslookup www.example.jp.
サーバー:  dns1.corp.example.jp
Address:  192.0.2.53

権限のない回答:
名前:    www.example.jp
Address:  203.0.113.10

C:\> nslookup -type=mx example.jp. 198.51.100.53

C:\> nslookup
> server 198.51.100.53
> set type=aaaa
> set debug
> www.example.jp.
> exit
  • ワンライナーはnslookup -type=型 名前 サーバーの順。名前の末尾に「.」を付けて、searchドメインの付加による余計な問い合わせを防ぐ
  • 対話モードのset type=・serverは以後ずっと効き続ける。結果がおかしいときはset allで今の設定を確認する
  • set debugでHEADER(rcode、answersの件数)、TTL、AUTHORITY、ADDITIONALが表示される
  • 「権限のない回答」は、キャッシュDNSからの回答(aaが無い)という意味。サーバー名がUnKnownなのは、そのサーバーの逆引きが無いだけ

ここが冒頭の疑問のポイントです。nslookupはOSのDNSクライアントを使わず自分で問い合わせるため、hostsファイルやNRPT(名前解決ポリシー)が効きません。つまり、nslookupの結果とアプリの動きは一致するとは限りません。


Resolve-DnsNameとipconfig(Windows)

そこで、Windowsでアプリの動きを再現するなら、Resolve-DnsNameを使います。

PS> Resolve-DnsName www.example.jp -Type A -Server 192.0.2.53 -DnsOnly

Name                  Type   TTL   Section    IPAddress
----                  ----   ---   -------    ---------
www.example.jp        A      245   Answer     203.0.113.10

PS> Resolve-DnsName example.jp -Type MX -NoHostsFile -DnssecOk
PS> ipconfig /displaydns        # DNSクライアントのキャッシュを表示
PS> ipconfig /flushdns          # キャッシュを削除
PS> Get-DnsClientCache ; Clear-DnsClientCache    # PowerShell 版
アプリとResolve-DnsNameはDNS Clientサービスを通ってhostsファイル・キャッシュ・NRPTを経てDNSサーバーへ行くが、nslookupはDNS Clientを通らず直接DNSサーバーへ行くことを示す図
  • Resolve-DnsNameは、OSのDNSクライアントと同じ経路(NRPTも含む)で名前を解決する。結果はオブジェクトで返るため、スクリプトで扱いやすい
  • 主なパラメーター:-Type、-Server、-DnsOnly(LLMNR・NetBIOSを使わない)、-NoHostsFile、-CacheOnly、-NoRecursion、-DnssecOk、-TcpOnly
  • ipconfig /displaydnsには、「名前が存在しない」というネガティブキャッシュも表示される
  • /flushdnsで消えるのはOSのキャッシュだけ。ブラウザー自身のキャッシュや、キャッシュDNSサーバーのキャッシュは残る

digとResolve-DnsNameの対応

ISCはBIND 9.18(2022年1月)からWindows対応をやめ、Windows版が提供された最後の9.16系も2024年4月にサポートを終えました。現在のWindowsには標準のdigが無いため、PowerShellのResolve-DnsNameを使います。

やりたいことdig(Linux・Mac)PowerShell(Windows 標準)
型とサーバーを指定して引くdig @192.0.2.53 example.jp MXResolve-DnsName example.jp -Type MX -Server 192.0.2.53
再帰なしで権威DNSに聞く+norec-NoRecursion
TCPで聞く+tcp-TcpOnly
逆引きdig -x 192.0.2.10Resolve-DnsName 192.0.2.10
DNSSECの署名を取る/検証を止める+dnssec/+cd-DnssecOk/-DnssecCd
hosts・LLMNRを除きDNSだけで引く(常にDNSだけ)-DnsOnly -NoHostsFile
値だけを取り出す+short(Resolve-DnsName 名前).IPAddress など
フラグ・EDE・+trace・CAA/HTTPS型表示・実行できるできない(Linux等のdigで確認)

OSと同じ経路(キャッシュ・NRPT)で引ける点は、digより優れています。ゾーン転送の確認だけは、nslookupのls -dを使います。

Resolve-DnsNameの結果の読み方

PS> Resolve-DnsName www.example.jp -Type MX -Server 192.0.2.53      # NODATA
Name        Type  TTL   Section    PrimaryServer     NameAdministrator       SerialNumber
example.jp  SOA   900   Authority  ns1.example.jp    hostmaster.example.jp   2026092501

PS> Resolve-DnsName nosuch.example.jp
Resolve-DnsName : nosuch.example.jp : DNS 名がありません。                 # NXDOMAIN

PS> Resolve-DnsName www.bad.example.com
Resolve-DnsName : www.bad.example.com : DNS サーバーにエラーが発生しました。   # SERVFAIL
  • TTLとSectionの列が、digのANSWER・AUTHORITYに当たる。SectionがAuthorityのSOAだけなら、NODATA
  • NXDOMAIN・SERVFAILなどはエラーとして表示される。EDEは出ないため、SERVFAILは-DnssecCdで答えが返るかでDNSSECの問題かを見分ける
  • 英語版では DNS name does not exist・DNS server failure。エラーの種類は FullyQualifiedErrorId(DNS_ERROR_RCODE_NAME_ERROR・RCODE_SERVER_FAILURE)で見分けられる。Windows Server 2016 では SOA・MX の結果が1件ずつ縦に並ぶ形で表示される
  • 結果はオブジェクトなので加工できる。全NSのSOAのシリアルを並べる例(第7回の宿題):
PS> Resolve-DnsName example.jp -Type NS | Where-Object Type -eq NS | ForEach-Object {
      $ns = $_.NameHost
      Resolve-DnsName example.jp -Type SOA -Server $ns | Where-Object Type -eq SOA |
        Select-Object @{n='NS';e={$ns}}, SerialNumber }

resolvectl(Linuxのsystemd-resolved)

systemd-resolvedを使うLinux(Ubuntu等)では、resolvectlで調べます。

$ resolvectl query www.example.jp
www.example.jp: 203.0.113.10                   -- link: eth0

-- Information acquired via protocol DNS in 1.8ms.
-- Data is authenticated: no; Data was acquired via local or encrypted transport: no
-- Data from: cache

$ resolvectl status eth0       # リンクごとの DNSサーバー・DNS Domain・DoT・DNSSEC の設定
$ resolvectl statistics        # キャッシュのヒット数、DNSSEC の判定結果の件数
$ resolvectl flush-caches      # キャッシュを削除
アプリやdig(@無し)が127.0.0.53のsystemd-resolvedに聞き、キャッシュとリンクごとの振り分けを経て、eth0は社内DNSへ、VPNのtun0は~corp.example.jpだけ社内側のDNSへ行くことと、resolvectlの各サブコマンドの役割を示す図
  • /etc/resolv.confのnameserver 127.0.0.53はこのサービスを指す。digを@無しで実行すると、まずsystemd-resolvedが答える(第3回)
  • resolvectl queryは、アプリと同じ経路で解決し、キャッシュから答えたか(Data from)、DNSSECで検証済みか(authenticated)を表示する。型は-t MXのように指定する
  • resolvectl statusでは、リンク(NIC)ごとにどのDNSサーバーを使い、どのドメインをどのリンクへ振り分けるか(DNS Domain、~付きは振り分け専用)が分かる。VPN接続時の「社内名だけ引けない」の調査に使う
  • statisticsは、キャッシュのヒット・ミス、タイムアウトの件数を確かめるのに便利

応答の型ごとの見え方

ここまでのまとめとして、応答の型ごとの見え方を整理します。

応答が返ってきたか、statusは何か、NOERRORならANSWERの件数はいくつかという順に見て、正常・NODATA・NXDOMAIN・SERVFAIL・REFUSED・FORMERR・タイムアウトを見分けるフローチャート
型digの表示nslookupの表示主な原因と次の確認
NOERRORstatus: NOERROR、ANSWER: 1 以上名前と Address が表示される正常。rcodeとANSWERの件数を必ずセットで見る
NODATAstatus: NOERROR、ANSWER: 0、AUTHORITY に SOAエラーは出ず、SOAの情報が表示される名前はあるがその型が無い。AAAA・MX等の登録漏れ
NXDOMAINstatus: NXDOMAIN、AUTHORITY に SOANon-existent domain名前が無い。タイプミス、未登録、問い合わせ先の誤り
SERVFAILstatus: SERVFAIL、EDE が付くことがあるServer failed権威DNSに届かない、DNSSECの検証失敗。+cdとEDEで切り分け
REFUSEDstatus: REFUSED、EDE: 20 等Query refusedACLで拒否、権威DNSに担当外の名前を聞いた
FORMERRstatus: FORMERR、EDNSに関する WARNINGFormat error相手や経路上の機器がEDNSを解釈できない
応答なしcommunications error … timed outDNS request timed outF/Wで破棄、サーバー停止。REFUSEDとは別物

実際の出力で比べると、こうなります。

(NODATA:www.example.jp の MX)
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40148
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
example.jp.  900  IN  SOA  ns1.example.jp. hostmaster.example.jp. 2026092501 3600 900 1209600 900

(SERVFAIL:DNSSEC の検証失敗)
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 9270
; EDE: 9 (DNSKEY Missing): (no SEP matching the DS found for bad.example.com.)

(REFUSED:権威DNSに担当外の名前を再帰で聞いた)
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 47847
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
; EDE: 20 (Not Authoritative)
  • NODATAとNXDOMAINではAUTHORITYにSOAが付く。このSOAのTTLが「無い」という結果をキャッシュする時間(ネガティブキャッシュ、第3回)
  • SERVFAILのEDE 9は「親のDSに合う鍵が子ゾーンに無い」という意味。鍵の更新時のDSの差し替え忘れが典型的な原因(第9回)
  • REFUSEDにraが無くWARNINGが出ているのは、再帰に応じない権威DNSサーバーに聞いたため。問い合わせ先の役割を確かめる
  • FORMERRでは、digが;; WARNING: EDNS query returned status FORMERR - retry with '+noedns'と表示する

パケットキャプチャで見るDNS

コマンドで分からないときは、パケットを見ます。

# tcpdump -ni eth0 port 53
IP 192.0.2.10.51234 > 192.0.2.53.53: 4660+ [1au] A? www.example.jp. (43)
IP 192.0.2.53.53 > 192.0.2.10.51234: 4660 1/0/1 A 203.0.113.10 (59)
IP 192.0.2.10.40001 > 192.0.2.53.53: 1235+ [1au] AAAA? nosuch.example.jp. (46)
IP 192.0.2.53.53 > 192.0.2.10.40001: 1235 NXDomain 0/1/1 (97)

tcpdumpの4660+はIDとrd、[1au]はEDNSのOPT、1/0/1は回答・権威・追加の件数です。問い合わせに応答が対になっていなければ、途中で落ちています。

見たいものWireshark の表示フィルター
DNSだけdns
特定の名前dns.qry.name == “www.example.jp”
エラーの応答(NXDOMAIN は 3)dns.flags.rcode != 0
応答が遅いもの(秒)dns.time > 0.5
切り詰められた応答dns.flags.truncated == 1
暗号化DNS(DoT・DoQ)tcp.port == 853 or udp.port == 853
クライアントとキャッシュDNSの間、キャッシュDNSと権威DNSの間の2か所でtcpdumpを取り、応答が途切れる区間でキャッシュDNS側・権威DNSや経路側・アプリ側のどこを調べるかが決まることを示す図

コツは、2か所で取って、応答が途切れる区間を見つけることです。

  • ①(クライアント⇔キャッシュDNS)で問い合わせのみで応答が無い → キャッシュDNS側
  • ②(キャッシュDNS⇔権威DNS)で権威DNSから応答が無い → 権威DNS・経路(F/W)側
  • ①②とも応答が対になっている → アプリ側

なお、DoHは443番のHTTPSに紛れるため中身は見えません。キャプチャは社内のルールに従って取得しましょう。


考えてみよう

  1. 社内のキャッシュDNSにdigするとSERVFAIL、+cd(PowerShellでは-DnssecCd)を付けるとNOERRORで答えが返りました。何が起きていて、次に何を確かめますか。
  2. nslookupでは新しいIPアドレスが返るのに、ブラウザーでは古いサーバーにつながります。どのキャッシュを疑い、どう確かめますか。
  3. dig +traceでは新しいレコードが見えるのに、digでは古い値が返ります。この差は何を意味しますか。

ヒント:この記事の「セクション・TTL・所要時間」「delv」「Resolve-DnsNameとipconfig(キャッシュの範囲)」「応答の型ごとの見え方」が、それぞれの答えにつながります。


まとめ

  • digは HEADER(status)→ ANSWER → SERVER の順に読む
  • TTLが減っていればキャッシュ、aaがあれば権威の答え
  • +traceはキャッシュDNSを通らない。通常の結果と比べて差を見る
  • delvの1行目で「署名なし」と「検証失敗」を見分ける
  • nslookupはhosts・NRPTを通らない。アプリの再現はResolve-DnsName・resolvectl queryで
  • 型はrcodeとANSWERの件数をセットで。キャプチャは2か所で取る

次回は、ここで見たSERVFAILの原因にもなるDNSSECを含め、DNSを狙う攻撃と守り方を扱います。


連載「DNS入門」全12回

  1. DNSとは?名前解決の全体像と3つの登場人物
  2. ドメイン名の階層と委任
  3. 名前解決の流れ
  4. DNSメッセージとトランスポート
  5. リソースレコード 前編
  6. リソースレコード 後編
  7. 権威DNSサーバーの運用
  8. コマンドで調べる(この記事)
  9. DNSのセキュリティ
  10. クラウド・社内環境のDNS
  11. DNSトラブルシュート
  12. DNS設計演習

コメント

タイトルとURLをコピーしました