DNSサーバ BIND

2021年12月8日

動作確認済みシステム Debian 11

DNSは、ホスト名とIPアドレスを対応付けます。DNSを使って、ホスト名からIPアドレスを取得(正引き)したり、IPアドレスからホスト名を取得したり(逆引き)します。

DNSサーバを、BINDを使って構築します。外部からDNSのお問い合わせができるように設定します。

セキュリティを確保するために、chrootを用いた運用を行うこととします。

ここでは、ドメイン名をexample.com、ネームサーバ名をns.exmaple.com、IPアドレスを203.0.113.123とします。また、ネームサーバは1台のみで構築し、セカンダリサーバは、お名前.comのセカンダリDNS(Slave)を利用します。

BINDをインストールします。

apt install bind9 bind9-utils

インストールした後はBINDが起動しているので、止めます。

systemctl stop named.service

内部向けゾーンファイルを作成します。

vi /etc/bind/named.conf.internal-zones
view "internal" {
    # 内部向けの対象範囲定義
    match-clients {
        localhost;
    };

    # 再帰検索を受け付ける
    recursion yes;

    # 正引きゾーン定義
    zone "example.com" {
        type master;
        file "/etc/bind/example.com.zone";
        allow-update { none; };
    };

    # 逆引きゾーン定義
    zone "123.113.0.in-addr.arpa" {
        type master;
        file "/etc/bind/123.113.0.in-addr.arpa.zone";
        allow-update { none; };
    };

    include "/etc/bind/named.conf.default-zones";

    empty-zones-enable no;
};

外部向けゾーンファイルを作成します。

vi /etc/bind/named.conf.external-zones
view "external" {
    # 外部向けの対象範囲定義
    match-clients { any; }; # 全てを対象

    # 再帰検索を受け付けない
    recursion no;

    # 正引きゾーン定義
    zone "example.com" {
        type master;
        file "/etc/bind/example.com.zone";
        allow-update { none; };
    };

    # 逆引きゾーン定義
    zone "123.113.0.in-addr.arpa" {
        type master;
        file "/etc/bind/123.113.0.in-addr.arpa.zone";
        allow-update { none; };
    };
};

オプション設定ファイルを編集します。

vi /etc/bind/named.conf.options
options {
    directory "/var/cache/bind";

    # 問合わせを受け付ける範囲
    # どこからも受け付ける
    allow-query { any; };

    # ゾーン情報の転送を許可する範囲
    # ローカルホストやローカルネットワーク内のホストへのみ許可する
    allow-transfer { localhost; localnets; };

    # BINDのバージョン情報を公開しない
    version "unknown";

    dnssec-validation auto;

    auth-nxdomain no;

    listen-on-v6 { any; };
};

# "error (unexpected RCODE REFUSED) ..." 出力抑止
server 0.0.0.0 {
    edns no;
};

# "DNS format error ... invalid response" 出力抑止
logging {
    category resolver { null; };
};

正引きゾーン定義ファイルを作成します。

vi /etc/bind/example.com.zone
$TTL 86400
$ORIGIN example.com
@ IN  SOA ns.example.com. administrator.example.com. (
  2021112103 ; Serial
  3600 ; Refresh
  900 ; Retry
  604800 ; Expire
  300 ; Minimum
)
      3600 IN  NS    ns.example.com.

      3600 IN  A     203.0.113.123
ns    3600 IN  A     203.0.113.123
www   3600 IN  A     203.0.113.123

@     3600 IN  MX 10 mail.example.com.

逆引きゾーン定義ファイルを作成します。

vi /etc/bind/123.113.0.in-addr.arpa.zone
$TTL 86400
@     IN  SOA   ns.example.com. administrator.example.com. (
  2021112101 ; Serial
  3600 ; Refresh
  900 ; Retry
  604800 ; Expire
  300 ; Minimum
)
      IN  NS    ns.example.com.
      IN  PTR   example.com.
$TTL
再帰問い合わせを行った際にキャッシングする時間。
$ORIGIN
ドメイン名が明示されていないレコードで補完するドメイン名を記述。
SOAレコード
DNSサーバ名と管理者のメールアドレス、DNSサーバの各種設定を記述。
DNSサーバ名は、NSレコードで定義したもの。メールアドレスは、@は使えないため、その代わりにピリオドで記述。
SOA 内のパラメータ
Serial
10桁のシリアルナンバー。
Refresh
リフレッシュ値。セカンダリサーバへのゾーン情報の転送間隔。
Retry
リフレッシュが失敗したときの再送間隔。
Expire
リフレッシュが失敗しているときのセカンダリサーバの有効期間。
Minimum
存在しないドメイン名に対して「存在しない」という情報(=ネガティブキャッシュ)を保持する時間。
NSレコード
このゾーンを管理するDNSサーバ。セカンダリサーバを定義するときは、追加でNSレコードを定義。
Aレコード
IPv4でホスト名とIPアドレスの関連付けを定義。
AAAAレコード
IPv6でホスト名とIPアドレスの関連付けを定義。
CNAMEレコード
正規ホスト名に対する別名を定義。
MXレコード
対象ドメイン宛てのメールの配送先(メールサーバ)のホスト名を定義。
TXTレコード
ホスト名に関連付けるテキスト情報(文字列)を定義。
PTRレコード
IPアドレスに対応するホスト名を定義。1IPアドレスに対し、1レコード。

