2026年6月9日

2026年6月9日

NSD のパフォーマンスチューニング|計測してから server-count・reuseport・TCP・RRL を調整する

NSD はもともと軽量で速い権威 DNS サーバーなので、多くの環境では既定の設定のままでも十分に応答できます。チューニングが効くのは、問い合わせが多い・CPU のコアを使い切れていない・TCP の問い合わせが溜まる・攻撃的な大量の問い合わせを受ける、といった具体的な症状があるときです。この記事では、まず現状を計測し、そのうえで server-count と reuseport、TCP の上限、応答レート制限(RRL)、OS 側の設定を順に調整する方法を説明します。

内容は NSD 4.x 系を前提にしています(2026年10月現在)。設定項目はビルド時のオプションや版によって使えるものが変わるため、nsd -v で手元の版を確かめ、同梱の nsd.conf(5) のマニュアルと照らし合わせてください。設定を変える前に nsd.conf をバックアップし、検証環境で試してから本番に入れます。

まず計測する

何がボトルネックなのか分からないまま値を上げても、効果が出ないか、メモリを無駄に使うだけになります。次の3つを見て、どこで詰まっているかを確かめます。

NSD の統計

nsd-control stats_noreset

問い合わせの総数、UDP と TCP の内訳、応答コードの内訳などが表示されます(統計機能はビルド時に有効になっている必要があります)。stats は表示と同時にカウンタをリセットするため、監視の仕組みで定期的に取得している場合は stats_noreset を使います。

CPU とプロセス

top -H -p "$(pgrep -d, nsd)"

既定では NSD の応答用プロセスは1つです。複数コアのサーバーで1つのプロセスだけが CPU を使い切っていて、他のコアが空いているなら、後述の server-count を増やすと効果が見込めます。

OS の UDP 受信バッファ

nstat -az | grep -i -E 'UdpRcvbufErrors|UdpInErrors'

この値が増え続けている場合、NSD が受け取る前に OS が UDP パケットを捨てています。アプリケーションの設定ではなく、プロセス数か OS のバッファの問題です。

負荷をかけて測る

本番と同じ構成の検証環境で、DNS-OARC の dnsperf を使って負荷をかけると、変更前後の比較ができます。

# queries.txt には「名前 タイプ」を1行ずつ書く(例: www.example.com A)
dnsperf -s 192.0.2.1 -d queries.txt -l 30 -c 20

本番のサーバーに対して負荷試験を行うと、実際の利用者への応答が遅れます。試験は検証環境で行い、他者のサーバーには向けないでください。

server-count と reuseport でコアを使う

server:
    server-count: 4
    reuseport: yes
  • **server-count** は応答用プロセスの数です。CPU のコア数を上限の目安にし、NSD 以外の処理(OS、監視、ゾーン転送)にも余力を残します。
  • **reuseport: yes** にすると、各プロセスが同じポートを別々に開き、カーネルが問い合わせを振り分けます。server-count を増やしても1つのソケットを取り合う形だと伸びにくいため、両方をセットで設定するのが一般的です。

版によっては、プロセスを特定の CPU に割り当てる cpu-affinity などの項目もあります。効果は環境によって差が大きいので、計測で差が出たときだけ使います。

プロセスを増やすとメモリも増えます。NSD はゾーンをメモリに展開して答えるため、ゾーンの更新や nsd-control reload の際には、古いデータと新しいデータが一時的に並ぶ時間があり、使用量が一時的に増えます。nsd-mem でおおよその使用量を見積もり、余裕を持ったメモリを確保してから増やします。

TCP の上限とタイムアウト

TCP の問い合わせは、ゾーン転送、応答が大きく UDP で切り詰められた場合、DNS over TLS などで使われます。

server:
    tcp-count: 200
    tcp-timeout: 60
  • **tcp-count** は同時に受け付ける TCP 接続の数です。上限に達すると新しい接続を受け付けにくくなるため、TCP の問い合わせが多い環境では増やします。増やすほどファイルディスクリプタとメモリを使います。
  • **tcp-timeout** は、問い合わせが来ない接続を閉じるまでの秒数です。長すぎると、何もしない接続が枠を埋めます。

tcp-count を増やす場合は、プロセスが開けるファイル数の上限も確認します。systemd で動かしているなら、ユニットのドロップインで LimitNOFILE を設定できます。

