dnsperf を使ってみた

balaeniceps-rex DNS

DNS 用のストレスツールである dnsperf をいろいろ試してみました。

※ここでは実際に設定、動作したものを掲載していますが、内容について保証するものではありません。流用される場合は各自の責任でお願いします。

DNS 用のストレスツールの比較を行いました。「DNS 用ストレスツールの比較」をご参照ください。

dnsperf を実施する OS のバージョンは以下のとおりです。
※ dnsperf のバージョンについては dnsperf のヘルプ(dnsperf -h)で確認できます。

[root@rocky8-client ~]# uname -a
Linux rocky8-client.mydomain 4.18.0-553.56.1.el8_10.x86_64 #1 SMP Tue Jun 10 17:00:45 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
参考:dnsperf のインストール

EPEL リポジトリインストール

[root@rocky8-client ~]# dnf install epel-release -y

- 省略 -

インストール済み:
  epel-release-8-18.el8.noarch

完了しました!
[root@rocky8-client ~]#

dnsperf のインストール

[root@rocky8-client ~]# dnf install dnsperf -y

- 省略 -

インストール済み:
  ck-0.6.0-9.el8.x86_64                             cups-libs-1:2.2.6-62.el8_10.x86_64         dejavu-sans-fonts-2.35-7.el8.noarch
  dnsperf-2.12.0-1.el8.x86_64                       fribidi-1.0.4-9.el8.x86_64                 gd-2.2.5-7.el8.x86_64
  glx-utils-8.4.0-5.20181118git1830dcb.el8.x86_64   gnuplot-5.2.4-3.el8.x86_64                 gnuplot-common-5.2.4-3.el8.x86_64
  graphite2-1.3.10-10.el8.x86_64                    harfbuzz-1.7.5-4.el8.x86_64                jbigkit-libs-2.1-14.el8.x86_64
  ldns-1.7.0-22.el8.x86_64                          libICE-1.0.9-15.el8.x86_64                 libSM-1.2.3-1.el8.x86_64
  libX11-xcb-1.6.8-9.el8_10.x86_64                  libXfixes-5.0.3-7.el8.x86_64               libXft-2.3.3-1.el8.x86_64
  libXpm-3.5.12-11.el8.x86_64                       libXxf86vm-1.1.4-9.el8.x86_64              libdatrie-0.2.9-7.el8.x86_64
  libdrm-2.4.115-2.el8.x86_64                       libevdev-1.10.0-1.el8.x86_64               libglvnd-1:1.3.4-2.el8.x86_64
  libglvnd-egl-1:1.3.4-2.el8.x86_64                 libglvnd-glx-1:1.3.4-2.el8.x86_64          libinput-1.16.3-3.el8_6.x86_64
  libjpeg-turbo-1.5.3-14.el8_10.x86_64              libpciaccess-0.14-1.el8.x86_64             libthai-0.1.27-2.el8.x86_64
  libtiff-4.0.9-34.el8_10.x86_64                    libwacom-1.6-3.el8.x86_64                  libwacom-data-1.6-3.el8.noarch
  libwayland-client-1.21.0-1.el8.x86_64             libwayland-server-1.21.0-1.el8.x86_64      libwebp-1.0.0-11.el8_10.x86_64
  libxkbcommon-x11-0.9.1-1.el8.x86_64               libxshmfence-1.3-2.el8.x86_64              mesa-libEGL-23.1.4-4.el8_10.x86_64
  mesa-libGL-23.1.4-4.el8_10.x86_64                 mesa-libgbm-23.1.4-4.el8_10.x86_64         mesa-libglapi-23.1.4-4.el8_10.x86_64
  mtdev-1.1.5-12.el8.x86_64                         pango-1.42.4-8.el8.x86_64                  pcre2-utf16-10.32-3.el8_6.x86_64
  qt5-qtbase-5.15.3-8.el8_10.x86_64                 qt5-qtbase-common-5.15.3-8.el8_10.noarch   qt5-qtbase-gui-5.15.3-8.el8_10.x86_64
  qt5-qtsvg-5.15.3-2.el8.x86_64                     xcb-util-0.4.0-10.el8.x86_64               xcb-util-image-0.4.0-9.el8.x86_64
  xcb-util-keysyms-0.4.0-7.el8.x86_64               xcb-util-renderutil-0.3.9-10.el8.x86_64    xcb-util-wm-0.4.1-12.el8.x86_64

完了しました!
[root@rocky8-client ~]#
参考:dnsperf のヘルプ
[root@rocky8-client ~]# dnsperf -h
DNS Performance Testing Tool
Version 2.12.0

