
ZDNS は、大規模な DNS 測定を実行するための高速 DNS リゾルバ兼コマンドラインユーティリティです。ZDNS は Go で書かれており、独自の再帰解決コードと、多様な名前のルックアップに最適化されたキャッシュを備えています。生の DNS パケットの構築と解析には、https://github.com/zmap/dns を使用しています。ZDNS のアーキテクチャとパフォーマンスの詳細については、ACM の Internet Measurement Conference '22 で発表された次の論文を参照してください。
[!TIP] ZDNS Wiki には、ZDNS に関する追加情報と使用例・サンプルが含まれています。
ZDNS は、リポジトリをチェックアウトして make install を実行することでインストールできます。
git clone https://github.com/zmap/zdns.git
cd zdns
make install
ZDNS は、再帰リゾルバのライブラリと CLI ラッパーで構成されています。
ライブラリは、すべてのルックアップの設定オプションを含む ResolverConfig 構造体で構成されています。ResolverConfig を使用して、すべてのルックアップを実行する 1 つ以上の Resolver 構造体を作成します。Resolver は一度に 1 つのルックアップのみを実行する必要があり(スレッドセーフではありません)、並列処理には複数の Resolver 構造体を使用する必要があります。ライブラリの使用方法については、examples を参照してください。Modules はルックアップの動作を定義するために使用されます。
ZDNS はいくつかのタイプのモジュールを提供します。
Raw DNS モジュール は、dig と同様にサーバーからの生の DNS 応答を JSON 形式で提供します。(ほとんど)すべての DNS レコードタイプに対応するモジュールがあります。
Lookup モジュール は、複数のクエリが必要な場合(NSLOOKUP で NS を受信した場合の IP アドレスの追加 A ルックアップの完了など)に、より便利な応答を提供します。
Misc モジュール は、サーバーへのクエリの他の追加手段を提供します(例:bind.version)。
モジュールの詳細は以下の通りです。
A、AAAA、AFSDB、ANY、ATMA、AVC、AXFR、BINDVERSION、CAA、CDNSKEY、CDS、CERT、CNAME、CSYNC、DHCID、DMARC、DNSKEY、DS、EID、EUI48、EUI64、GID、GPOS、HINFO、HIP、HTTPS、ISDN、KEY、KX、L32、L64、LOC、LP、MB、MD、MF、MG、MR、MX、NAPTR、NID、NINFO、NS、NSAPPTR、NSEC、NSEC3、NSEC3PARAM、NSLOOKUP、NULL、NXT、OPENPGPKEY、PTR、PX、RP、RRSIG、RT、SVCBS、MIMEA、SOA、SPF、SRV、SSHFP、TALINK、TKEY、TLSA、TXT、UID、UINFO、UNSPEC、URI モジュールは、dig と同様に生の DNS 応答を JSON 形式で提供します。
例えば、次のコマンド:
echo "censys.io" | zdns A
は以下を返します:
{
"name": "censys.io",
"results": {
"A": {
"data": {
"additionals": [
{
"flags": "",
"type": "EDNS0",
"udpsize": 512,
"version": 0
}
],
"answers": [
{
"answer": "104.18.10.85",
"class": "IN",
"name": "censys.io",
"ttl": 300,
"type": "A"
},
{
"answer": "104.18.11.85",
"class": "IN",
"name": "censys.io",
"ttl": 300,
"type": "A"
}
],
"protocol": "udp",
"resolver": "[2603:6013:9d00:3302::1]:53"
},
"duration": 0.285295416,
"status": "NOERROR",
"timestamp": "2024-08-23T13:12:43-04:00"
}
}
}
生の DNS 応答は、必要なデータを提供しないことがよくあります。例えば、MX 応答には、追加セクションに関連する A レコードが含まれていない場合があり、追加のルックアップが必要になります。このギャップを埋め、より使いやすいインターフェースを提供するために、alookup、mxlookup、nslookup という lookup モジュールも提供しています。
alookup は nslookup と同様に動作し、CNAME レコードを辿ります。
mxlookup は、交換レコードに対応する IP アドレスの A ルックアップを追加で実行します。
nslookup は、NS レコードに対応する IP アドレスの A/AAAA ルックアップを追加で実行します。
例えば、
echo "censys.io" | zdns mxlookup --ipv4-lookup
は以下を返します:
{
"name": "censys.io",
"results": {
"MXLOOKUP": {
"data": {
"exchanges": [
{
"class": "IN",
"ipv4_addresses": [
"209.85.202.27"
],
"name": "alt1.aspmx.l.google.com",
"preference": 5,
"ttl": 300,
"type": "MX"
},
{
"class": "IN",
"ipv4_addresses": [
"142.250.31.26"
],
"name": "aspmx.l.google.com",
"preference": 1,
"ttl": 300,
"type": "MX"
}
]
},
"duration": 0.154786958,
"status": "NOERROR",
"timestamp": "2024-08-23T13:10:11-04:00"
}
}
}
ZDNS は特別な「デバッグ」DNS クエリもサポートしています。モジュールには BINDVERSION が含まれます。
ZDNS は、目的の動作に応じて様々な形式での入力をサポートしています。
最も基本的な入力は、改行で区切られた名前のリストです。例:
標準入力から:
echo "google.com\nyahoo.com" | zdns A
cat list_of_domains.txt | zdns A
ファイルから:
zdns A --input-file=list_of_domains.txt
多くのドメインを解決する必要がない場合は、使いやすさのために dig と同様にドメインを CLI 引数として指定することができます。
例:
zdns A google.com --name-servers=1.1.1.1
dig -t A google.com @1.1.1.1 と同等
通常、ZDNS は --name-servers から各ドメインルックアップにランダムなネームサーバーを選択します。代わりにドメインごとに異なるネームサーバーを指定したい場合は、ドメイン名とネームサーバーの IP をカンマ区切りで改行で区切って指定できます。これは --name-servers で指定されたネームサーバーを上書きします。
例:
echo "google.com,1.1.1.1\nfacebook.com,8.8.8.8" | zdns A
出力で各ドメインに対して指定されたリゾルバを確認できます(簡潔にするため追加/回答は省略):
$ echo "google.com,1.1.1.1\nfacebook.com,8.8.8.8" | zdns A
{"name":"google.com","results":{"A":{"data":{"additionals":...,"answers":[...],"protocol":"udp","resolver":"1.1.1.1:53"},"duration":0.030490042,"status":"NOERROR","timestamp":"2024-09-13T09:51:34-04:00"}}}
{"name":"facebook.com","results":{"A":{"data":{"additionals":[...],"answers":[...],"protocol":"udp","resolver":"8.8.8.8:53"},"duration":0.061365459,"status":"NOERROR","timestamp":"2024-09-13T09:51:34-04:00"}}}
ICANN CZDS などからのゾーンファイルは、--zone-file フラグを使用して ZDNS の入力ソースとして使用できます。これにより、標準入力(デフォルト)または --input-file フラグを使用したファイルからのゾーンファイルの解析が可能になります。
デフォルトでは、ZDNS は各ゾーンファイルレコードから名前のみを抽出します。CNAME や NS レコードなどの回答セクションで参照される名前も解決したい場合は、--zone-file-include-targets CLI フラグを使用できます。
例えば、--zone-file-include-targets と次の DNS ゾーンファイルエントリを使用した場合:
example.com. 3600 IN NS ns1.example.com
example.com と ns1.example.com の両方が解決されます。
ZDNS は、入力行を特定のモジュールにマッピングする、入力行ごとの「トリガー」の受け渡しもサポートしています。これにより、特定のドメインを特定のモジュールでルックアップするように指定できます。
入力形式は次のとおりです:
domain_name,name_server,trigger,trigger_2,etc ここで、nameServer はデフォルトのネームサーバーを使用する場合は空にでき、1 つ以上のトリガーを指定できます。
input.csv ファイルの例:
example.com,,a-trigger
google.com,,a-trigger,cname-trigger
example.com,1.1.1.1,aaaa-trigger
yahoo.com
apnews.com,1.1.1.1
対応する multiple.ini:
; グローバルオプションをここで指定
[Application Options]
iterative=true
prefer-ipv6-iteration="true"
; モジュールとそれぞれのモジュール固有オプションをここにリストします。各モジュールは一度だけリストできます。
[A]
trigger = "a-trigger"
[AAAA]
trigger = "aaaa-trigger"
[CNAME]
trigger = "cname-trigger"
これにより、次がルックアップされます:
example.com を A モジュール、デフォルトネームサーバーを使用google.com を A + CNAME モジュール、デフォルトネームサーバーを使用example.com を AAAA モジュール、Cloudflare の 1.1.1.1 リゾルバを使用yahoo.com を指定されたすべてのモジュール、デフォルトネームサーバーを使用apnews.com を指定されたすべてのモジュール、Cloudflare の 1.1.1.1 リゾルバを使用コマンドの実行:
zdns MULTIPLE --multi-config-file="./multiple.ini" --input-file="input.csv"
ZDNS は、再帰リゾルバ(例:組織の DNS サーバー)に対して動作するか(デフォルトの動作)、内部で独自の再帰を実行できます。少数(数百万程度)のルックアップを実行し、10,000 未満の goroutine を使用する場合は、通常、Cloudflare や Google などの一般的な再帰リゾルバを使用するのが最速です。Cloudflare はほとんどの場合 Google よりも高速です。これは、特に人気のある名前をルックアップする場合に当てはまります。なぜなら、それらはキャッシュされており、1 ラウンドトリップで応答できるからです。数万の同時スレッドを使用する場合は、再帰リゾルバへの DoS 攻撃やレート制限を避けるために、内部で反復を実行することを検討してください。
ローカル再帰を実行するには、--iterative フラグを指定して zdns を実行します。このフラグを使用すると、ZDNS は公開ルートサーバー(例:198.41.0.4)間でラウンドロビンを行います。反復モードでは、--cache-size を指定してローカルキャッシュのサイズを制御し、--iteration-timeout を設定して個々の反復のタイムアウトを制御できます。--timeout フラグは、特定の入力に対する解決全体のタイムアウト(つまり、すべての反復ステップの合計)を制御します。
ZDNS のパフォーマンスは、軽量な Go ルーチンを使用した大規模な並列化に由来します。このアーキテクチャにはいくつかの注意点があります: