2026年6月12日

2026年6月12日

kdig コマンドでトレースする方法|+trace の無い kdig で、ルートから権威サーバーまで委任を1段ずつたどる

kdig には dig の +trace に当たる自動トレースの機能がありません(2026年10月現在の Knot DNS 3 系)。その代わり、+norec(再帰なし)で問い合わせ先を1段ずつ切り替えていけば、ルートサーバーから TLD、ドメインの権威サーバーまでの委任を自分の手でたどれます。この記事では、kdig で手作業のトレースを行う手順と各段の応答の読み方、作業を自動化する簡単なスクリプト、kdig ならではの通信方式や拠点の確認を組み合わせる方法を説明します。

kdig は Knot DNS に付属するコマンドで、Debian・Ubuntu では knot-dnsutils、RHEL 系では knot-utils(EPEL が必要な場合あり)、macOS では Homebrew の knot で入れられます。将来の版で機能が加わる可能性もあるため、手元の版の対応状況は man kdig で確かめてください。

トレースで何を確かめるのか

ふだん名前を引くと、答えを返すのはキャッシュサーバーです。キャッシュサーバーは裏でルート、TLD(.com や .jp など)、権威サーバーへと順に問い合わせていますが、その途中経過は見えません。トレースはこの道のりを再現し、次のような問題を切り分けるために行います。

  • レジストラで設定したネームサーバーが、親ゾーン(TLD)に反映されているか
  • 委任先のネームサーバーが、そのドメインの答えを本当に持っているか
  • キャッシュに古い答えが残っているだけなのか、権威サーバーの設定そのものが違うのか

手順1:ルートサーバーに聞く

調べたい名前を、ルートサーバーに再帰なしでそのまま問い合わせます。

kdig @a.root-servers.net www.example.com A +norec
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 4321
;; Flags: qr; QUERY: 1; ANSWER: 0; AUTHORITY: 13; ADDITIONAL: 27

;; AUTHORITY SECTION:
com.                	172800	IN	NS	a.gtld-servers.net.
com.                	172800	IN	NS	b.gtld-servers.net.
(省略)

;; ADDITIONAL SECTION:
a.gtld-servers.net. 	172800	IN	A	192.5.6.30
a.gtld-servers.net. 	172800	IN	AAAA	2001:503:a83e::2:30
(省略)

読むポイントは3つです(件数や値は例です)。

  • status が NOERROR で、ANSWER が0件、AUTHORITY に NS が並んでいる。これは「答えは持っていないので、.com はこのサーバーたちに聞いてほしい」という委任の案内(referral)です。
  • Flags に aa が無い。ルートサーバーは example.com の権威ではないので正常です。
  • ADDITIONAL に、次に問い合わせるサーバーのアドレス(グルー)が入っている。

手順2:TLD のサーバーに聞く

手順1の AUTHORITY に出たサーバーのどれか1台に、同じ名前を問い合わせます。

kdig @a.gtld-servers.net www.example.com A +norec

今度は AUTHORITY に、そのドメインのネームサーバー(例:example.com. 172800 IN NS ns1.example.net.)が並びます。これが親ゾーンに登録されている委任の情報で、レジストラの管理画面で設定した値と一致しているべきものです。

トレースで最も大事な確認点はこの段です。DNS 事業者を乗り換えたのに旧事業者のネームサーバーが出ているなら、レジストラ側の変更が済んでいないか、反映の途中です。.jp ドメインなら a.dns.jp など担当サーバーは TLD ごとに違いますが、手順1の結果に出た名前を使えば迷いません。

手順3:権威サーバーに聞く

手順2で出たネームサーバーに問い合わせます。

kdig @ns1.example.net www.example.com A +norec

Flags に aa が立ち、ANSWER にレコードが出れば、権威サーバー自身の答えです。ここで表示される TTL はゾーンに設定された値そのものです。

委任先が複数あるときは、すべてに同じ問い合わせをして比べます。1台だけ値が違う、1台だけ REFUSED を返す、といった状態は、同期の遅れや設定漏れの手がかりです。REFUSED や aa の無い答えを返すサーバーは、そのドメインを預かっていない可能性があります(委任されているのに答えを持たない状態で、lame delegation と呼ばれます)。

各段で DNSSEC の委任も見る

+dnssec を付けると、委任の案内に DS レコード(親ゾーンが子ゾーンの鍵を指す記録)とその署名が含まれるかを確かめられます。

kdig @a.gtld-servers.net www.example.com A +norec +dnssec

署名されたドメインなら AUTHORITY に NS と並んで DS と RRSIG が、署名されていないドメインなら「DS が無いこと」を示す NSEC や NSEC3 の行が出ます。DNSSEC を使っていないのに DS が残っている、使っているのに DS が無い、といった食い違いはここで見つかります。kdig 自身は DNSSEC の検証を行わないので、署名が正しいかまで確かめたいときは delv や DNSViz を使います。

手順を自動化するスクリプト

毎回3段を手で打つのは手間なので、委任の案内を受け取ったら次のサーバーへ進む、という処理を繰り返す簡単なスクリプトにまとめられます。

