概要
2024 年 6 月 10 日に「dig の全てのコマンドラインオプションを一覧にしたシートを作成しました」という記事を公開してから約 1 年半が経ちました。
記事では一般の方が利用しやすい dig のバージョンとして 9.18 という当時の安定版ブランチで使用できるコマンドラインオプションを全て機能別に整理した表を作成し、紹介していました。
その後、あたらしい安定版ブランチとして 9.20 がリリースされ、開発版ブランチは 9.21 となっています。
今回は、当時参照した 9.18.18 から執筆時点の開発版ブランチの最新バージョンである 9.21.15 までに追加されているオプションをチェックすることで、dig と DNS プロトコルの進化を学んでいきたいと思います。
あたらしいコマンドラインオプション
9.18.18 と 9.21.15 を比べてみると、8 つのコマンドラインオプションが追加されていました。以下では追加された順番に見ていくことにします。括弧()内は追加されたバージョンです。開発版にのみ実装され、次の安定版に採用される場合と、開発版だけでなく現行の安定版にも追加される場合があるのが分かります。最後の +coflag に関しては、開発版と現行の安定版だけでなく、並行してサポートが続いている一つ前の安定版にも追加されていました。
+idn (9.19.6, 9.20.0)
国際化ドメイン(IDN - Internationalized Domain Names)に対応します。
9.19.5 以前では分かれていた、入力に関する +idnin と 出力に関する +idnout が一つになりました (+idnin / +idnout も man ページからは消えましたが引き続き利用可能なようです)。端末に出力する (パイプに渡す等ではない) 場合は +idn がデフォルトで有効なので、例えば IDN を ASCII でエンコードされた Punycode 表記のまま出力したいといったときに +noidn として利用することになります。
なお、IDN 対応はビルド時オプション扱いのため、OS のパッケージでインストールした dig の場合などでは使えないことがあります。
+proxy[=src_addr[#src_port]-dst_addr[#dst_port] / +proxy-plain[=src_addr[#src_port]-dst_addr[#dst_port] (9.19.19, 9.20.0)
PROXYv2 プロトコルに対応します。
DNS サーバー(再帰リゾルバーや権威ネームサーバー)の前にロードバランサーが入り NAT やプロキシー動作を行う場合、DNS サーバー側に見える送信元 IP アドレスはロードバランサーの IP アドレスとなり、本来の送信元の IP アドレスは見えなくなってしまいます。HAProxy の作者によって作られた PROXYv2 プロトコルでは送信元と宛先の IP アドレスやポート番号の情報を付加することでこの課題を解決します。
dig の +proxy / +proxy-plain オプションは、クエリを送る際、PROXYv2 により送信元と宛先の IP アドレスとポート番号の情報を付加して接続します。TLS による暗号通信においてこれらの情報は +proxy では TLS ハンドシェイク後に、+proxy-plain では TLS ハンドシェイク前にやりとりするという違いがあります。named が PROXYv2 をサポートしたため、それをテストするため dig もサポートしたようです。
-F (9.21.3)
FIPS モードをランタイムで有効化します。
従来 OpenSSL の FIPS モードを強制する --enable-fips-mode はビルド時のオプションでした。このあたらしいコマンドラインオプションは、実行時に FIPS モードを強制できるようにするものです。
+svcparamkeycompat (9.21.6)
SvcParamKey の互換表示モードを指定します。
SVCB レコードと HTTPS レコードは RFC9460 で標準化されていますが、これらのレコードで用いられるサービスパラメーターの種別を表す SvcParamKey として、alpn、port など 7 つが定義されています。dig ではその後に定義された SvcParamKey に関しても順次サポートしています。
例えば RFC9461 Service Binding Mapping for DNS Servers では、DNS over HTTPS (DoH) で用いる URI テンプレートを指定するサービスパラメーター用の SvcParamKey として dohpath を定義しています。
9.21.6 以降ではこれに対応しているため「dohpath」と表示されます。
$ dig +noall +answer SVCB _dns.resolver.arpa @8.8.8.8
_dns.resolver.arpa. 86400 IN SVCB 1 dns.google. alpn="dot"
_dns.resolver.arpa. 86400 IN SVCB 2 dns.google. alpn="h2,h3" dohpath="/dns-query{?dns}"
$
一方で、9.21.5 以前のバージョンの dig では未知の SvcParamKey として、「key7」と表示していました。つまり、dig のバージョンによって表示が異なることになります。
+svcparamkeycompat オプションを指定すると、9.21.6 以降であってもそれ以前と同様に keyNNNNN フォーマットで表示します。
$ dig +noall +answer +svcparamkeycompat SVCB _dns.resolver.arpa @8.8.8.8
_dns.resolver.arpa. 86400 IN SVCB 1 dns.google. alpn="dot"
_dns.resolver.arpa. 86400 IN SVCB 2 dns.google. alpn="h2,h3" key7="/dns-query{?dns}"
$
dohpath のかわりに key7 と表示されているのがわかります。
+showbadvers (9.20.18, 9.21.7)
BADVERS 応答を表示します。
+noednsnegotiation が指定されていないデフォルト動作では、dig は EDNS バージョンのネゴシエーションを行う、つまりサーバーから BADVERS レスポンスを受け取ると、同レスポンスで示された EDNS バージョンで再送を行います。その際、デフォルトでは BADVERS 応答の詳細は表示されません。 +showbadvers を指定すると、この暫定的な BADVERS 応答に関しても詳細の表示を行います。
+zoneversion (9.21.7)
RFC9660 The DNS Zone Version (ZONEVERSION) Option で追加された EDNS オプションを付加してクエリーします。
クライアントがこのオプションをつけてクエリを行うと、サーバーが対応する場合、同オプションでゾーンのデータのバージョンをつけて応答します。バージョンとしては SOA のシリアル番号を用いる方法が定義されています。
SOA レコードを問い合わせることによってもシリアル番号を知ることはできますが、複数のサーバーに分散されているときなどは知りたい対象のクエリーと SOA レコードのクエリーに対して同じサーバーが返すとは限らないため、応答と同じメッセージの中にシリアル番号の情報を付加することが求められました。こちらは権威ネームサーバーの運用上の用途を想定したオプションと言えそうです。
$ dig +nord +zoneversion example.com @XXX.XX.XXX.XX
; <<>> DiG 9.21.15 <<>> +nord +zoneversion @XXX.XX.XXX.XX
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: XXXX
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; ZONEVERSION: ZONE: example.com, SOA-SERIAL: 2025121701
;; QUESTION SECTION:
;example.com. IN A
;; ANSWER SECTION:
example.com. 300 IN A XXX.XX.XXX.XX
;; Query time: 123 msec
;; SERVER: XXX.XX.XXX.XX#53(XXX.XX.XXX.XX) (UDP)
;; WHEN: Tue Dec 17 00:00:00 UTC 2025
;; MSG SIZE rcvd: XX
$
+coflag (9.18.38, 9.20.11, 9.21.10)
RFC9824 で定義された EDNS 拡張フラグである CO (Compact Answers OK) フラグをセットしてクエリを行います。
同 RFC は DNSSEC の Compact Denial of Existence を標準化しています。一般的に NXDOMAIN 応答時の不存在証明には複数の NSEC(または NSEC3) レコードを返すことが多くなります。
Compact Denial of Existence を用いる権威ネームサーバーは、クエリされた名前が存在しない場合に NXDOMAIN で応答するかわりにアンサーがひとつもない NOERROR、つまり NODATA で応答します。NODATA であれば一つの NSEC(または NSEC3) レコードで不存在証明を行うことができます。これにより、繰り返しクエリを行うことでゾーンデータ全体を導き出す行為 (ゾーンウォーキング) を防ぎつつ、動的応答生成の暗号計算処理を抑え、メッセージサイズも小さくすることができます。
CO フラグはこの RFC の 5.1 節でオプションとして定義されており、再帰リゾルバーがクエリーにこのフラグをセットすることで「Compact Denial of Existence 方式を理解している」ことを伝え、権威ネームサーバー側がレスポンスコードを NOERROR ではなく NXDOMAIN にすることができるようにしています。
Compact Denial of Existence は従来 Black Lies (黒い嘘)と呼ばれていたものをベースに細かい部分を含めて標準化したものですが、CO フラグは「私は分かっているから堂々と嘘をついていいですよ」と伝えていると言えそうです。
おわりに
ここまで、dig に追加された 8 つのさまざまなコマンドラインオプションを見てきました。
dig の man ページには、「バグ」として「おそらくクエリオプションが多すぎる」と書かれています。
BUGS
There are probably too many query options.
とはいえ、DNS のプロトコルが拡張され、named の機能が追加されていくに従って、dig のオプションも自然に増えてきたものと言えそうです。私たちはこの憎めない「バグ」と仲良くつきあいながら学んでいくしかなさそうです。
今年の DNS Summer Day 2025 では「変な dig」と題して dig の +trace オプションの不思議な挙動についてお話ししました(資料はこちら)。来年も楽しいお話ができればと思っています。ぜひ会場でお会いしましょう。