設定ファイルを編集し、作成した内部向けゾーンファイル、外部向けゾーンファイルを読み込むようにします。

vi /etc/bind/named.conf
include "/etc/bind/named.conf.options";
include "/etc/bind/named.conf.local";

# コメント化
#include "/etc/bind/named.conf.default-zones";

# 追記
include "/etc/bind/named.conf.internal-zones";
include "/etc/bind/named.conf.external-zones";

OSのネームサーバ設定を編集します。

vi /etc/resolv.conf
domain example.com
search example.com
nameserver 127.0.0.1
nameserver xxx.xxx.xxx.xxx # (別のDNSサーバ1)
nameserver xxx.xxx.xxx.xxx # (別のDNSサーバ2)

nameserverの1個目が今回構築したネームサーバを指すようにします。

続いて、chrootを用いた運用とするようにしていきます。

起動時のオプションを変更します。

vi /etc/default/named
# 修正
OPTIONS="-u bind -4 -t /var/named/chroot"

chroot用ディレクトリを作成します。

mkdir -p /var/named/chroot/{etc,dev,var/cache/bind,var/run/named,usr/share}

chroot化に必要なスペシャルファイルを作成します。

mknod /var/named/chroot/dev/null c 1 3
mknod /var/named/chroot/dev/random c 1 8
mknod /var/named/chroot/dev/urandom c 1 9
chmod 660 /var/named/chroot/dev/{null,random,urandom}

BINDディレクトリをchroot用ディレクトリに移動させます。

mv /etc/bind /var/named/chroot/etc/
mv /usr/share/dns /var/named/chroot/usr/share/

BINDディレクトリのあった場所に、chroot用ディレクトリへ移動させたディレクトリを参照するシンボリックリンクを作成します。

ln -s /var/named/chroot/etc/bind /etc/bind

所有者・グループ・パーミッションを変更します。

chown bind:bind /var/named/chroot/etc/bind/rndc.key
chmod 775 /var/named/chroot/var/{cache/bind,run/named}
chgrp bind /var/named/chroot/var/{cache/bind,run/named}

BINDの起動スクリプトを編集します。

vi /etc/init.d/named
PIDFILE=/var/named/chroot/var/run/named/named.pid

BINDディレクトリのあった場所に、chroot用ディレクトリへ移動させたディレクトリを参照するシンボリックリンクを作成します。

ln -s /var/named/chroot/etc/bind /etc/bind

所有者・グループ・パーミッションを変更します。

chown bind:bind /var/named/chroot/etc/bind/rndc.key
chmod 775 /var/named/chroot/var/{cache/bind,run/named}
chgrp bind /var/named/chroot/var/{cache/bind,run/named}

BINDの起動スクリプトを編集します。

vi /etc/init.d/named
PIDFILE=/var/named/chroot/var/run/named/named.pid

rsyslogにログを出力するようにします。

vi /etc/rsyslog.d/bind-chroot.conf
$AddUnixListenSocket /var/named/chroot/dev/log

rsyslogを再起動します。

systemctl restart rsyslog.service

AppArmorを設定します。

vi /etc/apparmor.d/local/usr.sbin.named
/var/named/chroot/**            rwm,

AppArmorの設定変更を適用します。

systemctl reload apparmor.service

BINDを起動します。

systemctl start named.service

ファイアウォールを設定します。

ufw allow 'DNS'
ufw reload

お名前.comで、セカンダリDNS(Slave)の設定を行い、プライマリネームサーバ IPアドレスを、今回構築したネームサーバのIPアドレスにします。
また、ネームサーバの変更を行い、ネームサーバ1を今回構築したネームサーバのIPアドレス、ネームサーバ2を2nd.dnsv.jp(お名前.comが指定しているもの)に変更します。

しばらく時間を置けば、ネームサーバの変更が反映されます。

レコードの追加などの変更を行った場合、以下のコマンドを実行します。

systemctl reload named.service