#!/bin/bash
# kdig で委任を1段ずつたどる簡易版(調査用)
# 使い方: ./ktrace.sh www.example.com A
name=${1:?調べる名前を指定してください}
type=${2:-A}
server=a.root-servers.net

for step in 1 2 3 4 5 6 7 8; do
  # 問い合わせ先の名前を IPv4 アドレスに変換する(手元のキャッシュサーバーを使う)
  addr=$(kdig +short "$server" A | head -n 1)
  if [ -z "$addr" ]; then
    echo "$server のアドレスを引けませんでした"
    exit 1
  fi
  echo "== 段$step: $server ($addr)"

  out=$(kdig @"$addr" "$name" "$type" +norec 2>&1)
  status=$(printf '%s\n' "$out" | sed -n 's/.*status: \([A-Z]*\).*/\1/p')
  flags=$(printf '%s\n' "$out" | sed -n 's/^;; Flags: \([^;]*\);.*/\1/p')
  if [ -z "$status" ]; then
    printf '%s\n' "$out" | tail -n 3   # 応答が無いときはエラーの行を表示する
    exit 1
  fi
  echo "status=$status flags=$flags"

  answer=$(printf '%s\n' "$out" | awk '/^;; ANSWER SECTION:/{f=1; next} /^$/{f=0} f')
  if [ -n "$answer" ]; then
    printf '%s\n' "$answer"
    exit 0
  fi

  auth=$(printf '%s\n' "$out" | awk '/^;; AUTHORITY SECTION:/{f=1; next} /^$/{f=0} f')
  printf '%s\n' "$auth"
  next=$(printf '%s\n' "$auth" | awk '$4 == "NS" {print $5; exit}')
  if [ -z "$next" ]; then
    echo "委任も答えもありません(status を確認してください)"
    exit 0
  fi
  server=$next
done
echo "段数が上限に達したため中断しました"

このスクリプトは、各段で AUTHORITY に出た最初の NS だけを次の問い合わせ先にします。すべての NS を比べたいときは、表示された一覧を見て手順3を個別に実行してください。また、次のサーバーのアドレスはグルーではなく手元のキャッシュサーバーで引いています。グルーそのものを確かめたいときは、手順1・2のように ADDITIONAL を目で見ます。ANSWER に CNAME が返った場合はそこで止まるので、別名の先の名前でもう一度実行します。

kdig ならではの確認を組み合わせる

手作業でたどる利点は、各段の問い合わせ方を自由に変えられることです。dig の +trace では途中の問い合わせ方を細かく選べませんが、kdig なら段ごとに次のような条件を足せます。

# IPv6 で届くか(-6)、TCP で答えるか(+tcp)
kdig -6 @ns1.example.net www.example.com A +norec
kdig @ns1.example.net www.example.com A +norec +tcp

# どの拠点が答えたか(NSID に対応したサーバーのみ)
kdig @ns1.example.net www.example.com A +norec +nsid

エニーキャストで運用されている権威サーバーでは、同じアドレスでも場所によって別の拠点が答えます。+nsid で返る識別子を控えておくと、「特定の拠点だけ古い値を返している」といった事象を DNS 事業者に伝えるときの材料になります。NSID を返すかどうかはサーバーしだいです。

つまずきやすい点

  • ネームサーバーの名前に答えが無い:ネームサーバーが別のドメインにあり、グルーが付かない場合、そのサーバーの名前を別に解決する必要があります。スクリプトが kdig +short でアドレスを引いているのはこのためです。
  • グルーと実際のアドレスが違う:ネームサーバーの IP を変えたのにレジストラでグルー(ホスト情報)を更新していないと、親ゾーンの ADDITIONAL に古いアドレスが残ります。手順2の ADDITIONAL と、権威サーバーに聞いたネームサーバー名の A レコードを比べます。
  • 時間切れになる:;; WARNING や ;; ERROR の行が出て応答が無い場合は、サーバーの停止、経路の問題、または手元のネットワークが外部の53番ポートへの通信を制限している可能性があります。別の回線や +tcp で試して切り分けます。
  • キャッシュサーバーに +norec で聞いてしまう:@ を付け忘れると、手元のキャッシュサーバーに再帰なしで聞くことになり、キャッシュにある分だけの答えが返り、トレースの結果としては使えません。各段で @ の問い合わせ先を確かめます。

ルートや TLD のサーバーは公共の設備です。調査に必要な範囲で使い、短時間に大量の問い合わせを繰り返す使い方は避けてください。

まとめ

  • kdig には自動トレースが無いため、+norec で問い合わせ先をルート → TLD → 権威サーバーと切り替えて委任をたどります。
  • 委任の案内は「ANSWER が0件、AUTHORITY に NS、aa 無し」、権威サーバーの答えは「aa 有り、ANSWER にレコード」と読みます。
  • 最も大事なのは TLD の段で、ここに出るネームサーバーがレジストラの登録と一致しているかを確かめます。
  • +dnssec で各段の DS の有無を、-6・+tcp・+nsid で通信方式や拠点ごとの違いを確かめられるのが kdig で手作業する利点です。
  • 繰り返し使うならスクリプトにまとめ、グルーや複数の NS は手順を分けて確認します。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