Usage: dnsperf [-f family] [-m mode] [-s server_addr] [-p port]
               [-a local_addr] [-x local_port] [-d datafile] [-c clients]
               [-T threads] [-n maxruns] [-l timelimit] [-b buffer_size]
               [-t timeout] [-e] [-E code:value] [-D]
               [-y [alg:]name:secret] [-q num_queries] [-Q max_qps]
               [-S stats_interval] [-u] [-B] [-v] [-W] [-h] [-H] [-O]
  -f address family of DNS transport, inet or inet6 (default: any)
  -m set transport mode: udp, tcp, dot or doh (default: udp)
  -s the server to query (default: 127.0.0.1)
  -p the port on which to query the server (default: udp/tcp 53, DoT 853 or DoH 443)
  -a the local address from which to send queries
  -x the local port from which to send queries (default: 0)
  -d the input data file (default: stdin)
  -c the number of clients to act as
  -T the number of threads to run
  -n run through input at most N times
  -l run for at most this many seconds
  -b socket send/receive buffer size in kilobytes
  -t the timeout for query completion in seconds (default: 5)
  -e enable EDNS 0
  -E send EDNS option
  -D set the DNSSEC OK bit (implies EDNS)
  -y the TSIG algorithm, name and secret (base64)
  -q the maximum number of queries outstanding (default: 100)
  -Q limit the number of queries per second
  -S print qps statistics every N seconds
  -u send dynamic updates instead of queries
  -B read input file as TCP-stream binary format
  -v verbose: report each query and additional information to stdout
  -W log warnings and errors to stdout instead of stderr
  -h print this help
  -H print long options help
  -O set long options: <name>=<value>
[root@rocky8-client ~]#

(個人メモ)
-a : クエリ送信元を指定(アドレスもしくはホスト名)※ここで指定するアドレスはインターフェイスに設定されている必要がある。
-s : クエリ送信先を指定(アドレスもしくはホスト名)
-d : クエリ情報(ドメイン名とタイプのリスト)が登録されているファイルを指定。この内容に従いクエリを発行する
-S : 情報(time stamp と qps)を表示する間隔を指定(秒)
-c : クライアント同時接続数を指定。ここで指定した数だけ異なる送信元ポートを使用する。デフォルトは1。1クライアント当たり送・受で2スレッド使用。
-q : プールのクエリ数を指定。ここで指定した数だけクエリ処理待ちとなるようにクエリ要求をプールする。※qpsではない
-Q : 1秒あたりのクエリ発行数を指定
-m : プロトコルを指定(tcp, udp(default))
-n : -d で指定したファイルを読み込む回数
-b : UDPバッファ(デフォルトは32Kbyte)。実行中の画面に"Timeout"が出力される場合は、この値を大きくすると改善されるかも。
-l : 何秒間送信し続けるかを指定。指定時間前に、-d 指定のRRが尽きた場合、再度リストの先頭から送信を継続する。
参考:その他

dnsperf で DDNS(Dynamic DNS)を試してみました。手順については「dnsperf で DDNS を実施してみた」をご参照ください。

概要

  • クエリデータをファイルに登録し、dnsperf コマンドに読み込ませることでクエリを送信することができます。
  • クエリリクエストの RD フラグは 1(再帰問い合わせ)のため、基本的にはスタブリゾルバからキャッシュ DNS へ負荷をかけるためのツールと思われます。ヘルプでは、RD フラグを 0(非再起問い合わせ)として送信するためのオプションは見当たりませんでした。ただし、権威 DNS が再帰問い合わせを拒否しなければ(再帰問い合わせを拒否する権威 DNS が存在するかは承知していません)、権威 DNS へ負荷をかけることも可能です。(*1)
  • トランスポートのデフォルトは UDP です。-m オプションを指定することで TCP に変更することが可能です。
  • UDP 通信時のクエリレスポンスで truncated(切り捨て)が発生しても TCP フォールバックは行われません。
  • 送信件数は -d で指定するファイルに登録されているクエリデータの件数と -n で指定するファイルの読み込み回数で決まります。ただし、-l で試験期間(秒)が指定されている場合、試験期間経過後に dnsperf の処理は打ち切られます。
  • dnsperf の内部仕様を確認したわけではありませんが、環境のスペックに応じてクエリリクエストの送信量を調整しているようです。-Q で qps の上限を指定できますが、timeout が頻発する環境では、-Q の指定値を大きく下回る qps で通信が行われる場合があります。
*1 BIND では権威 DNS 用の構成(下記の named.conf 抜粋参照)でも、再帰問い合わせに応答していました。
recursion no;
allow-query { any; };
allow-recursion { none; };
allow-query-cache { none; };

キャッシュ DNS へ UDP でクエリ

dnsperf はデフォルトでは UDP でクエリリクエストを送信します。

クエリデータを登録したファイルを用意します。

[root@rocky8-client dnsperf]# cat test.com.lst
always1.test.com A
[root@rocky8-client dnsperf]#

以下の条件で実施します。

(-s) 試験対象の DNS サーバに cachedns(/etc/hosts 登録済み)を指定
(-d) クエリのリストファイルに test.com.lst を指定
[root@rocky8-client dnsperf]# dnsperf -s cachedns -d test.co.jp.lst
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s cachedns -d test.co.jp.lst
[Status] Sending queries (to 10.0.2.40:53)
[Status] Started at: Wed Jun 25 17:02:58 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         1             <<クエリリクエスト件数
  Queries completed:    1 (100.00%)   <<クエリレスポンス件数
  Queries lost:         0 (0.00%)     <<timeout 等で dnsperf にレスポンスがかえらなかった件数

  Response codes:       NOERROR 1 (100.00%)  <<NOERROR の件数
  Average packet size:  request 32, response 121
  Run time (s):         0.020616
  Queries per second:   48.506015            <<qps の実績

  Average Latency (s):  0.015844 (min 0.015844, max 0.015844)

[root@rocky8-client dnsperf]#

以下は、dnsperf 実行中のパケットキャプチャのログです。

