Chapter 04

再帰検索が出来るか確認しよう

koyamaso
koyamaso
2021.11.02に更新

スタブリゾルバ(DNSクライアント)は再帰検索を行いません。

スタブリゾルバは、/etc/resolv.confで指定したネームサーバ(もしくはそれが参照している別のネームサーバ)が再帰検索をして得た応答を受け取るだけで、スタブリゾルバ自体に再帰検索をする機能はありません。

また、基本的に、権威サーバは再帰検索要求を受け付けず、反復検索要求のみを受け付けます。

権威サーバが再帰検索要求を受け付ける(フルサービスリゾルバを兼用することを意味します)ことは可能ですが、DNSキャッシュポイズニング攻撃を受けたときのリスクが大きくなるので非推奨となっています。

権威サーバとフルサービスリゾルバの分離が強く推奨されているので、分離しましょう。

誤って権威サーバのIPアドレスを/etc/resolv.confに書いてしまうと、スタブリゾルバと権威サーバはどちらとも再帰検索を行わないので、名前解決が出来なくなります。

これを防ぐために、ネームサーバが再帰検索を行うか、行わないかを見分けることは重要です。

方法を2つ紹介します。

digの応答を見る

digコマンドを使ってリクエストを発行し、応答のフラグを確認します

ネームサーバのアドレスは今回は127.0.0.10だとします(適宜読み替えてください)

適当な名前でリクエストを発行してみましょう

$ dig example.com @127.0.0.10

; <<>> DiG 9.16.1-Ubuntu <<>> example.com @127.0.0.10
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 50633
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

WARNING: recursion requested but not availableとあります。

ra ビットが設定されていないことが分かります。ネームサーバで再帰検索が可能な時raビットが設定されます。

フラグの読み方の一部を紹介しておきます。このフラグはDNSの仕様で、RFC1035 4.1.1. Header section formatに説明があります。

フラグ ビットが設定されているときの意味 クエリで意味をもつ 応答で意味を持つ
qr 応答である (query or response) o o
aa 権威をもつ応答 (Authoritative Answer) x o
tc メッセージが長く途中で切れた (TrunCation) x o
rd 再帰検索を期待していた(Recursion Desired) o x
ra 再帰検索可能(Recursion Available) x o

dig +norec example.comのように、+norec オプションをつけると再帰検索をしない問い合わせ(rdビットを設定しない)をリクエストできます。このオプションはmanページで確認できます。

$  dig +norec example.com @127.0.0.10
; <<>> DiG 9.16.12 <<>> +norec example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 56024
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;example.com.                   IN      A

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Wed Mar 31 18:28:44 JST 2021
;; MSG SIZE  rcvd: 40

この例では、127.0.0.10で動作しているネームサーバにexample.comの名前解決を、再帰検索をせず行うようリクエストしました。

フラグを見るだけで以下のようなことが分かります
再帰検索をサポートしていますがrdビットを設定せずリクエストをしたので、再帰検索をせず、反復検索をしました。

  • qrビットが設定されている
    応答である
  • aaビットが設定されていない
    権威をもたない応答だった(自身が権威をもつゾーンに対象が含まれていなかった)
    ネームサーバが権威サーバでないときは、必ずaaビットは設定されません
  • tcビットが設定されていない
    メッセージはこれで完結している
  • rdビットが設定されている
    RFC1035によると、rdビットはクエリから応答にそのままコピーされます。しかし、一部の実装では守られていないようです(今調べています)
  • raビットが設定されている
    ネームサーバは再帰検索要求を受け付ける

RFC6895により詳しく述べられていました。

日本語訳もありました

AA、TC、RD、RA、CDビットは、ビットに応じて問い合わせだけ、または応答だけ
でしか理論上の意味を持たない。

RDビットとCDビットだけが問い合わせから
応答にコピーされると期待されるが、幾つかのDNS実装は応答ヘッダーの初期値
として問い合わせヘッダーのすべてをコピーする。従って、既存の実装を考慮
すると、"問い合わせ"ビットを応答で異なる意味で使用したり、"応答"ビットに
問い合わせの意味を定義したりするあらゆる試みは危険だろう。