# /etc/systemd/system/nsd.service.d/limits.conf
[Service]
LimitNOFILE=65536
systemctl daemon-reload
systemctl restart nsd

応答レート制限(RRL)

権威 DNS サーバーは、送信元を偽装した問い合わせで第三者への攻撃(反射・増幅攻撃)に使われることがあります。RRL は、同じ送信元のネットワークに同じ応答を短時間に大量に返さないようにする仕組みで、自分のサーバーの負荷も下げます。

server:
    rrl-ratelimit: 200
    rrl-slip: 2
    rrl-ipv4-prefix-length: 24
    rrl-ipv6-prefix-length: 56
  • **rrl-ratelimit** は1秒あたりの上限です。低すぎると、多くの利用者を抱える公開リゾルバーからの正当な問い合わせまで制限されます。
  • **rrl-slip** は、制限に引っかかった応答のうち、何回に1回を切り詰めた応答(TC ビット付き)で返すかです。正当なクライアントは TC を受けると TCP で問い合わせ直すため、名前解決が止まりにくくなります。
  • プレフィックス長は、どの範囲の送信元を「同じ相手」とみなすかです。

RRL はビルド時に有効になっている必要があり、多くのディストリビューションのパッケージでは有効になっていますが、手元の版で確認してください。監視サーバーなど、制限をかけたくない送信元がある場合は、制限の対象外にする項目もマニュアルにあります。

あわせて、ANY タイプの問い合わせを拒否する refuse-any も増幅攻撃の対策になります。使える版かどうかを確認してから設定します。

EDNS のバッファサイズは既定値を基本にする

UDP で返す応答の最大サイズ(EDNS のバッファサイズ)は、IP の断片化による取りこぼしを避けるため、近年の版では 1232 バイト前後が既定になっています。値を大きくすると TCP へのやり直しは減りますが、途中の経路で断片化されたパケットが捨てられて応答が届かない問題が起きやすくなります。特別な理由がない限り既定値のままにします。

ログを減らす

NSD は既定では問い合わせごとのログを出しません。調査のために verbosity を上げたままにしていると、大量の問い合わせを受けたときにログの書き込みが負荷になります。調査が終わったら元に戻します。問い合わせの記録が必要な場合は、ビルド時に有効にした dnstap を使い、別のプロセスに受け取らせる方法が負荷を抑えられます。

OS とネットワーク側の確認

  • UDP の受信バッファ:UdpRcvbufErrors が増えるなら、net.core.rmem_max などのカーネルパラメータと、NSD のプロセス数を見直します。値を変えるときは sysctl の設定ファイルに書き、再起動後も残るようにします。
  • NIC の割り込み:1つの CPU コアに受信処理が集中していないかを確認します。マルチキューの NIC では、割り込みが複数のコアに分散しているかを見ます。
  • ファイアウォールのコネクション追跡:大量の UDP を受けると、conntrack のテーブルが溢れてパケットが捨てられることがあります。53番ポートの通信を追跡の対象から外す設定を検討します。
  • 台数を増やす:1台の調整には限界があります。セカンダリを追加して NS レコードに並べる、エニーキャストで複数拠点に置くといった構成の変更のほうが効果が大きい場合もあります。

変更の進め方

  1. 変更前の統計と負荷試験の結果を記録します。
  2. 項目を1つずつ変え、nsd-checkconf /etc/nsd/nsd.conf で文法を確認してから反映します。待ち受けやプロセス数に関わる項目は、再起動しないと反映されない場合があります。
  3. 同じ条件で計測し、効果がなかった変更は元に戻します。
  4. 本番に入れた後は、統計とログ、dig @192.0.2.1 example.com SOA +norec での応答を確認します。

まとめ

  • 先に nsd-control stats_noreset、CPU の使われ方、UdpRcvbufErrors を見て、どこで詰まっているかを確かめます。
  • コアが余っているなら server-count と reuseport をセットで増やし、メモリの余裕も確認します。
  • TCP が多い環境では tcp-count とファイル数の上限を調整します。
  • RRL と ANY の拒否で増幅攻撃への悪用と負荷を抑えます。EDNS のバッファサイズは既定値を基本にします。

お気軽にご相談ください

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