x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.40 はキャッシュ DNS のアドレスです。クエリリクエストのパケット(#1)の RD(Recursion desired)が 1(再帰問い合わせ)であることが確認できます。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
2 ^C
[root@rocky8-client ~]# tshark -t a -r /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
    1 17:02:58.740927186    10.0.2.44 → 10.0.2.40    DNS 74 Standard query 0x0000 A www.test.co.jp
    2 17:02:58.754667898    10.0.2.40 → 10.0.2.44    DNS 163 Standard query response 0x0000 A www.test.co.jp A 1.2.3.4 NS ns2.test.jp NS ns1.test.jp A 10.0.2.29 A 10.0.2.28
[root@rocky8-client ~]# tshark -nn -r /tmp/test.pcap  -Y '(frame.number==1)' -V | grep ^Domain -A10|cat -n
Running as user "root" and group "root". This could be dangerous.
     1  Domain Name System (query)
     2      Transaction ID: 0x0000
     3      Flags: 0x0100 Standard query
     4          0... .... .... .... = Response: Message is a query
     5          .000 0... .... .... = Opcode: Standard query (0)
     6          .... ..0. .... .... = Truncated: Message is not truncated
     7          .... ...1 .... .... = Recursion desired: Do query recursively
     8          .... .... .0.. .... = Z: reserved (0)
     9          .... .... ...0 .... = Non-authenticated data: Unacceptable
    10      Questions: 1
    11      Answer RRs: 0
[root@rocky8-client ~]#

キャッシュ DNS へ TCP でクエリ

TCP でクエリリクエストを送信する場合は、dnsperf に -m tcp オプションを指定します。

クエリデータを登録したファイルを用意します。

[root@rocky8-client dnsperf]# cat test.com.lst
always1.test.com A
[root@rocky8-client dnsperf]#

以下の条件で実施します。

(-s) 試験対象の DNS サーバに cachedns(/etc/hosts 登録済み)を指定
(-d) クエリのリストファイルに test.com.lst を指定
(-m) トランスポートに TCP を指定
[root@rocky8-client dnsperf]# dnsperf -s cachedns -d test.com.lst -m tcp
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s cachedns -d test.com.lst -m tcp
[Status] Sending queries (to 10.0.2.40:53)
[Status] Started at: Wed Jun 25 17:09:18 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         1             <<クエリリクエスト件数
  Queries completed:    1 (100.00%)   <<クエリレスポンス件数
  Queries lost:         0 (0.00%)     <<timeout 等で dnsperf にレスポンスがかえらなかった件数

  Response codes:       NOERROR 1 (100.00%)   <<NOERROR の件数
  Average packet size:  request 34, response 118
  Run time (s):         0.016668
  Queries per second:   59.995200             <<qps の実績

  Average Latency (s):  0.016618 (min 0.016618, max 0.016618)

Connection Statistics:

  Reconnections:        0 (0.00% of 1 connections)

  Average Latency (s):  0.003801 (min 0.003801, max 0.003801)

[root@rocky8-client dnsperf]#

以下は、dnsperf 実行中のパケットキャプチャのログです。
x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.40 はキャッシュ DNS のアドレスです。TCP の 3WAY ハンドシェイク(#1-3)の後、クエリリクエスト(#4)を送信しています。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
10 ^C
[root@rocky8-client ~]# tshark -t a -r /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
    1 17:09:18.756510885    10.0.2.44 → 10.0.2.40    TCP 74 37175 → 53 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=3056287563 TSecr=0 WS=128
    2 17:09:18.759375688    10.0.2.40 → 10.0.2.44    TCP 74 53 → 37175 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=772209918 TSecr=3056287563 WS=128
    3 17:09:18.759506624    10.0.2.44 → 10.0.2.40    TCP 66 37175 → 53 [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=3056287566 TSecr=772209918
    4 17:09:18.760261548    10.0.2.44 → 10.0.2.40    DNS 102 Standard query 0x0000 A always1.test.com
    5 17:09:18.761087168    10.0.2.40 → 10.0.2.44    TCP 66 53 → 37175 [ACK] Seq=1 Ack=37 Win=29056 Len=0 TSval=772209922 TSecr=3056287566
    6 17:09:18.775723627    10.0.2.40 → 10.0.2.44    DNS 186 Standard query response 0x0000 A always1.test.com A 2.3.4.5 NS ns1.test.com NS ns2.test.com A 10.0.2.32 A 10.0.2.32
    7 17:09:18.775733517    10.0.2.44 → 10.0.2.40    TCP 66 37175 → 53 [ACK] Seq=37 Ack=121 Win=29312 Len=0 TSval=3056287582 TSecr=772209936
    8 17:09:18.776928578    10.0.2.44 → 10.0.2.40    TCP 66 37175 → 53 [FIN, ACK] Seq=37 Ack=121 Win=29312 Len=0 TSval=3056287583 TSecr=772209936
    9 17:09:18.777638099    10.0.2.40 → 10.0.2.44    TCP 66 53 → 37175 [FIN, ACK] Seq=121 Ack=38 Win=29056 Len=0 TSval=772209938 TSecr=3056287583
   10 17:09:18.777785129    10.0.2.44 → 10.0.2.40    TCP 66 37175 → 53 [ACK] Seq=38 Ack=122 Win=29312 Len=0 TSval=3056287584 TSecr=772209938
[root@rocky8-client ~]#

権威 DNS へ UDP でクエリ

クエリリクエストの送信先に権威 DNS を指定して実施します。

クエリデータを登録したファイルを用意します。

[root@rocky8-client dnsperf]# cat test.com.lst
always1.test.com A
[root@rocky8-client dnsperf]#

以下の条件で実施します。

(-s) 試験対象の DNS サーバに dns-testcom(/etc/hosts 登録済み。test.com ゾーンを管理する NS)を指定
(-d) クエリのリストファイルに test.com.lst を指定
[root@rocky8-client dnsperf]# dnsperf -s dns-testcom -d test.com.lst
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s dns-testcom -d test.com.lst
[Status] Sending queries (to 10.0.2.32:53)
[Status] Started at: Wed Jun 25 17:53:03 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         1             <<クエリリクエスト件数
  Queries completed:    1 (100.00%)   <<クエリレスポンス件数
  Queries lost:         0 (0.00%)     <<timeout 等で dnsperf にレスポンスがかえらなかった件数

  Response codes:       NOERROR 1 (100.00%)  <<NOERROR の件数
  Average packet size:  request 34, response 50
  Run time (s):         0.004907
  Queries per second:   203.790503           <<qps の実績

  Average Latency (s):  0.004339 (min 0.004339, max 0.004339)

[root@rocky8-client dnsperf]#

以下は、dnsperf 実行中のパケットキャプチャのログです。
x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.32 は権威 DNS(test.com の NS)のアドレスです。権威 DNS には BIND を使用していますが、再帰問い合わせ(RD(Recursion desired) = 1)に対してもレスポンスを返しています。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
2 ^C
[root@rocky8-client ~]# tshark -t a -r /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
    1 17:53:03.478581253    10.0.2.44 → 10.0.2.32    DNS 76 Standard query 0x0000 A always1.test.com
    2 17:53:03.482084774    10.0.2.32 → 10.0.2.44    DNS 92 Standard query response 0x0000 A always1.test.com A 2.3.4.5
[root@rocky8-client ~]# tshark -nn -r /tmp/test.pcap  -Y '(frame.number==1)' -V | grep ^Domain -A10|cat -n
Running as user "root" and group "root". This could be dangerous.
     1  Domain Name System (query)
     2      Transaction ID: 0x0000
     3      Flags: 0x0100 Standard query
     4          0... .... .... .... = Response: Message is a query
     5          .000 0... .... .... = Opcode: Standard query (0)
     6          .... ..0. .... .... = Truncated: Message is not truncated
     7          .... ...1 .... .... = Recursion desired: Do query recursively
     8          .... .... .0.. .... = Z: reserved (0)
     9          .... .... ...0 .... = Non-authenticated data: Unacceptable
    10      Questions: 1
    11      Answer RRs: 0
[root@rocky8-client ~]#

truncated(切り捨て)発生時の動作

UDP でクエリリクエストを送信した場合、クエリレスポンスの RR(Resource Record)サイズが大きいと(DNS サーバの設定にもよりますが)truncated(切り捨て)が発生します。dig では、UDP を TCP に変更し、再度クエリリクエストを送信します。これを TCP フォールバックといいます。「概要」で述べたとおりですが、dnsperf は TCP フォールバックには対応していません。

まずは dig で TCP フォールバックが行われる様子を確認します。(2 行目に Truncated が表示されています)

[root@rocky8-client dnsperf]# dig @cachedns bigtxt.test.co.jp TXT
;; Truncated, retrying in TCP mode.

; <<>> DiG 9.11.36-RedHat-9.11.36-16.el8_10.4 <<>> @cachedns bigtxt.test.co.jp TXT
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52900
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 3

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: e8ac39c1e45db7ca0d952f2c685bd121fb6751f5c4eca1f5 (good)
;; QUESTION SECTION:
;bigtxt.test.co.jp.             IN      TXT

;; ANSWER SECTION:
bigtxt.test.co.jp.      604800  IN      TXT     "123456789.1234 -長いので省略- 56789.123456789."

;; AUTHORITY SECTION:
test.co.jp.             595600  IN      NS      ns2.test.jp.
test.co.jp.             595600  IN      NS      ns1.test.jp.

;; ADDITIONAL SECTION:
ns1.test.jp.            595600  IN      A       10.0.2.28
ns2.test.jp.            595600  IN      A       10.0.2.29

;; Query time: 3 msec
;; SERVER: 10.0.2.40#53(10.0.2.40)
;; WHEN: 水  6月 25 19:36:17 JST 2025
;; MSG SIZE  rcvd: 5209                <<レスポンスサイズ

[root@rocky8-client dnsperf]#

以下は、dig 実行中のパケットキャプチャのログです。
x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.40 はキャッシュ DNS のアドレスです。クエリリクエスト(#1)に対するクエリレスポンス(#2)で Truncated(=1 : 切り捨て)が発生しているため、TCP フォールバック(#3 以降)の処理が行われています。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
12 ^C
[root@rocky8-client ~]# tshark -t a -r /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
    1 19:36:17.974052629    10.0.2.44 → 10.0.2.40    DNS 100 Standard query 0xb1c7 TXT bigtxt.test.co.jp OPT
    2 19:36:17.983979783    10.0.2.40 → 10.0.2.44    DNS 116 Standard query response 0xb1c7 TXT bigtxt.test.co.jp OPT
    3 19:36:17.984514959    10.0.2.44 → 10.0.2.40    TCP 74 33989 → 53 [SYN] Seq=0 Win=29200 Len=0 MSS=1460 SACK_PERM=1 TSval=3065106791 TSecr=0 WS=128
    4 19:36:17.985798907    10.0.2.40 → 10.0.2.44    TCP 74 53 → 33989 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=781029146 TSecr=3065106791 WS=128
    5 19:36:17.986012878    10.0.2.44 → 10.0.2.40    TCP 66 33989 → 53 [ACK] Seq=1 Ack=1 Win=29312 Len=0 TSval=3065106792 TSecr=781029146
    6 19:36:17.988183883    10.0.2.44 → 10.0.2.40    DNS 142 Standard query 0xcea4 TXT bigtxt.test.co.jp OPT
    7 19:36:17.990013985    10.0.2.40 → 10.0.2.44    TCP 66 53 → 33989 [ACK] Seq=1 Ack=77 Win=29056 Len=0 TSval=781029150 TSecr=3065106794
    8 19:36:17.991159182    10.0.2.40 → 10.0.2.44    DNS 5277 Standard query response 0xcea4 TXT bigtxt.test.co.jp TXT NS ns2.test.jp NS ns1.test.jp A 10.0.2.28 A 10.0.2.29 OPT
    9 19:36:17.991172700    10.0.2.44 → 10.0.2.40    TCP 66 33989 → 53 [ACK] Seq=77 Ack=5212 Win=39680 Len=0 TSval=3065106797 TSecr=781029152
   10 19:36:17.992458248    10.0.2.44 → 10.0.2.40    TCP 66 33989 → 53 [FIN, ACK] Seq=77 Ack=5212 Win=39680 Len=0 TSval=3065106799 TSecr=781029152
   11 19:36:17.993795793    10.0.2.40 → 10.0.2.44    TCP 66 53 → 33989 [FIN, ACK] Seq=5212 Ack=78 Win=29056 Len=0 TSval=781029154 TSecr=3065106799
   12 19:36:17.993805614    10.0.2.44 → 10.0.2.40    TCP 66 33989 → 53 [ACK] Seq=78 Ack=5213 Win=39680 Len=0 TSval=3065106800 TSecr=781029154
[root@rocky8-client ~]# tshark -nn -r /tmp/test.pcap  -Y '(frame.number==2)' -V | grep ^Domain -A10|cat -n
Running as user "root" and group "root". This could be dangerous.
     1  Domain Name System (response)
     2      Transaction ID: 0xb1c7
     3      Flags: 0x8380 Standard query response, No error
     4          1... .... .... .... = Response: Message is a response
     5          .000 0... .... .... = Opcode: Standard query (0)
     6          .... .0.. .... .... = Authoritative: Server is not an authority for domain
     7          .... ..1. .... .... = Truncated: Message is truncated  <<切り捨て発生
     8          .... ...1 .... .... = Recursion desired: Do query recursively
     9          .... .... 1... .... = Recursion available: Server can do recursive queries
    10          .... .... .0.. .... = Z: reserved (0)
    11          .... .... ..0. .... = Answer authenticated: Answer/authority portion was not authenticated by the server
[root@rocky8-client ~]#

次に dnsperf では TCP フォールバックが行われないことを確認します。

Truncated(切り捨て)対象のクエリデータを登録したファイルを用意します。

[root@rocky8-client dnsperf]# cat test.co.jp.lst
bigtxt.test.co.jp TXT
[root@rocky8-client dnsperf]#

以下の条件で実施します。

(-s) 試験対象の DNS サーバに cachedns(/etc/hosts 登録済み)を指定
(-d) クエリのリストファイルに test.co.jp.lst を指定
[root@rocky8-client dnsperf]# dnsperf -s cachedns -d test.co.jp.lst
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s cachedns -d test.co.jp.lst
[Status] Sending queries (to 10.0.2.40:53)
[Status] Started at: Wed Jun 25 19:40:27 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         1
  Queries completed:    1 (100.00%)
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 1 (100.00%)
  Average packet size:  request 35, response 35
  Run time (s):         0.002249
  Queries per second:   444.642063

  Average Latency (s):  0.001355 (min 0.001355, max 0.001355)

[root@rocky8-client dnsperf]#

以下は、dnsperf 実行中のパケットキャプチャのログです。
x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.40 はキャッシュ DNS のアドレスです。クエリリクエスト(#1)に対するクエリレスポンス(#2)では Truncated(=1 : 切り捨て)が発生していますが、TCP フォールバックは行われていません。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
2 ^C
[root@rocky8-client ~]# tshark -t a -r /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
    1 19:40:27.096778478    10.0.2.44 → 10.0.2.40    DNS 77 Standard query 0x0000 TXT bigtxt.test.co.jp
    2 19:40:27.097990489    10.0.2.40 → 10.0.2.44    DNS 77 Standard query response 0x0000 TXT bigtxt.test.co.jp
[root@rocky8-client ~]# tshark -nn -r /tmp/test.pcap  -Y '(frame.number==2)' -V | grep ^Domain -A10|cat -n
Running as user "root" and group "root". This could be dangerous.
     1  Domain Name System (response)
     2      Transaction ID: 0x0000
     3      Flags: 0x8380 Standard query response, No error
     4          1... .... .... .... = Response: Message is a response
     5          .000 0... .... .... = Opcode: Standard query (0)
     6          .... .0.. .... .... = Authoritative: Server is not an authority for domain
     7          .... ..1. .... .... = Truncated: Message is truncated   <<切り捨て発生
     8          .... ...1 .... .... = Recursion desired: Do query recursively
     9          .... .... 1... .... = Recursion available: Server can do recursive queries
    10          .... .... .0.. .... = Z: reserved (0)
    11          .... .... ..0. .... = Answer authenticated: Answer/authority portion was not authenticated by the server
[root@rocky8-client ~]#

timeout 発生時の動作

レスポンスを 2 秒遅延させるクエリデータを用意します。dnsperf では、-t オプションで各クエリが 2 秒未満で timeout になるように指定します。

まずは、想定したクエリのレスポンスが 2 秒遅延することを dig で確認します。

[root@rocky8-client dnsperf]# dig @dns-testcom always.slp2000.test.com +norec

; <<>> DiG 9.11.36-RedHat-9.11.36-16.el8_10.4 <<>> @dns-testcom always.slp2000.test.com +norec
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33548
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;always.slp2000.test.com.       IN      A

;; ANSWER SECTION:
always.slp2000.test.com. 60     IN      A       2.3.4.5

;; Query time: 2003 msec          <<2 秒遅延
;; SERVER: 10.0.2.32#53(10.0.2.32)
;; WHEN: 水  6月 25 20:11:34 JST 2025
;; MSG SIZE  rcvd: 57

[root@rocky8-client dnsperf]#

次に dnsperf での timeout の発生を確認します。

2 秒遅延用のクエリデータを登録したファイルを用意します。

[root@rocky8-client dnsperf]# cat test.com.lst
always1.slp2000.test.com A
always2.slp2000.test.com A
always3.slp2000.test.com A
[root@rocky8-client dnsperf]#

以下の条件で実施します。

(-s) 試験対象の DNS サーバに dns-testcom(/etc/hosts 登録済み。test.com の NS)を指定
(-d) クエリのリストファイルに test.com.lst を指定
(-t) クエリの timeout に 1 秒を指定

※ 今回権威 DNS に直接クエリリクエストを送信しています。キャッシュ DNS を介するとオーバーヘッドやら、キャッシュやらで面倒なので。

[root@rocky8-client dnsperf]# dnsperf -s dns-testcom -d test.com.lst -t 1
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s dns-testcom -d test.com.lst -t 1
[Status] Sending queries (to 10.0.2.32:53)
[Status] Started at: Wed Jun 25 20:16:10 2025
[Status] Stopping after 1 run through file
[Timeout] Query timed out: msg id 0        <<timeout 発生
[Timeout] Query timed out: msg id 1
[Timeout] Query timed out: msg id 2
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         3             <<クエリリクエストの件数
  Queries completed:    0 (0.00%)
  Queries lost:         3 (100.00%)   <<timeout のため、dnsperf で lost した件数。(正確には、2 秒遅延で届いていいるけど timeout 後なので無視した件数)

  Response codes:
  Average packet size:  request 42, response 0
  Run time (s):         0.005236
  Queries per second:   0.000000

  Average Latency (s):  0.000000 (min 0.000000, max 0.000000)

[root@rocky8-client dnsperf]#

以下は、dnsperf 実行中のパケットキャプチャのログです。
x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.32 は権威 DNS(test.com の NS)のアドレスです。クエリリクエスト(#1-3)に対し、クエリレスポンス(#4-6)が 2 秒遅延で返されています。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
6 ^C
[root@rocky8-client ~]# tshark -t a -r /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
    1 20:16:10.965779124    10.0.2.44 → 10.0.2.32    DNS 84 Standard query 0x0000 A always1.slp2000.test.com
    2 20:16:10.967228140    10.0.2.44 → 10.0.2.32    DNS 84 Standard query 0x0001 A always2.slp2000.test.com
    3 20:16:10.967750171    10.0.2.44 → 10.0.2.32    DNS 84 Standard query 0x0002 A always3.slp2000.test.com
    4 20:16:12.969762774    10.0.2.32 → 10.0.2.44    DNS 100 Standard query response 0x0000 A always1.slp2000.test.com A 2.3.4.5
    5 20:16:12.971850060    10.0.2.32 → 10.0.2.44    DNS 100 Standard query response 0x0001 A always2.slp2000.test.com A 2.3.4.5
    6 20:16:12.974816303    10.0.2.32 → 10.0.2.44    DNS 100 Standard query response 0x0002 A always3.slp2000.test.com A 2.3.4.5
[root@rocky8-client ~]#

-c オプションについて

-c オプションを指定するとスタブリゾルバ(クライアント)側のポート番号を散らせることができます。-c オプションに指定した数だけポート番号が使用されます。(-T オプションを指定すると複数のスレッドで実行できるっぽいですが、そちらは試していません。)

クエリデータを登録したファイルを用意します。

[root@rocky8-client dnsperf]# cat test.com.lst
always1.test.com A
always2.test.com A
always3.test.com A
always4.test.com A
[root@rocky8-client dnsperf]#

-c 1 で実施します。

(-s) 試験対象の DNS サーバに dns-testcom(/etc/hosts 登録済み。test.com の NS)を指定
(-d) クエリのリストファイルに test.com.lst を指定
(-c) 使用するポート番号の数に 1 を指定
[root@rocky8-client dnsperf]# dnsperf -s dns-testcom -d test.com.lst -c 1
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s dns-testcom -d test.com.lst -c 1
[Status] Sending queries (to 10.0.2.32:53)
[Status] Started at: Fri Jun 20 13:49:07 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         4
  Queries completed:    4 (100.00%)
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 4 (100.00%)
  Average packet size:  request 34, response 50
  Run time (s):         0.019705
  Queries per second:   202.994164

  Average Latency (s):  0.005829 (min 0.003262, max 0.013397)
  Latency StdDev (s):   0.005045

[root@rocky8-client dnsperf]#

以下は、dnsperf 実行中のパケットキャプチャのログです。
x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.32 は権威 DNS(test.com の NS)のアドレスです。権威 DNS のポートは 53 ですが、クライアント側は 51883 だけを使用しています。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
8 ^C
[root@rocky8-client ~]# tshark -n -r /tmp/test.pcap -T fields -e ip.addr -e udp.port
Running as user "root" and group "root". This could be dangerous.
10.0.2.44,10.0.2.32     51883,53
10.0.2.44,10.0.2.32     51883,53
10.0.2.32,10.0.2.44     53,51883
10.0.2.44,10.0.2.32     51883,53
10.0.2.32,10.0.2.44     53,51883
10.0.2.44,10.0.2.32     51883,53
10.0.2.32,10.0.2.44     53,51883
10.0.2.32,10.0.2.44     53,51883
[root@rocky8-client ~]#

-c 2 で実施します。

(-s) 試験対象の DNS サーバに dns-testcom(/etc/hosts 登録済み。test.com の NS)を指定
(-d) クエリのリストファイルに test.com.lst を指定
(-c) 使用するポート番号の数に 2 を指定
[root@rocky8-client dnsperf]# dnsperf -s dns-testcom -d test.com.lst -c 2
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s dns-testcom -d test.com.lst -c 2
[Status] Sending queries (to 10.0.2.32:53)
[Status] Started at: Fri Jun 20 13:59:47 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         4
  Queries completed:    4 (100.00%)
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 4 (100.00%)
  Average packet size:  request 34, response 50
  Run time (s):         0.007761
  Queries per second:   515.397500

  Average Latency (s):  0.003503 (min 0.003027, max 0.004029)
  Latency StdDev (s):   0.000453

[root@rocky8-client dnsperf]#

以下は、dnsperf 実行中のパケットキャプチャのログです。
x.x.x.44 はクライアント(スタブリゾルバ)、x.x.x.32 は権威 DNS(test.com の NS)のアドレスです。権威 DNS のポートは 53 ですが、クライアント側は 55941 と 54330 の 2 つのポートを使用しています。

[root@rocky8-client ~]# tshark -i 1 -f "port 53" -w /tmp/test.pcap
Running as user "root" and group "root". This could be dangerous.
Capturing on 'enp0s3'
8 ^C
[root@rocky8-client ~]# tshark -n -r /tmp/test.pcap -T fields -e ip.addr -e udp.port
Running as user "root" and group "root". This could be dangerous.
10.0.2.44,10.0.2.32     55941,53
10.0.2.32,10.0.2.44     53,55941
10.0.2.44,10.0.2.32     54330,53
10.0.2.44,10.0.2.32     55941,53
10.0.2.44,10.0.2.32     54330,53
10.0.2.32,10.0.2.44     53,54330
10.0.2.32,10.0.2.44     53,55941
10.0.2.32,10.0.2.44     53,54330
[root@rocky8-client ~]#

クエリリクエストの送信件数について

dnsperf はファイルに登録されているクエリデータを全件送信すると処理を終了します。-n オプションでファイルを読み込む回数を指定できます。例えば、ファイルにクエリデータを 10 件登録し、dnsperf のオプションに -n 10 を指定した場合、100(10 × 10)件のクエリリクエストが送信されます。ただし、-l オプションで負荷をかける期間(秒)を指定している場合、その期間を経過すると dnsperf は処理は終了します。

クエリデータを登録したファイルを用意します。

[root@rocky8-client dnsperf]# cat test.com.lst
always1.test.com A
always2.test.com A
always3.test.com A
[root@rocky8-client dnsperf]#

-n 未指定で実施します。(ヘルプには未記載ですが -n のデフォルトは 1 のようです)

(-s) 試験対象の DNS サーバに cachedns(/etc/hosts 登録済み)を指定
(-d) クエリのリストファイルに test.com.lst を指定
[root@rocky8-client dnsperf]# dnsperf -s cachedns -d test.com.lst
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s cachedns -d test.com.lst
[Status] Sending queries (to 10.0.2.40:53)
[Status] Started at: Mon Jun 23 16:26:14 2025
[Status] Stopping after 1 run through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         3             <<クエリリクエスト件数(=ファイルの登録件数)
  Queries completed:    3 (100.00%)   <<クエリレスポンス件数
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 3 (100.00%)
  Average packet size:  request 34, response 118
  Run time (s):         0.035905
  Queries per second:   83.553823

  Average Latency (s):  0.030855 (min 0.026469, max 0.033288)
  Latency StdDev (s):   0.003806

[root@rocky8-client dnsperf]#

次にファイルを複数回読み込むオプション(-n)を指定して実施します。

(-s) 試験対象の DNS サーバに cachedns(/etc/hosts 登録済み)を指定
(-d) クエリのリストファイルに test.com.lst を指定
(-n) ファイルの読み込み回数に 2 を指定
[root@rocky8-client dnsperf]# dnsperf -s cachedns -d test.com.lst -n 2
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s cachedns -d test.com.lst -n 2
[Status] Sending queries (to 10.0.2.40:53)
[Status] Started at: Mon Jun 23 16:27:44 2025
[Status] Stopping after 2 runs through file
[Status] Testing complete (end of file)

Statistics:

  Queries sent:         6             <<クエリリクエスト件数(= 3 × 2)
  Queries completed:    6 (100.00%)   <<クエリレスポンス件数
  Queries lost:         0 (0.00%)

  Response codes:       NOERROR 6 (100.00%)
  Average packet size:  request 34, response 118
  Run time (s):         0.024733
  Queries per second:   242.590870

  Average Latency (s):  0.013072 (min 0.005884, max 0.022011)
  Latency StdDev (s):   0.005832

[root@rocky8-client dnsperf]#

大量クエリ

10 万件のクエリデータを作成し、dnsperf に読み込ませます。
dnsperf の内部仕様を確認したわけではありませんが、環境のスペックに応じてクエリリクエストの送信量を調整しているようです。本検証環境のスペックが脆弱なためか、10000 qps の要求に対し、約 700 qps のパフォーマンスでした。ただし、全件 NOERROR でした。憶測ですが、RTT(Round Trip Time)あたりを見て、送信量を調整しているのではないかと思われます。RTT は DNS サーバの性能だけでは決まらないので、性能評価時には、ボトルネックの原因が DNS サーバかそれ以外(ネットワークや途中の機器)かを見極める必要があります。

クエリデータを作成します。(*1)

*1 ここでは権威サーバに PolarDNS を使用しています。PolarDNS は、alwaysX.test.com のクエリに対し、NOERROR のレスポンスを自動的に返します。ゾーンファイルへの RR の登録を必要としません。
[root@rocky8-client dnsperf]# rm -f test.com.lst
[root@rocky8-client dnsperf]# for i in `seq 1 100000`; do
>   echo "always${i}.test.com A" >> test.com.lst
> done
[root@rocky8-client dnsperf]# wc -l test.com.lst
100000 test.com.lst
[root@rocky8-client dnsperf]# head -n 1 test.com.lst; tail -n 1 test.com.lst
always1.test.com A
always100000.test.com A
[root@rocky8-client dnsperf]#

以下の条件で実施します。

(-s) 試験対象の DNS サーバに cachedns(/etc/hosts 登録済み)を指定
(-d) クエリのリストファイルに test.com.lst を指定
(-l) 試験期間を 30 秒 に設定
(-Q) qps の上限を 10000 に指定
(-S) 1 秒おきに qps を表示するように指定
[root@rocky8-client dnsperf]# dnsperf -s cachedns -d test.com.lst -l 30 -Q 10000 -S 1
DNS Performance Testing Tool
Version 2.12.0

[Status] Command line: dnsperf -s cachedns -d test.com.lst -l 30 -Q 10000 -S 1
[Status] Sending queries (to 10.0.2.40:53)
[Status] Started at: Mon Jun 23 18:49:51 2025
[Status] Stopping after 30.000000 seconds
1750672192.244700: 614.875605    <<1 秒間隔で qps を表示(左の数字は unixtime)
1750672193.246817: 732.449405
1750672194.248520: 682.837128
1750672195.250217: 705.802254
1750672196.252032: 703.722743
1750672197.254169: 700.503025
1750672198.255901: 736.723994
1750672199.257825: 699.653866
1750672200.259840: 727.534019
1750672201.261481: 668.902331
1750672202.262362: 705.378561
1750672203.263895: 704.919359
1750672204.266030: 685.536380
1750672205.267918: 674.726117
1750672206.270357: 694.306586
1750672207.271603: 717.106485
1750672208.273087: 681.987930
1750672209.274088: 683.316001
1750672210.275831: 704.771583
1750672211.276655: 690.431085
1750672212.282104: 701.179274
1750672213.284256: 669.559109
1750672214.285395: 695.208158
1750672215.286200: 668.461888
1750672216.287733: 719.896399
1750672217.289383: 673.888085
1750672218.291269: 682.712404
1750672219.292197: 704.346367
1750672220.298364: 684.776980
[Status] Testing complete (time limit)

Statistics:

  Queries sent:         20901             <<クエリリクエストの件数
  Queries completed:    20901 (100.00%)   <<クエリレスポンスの件数
  Queries lost:         0 (0.00%)         <<lost が発生しないように送信件数を調整?

  Response codes:       NOERROR 20901 (100.00%)
  Average packet size:  request 37, response 121
  Run time (s):         30.088482         <<試験期間は 30 秒
  Queries per second:   694.651196        <<qps の実績

  Average Latency (s):  0.142448 (min 0.040879, max 0.255005)
  Latency StdDev (s):   0.031440

[root@rocky8-client dnsperf]#
タイトルとURLをコピーしました