BINDの設定を確認する

ログインして、まず53番ポートを使用しているプロセスが何か確認します

sudoで実行しなければprocess名が分からないことに注意しましょう

$ sudo ss -aup
State        Recv-Q       Send-Q             Local Address:Port                Peer Address:Port       Process                                                                                                                                                                                                                                    
UNCONN       0            0                      127.0.0.1:domain                   0.0.0.0:*           users:(("named",pid=203641,fd=26))                                                                   
UNCONN       0            0                      127.0.0.1:domain                   0.0.0.0:*           users:(("named",pid=203641,fd=25))                                                                    
UNCONN       0            0                  127.0.0.53%lo:domain                   0.0.0.0:*           users:(("systemd-resolve",pid=131695,fd=12))     

よって、users:(("named",pid=203641,fd=25))が53番ポートを使用していることが分かりました

namedはBINDのことを指します

systemctlで詳しい状態を調べましょう

$ systemctl status named
● named.service - BIND Domain Name Server
     Loaded: loaded (/lib/systemd/system/named.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2021-03-26 14:13:30 JST; 2 days ago
       Docs: man:named(8)
   Main PID: 203641 (named)
      Tasks: 8 (limit: 7031)
     Memory: 34.5M
     CGroup: /system.slice/named.service
             └─203641 /usr/sbin/named -f -u bind

pidが一致していたので(pid=203641)、

/lib/systemd/system/named.serviceが今動いているネームサーバだと分かりました。

次にsystemd のUnitファイルを調べて、設定ファイルがどこにあるか調べてみましょう

$ cat /lib/systemd/system/named.service
[Unit]
Description=BIND Domain Name Server
Documentation=man:named(8)
After=network.target
Wants=nss-lookup.target
Before=nss-lookup.target

[Service]
EnvironmentFile=-/etc/default/named
ExecStart=/usr/sbin/named -f $OPTIONS
ExecReload=/usr/sbin/rndc reload
ExecStop=/usr/sbin/rndc stop

[Install]
WantedBy=multi-user.target
Alias=bind9.service
$ cat /etc/default/named 
#
# run resolvconf?
RESOLVCONF=no

# startup options for the server
OPTIONS="-u bind"

特に設定ファイルについての記述は見当たりませんでした

OPTIONS="-c /etc/path/to/named.conf"

がある場合、/etc/path/to/named.confが読み込まれます。

今回は見当たらなかったので、journalctlを使ってみましょう

$ sudo journalctl -u named | grep named.conf
 3月 26 14:13:30 example.com named[203641]: loading configuration from '/etc/bind/named.conf'

よって/etc/bind/named.confが読み込まれていることが分かりました。

$ cat /etc/bind/named.conf
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";
include "/etc/bind/named.conf.default-zones";
$ cat /etc/bind/named.conf.options
options {
  ...
	  /*
         - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion.
         - If you are building a RECURSIVE (caching) DNS server, you need to enable
                 recursion.
         - If your recursive DNS server has a public IP address, you MUST enable access
                 control to limit queries to your legitimate users. Failing to do so will
                 cause your server to become part of large scale DNS amplification
                 attacks. Implementing BCP38 within your network would greatly
                 reduce such attack surface
	*/
        recursion no;
  ...
}

recursion noが記述されていたので、再帰検索要求を受け付けません。これは権威サーバです。

recursion yes(または記述がない場合)である場合、権威サーバとフルサービスリゾルバを兼用している可能性があります。

この場合は、/etc/bind/named.conf.localを見て、

 zone "example.com"  {
  type master;
  file "/etc/bind/global/example.com.zone";
 };

のようにlocalhost以外のゾーンが定義されていれば、権威サーバとフルサービスリゾルバを兼用していることになります。非推奨ですが、このネームサーバは/etc/resolv.confに記述出来ます。