CentOS7.9にBindをソースからインストールする手順

## はじめに

CentOS7にBindをソースからコンパイルしてインストールする用件があったので手順をまとめました。
Bindは利用者が多くサイバー攻撃で狙われやすい面があるので、運用には注意が必要です。
常に情報をウォッチし、必要であれば最新版をインストールするようにしてください。

## 前提

`CentOS-7-x86_64-Minimal-2009.iso`からインストールした状態で`yum update`のみを実行した環境で検証しています。

```
# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)
# uname -r
3.10.0-1160.el7.x86_64
```

今構築するBindは`example.com`ドメインの権威サーバとして動かします。
キャッシュDNSサーバとして動かす場合は設定が異なります。

## 必要なパッケージをインストール

必要なパッケージをインストールします。

```
yum install gcc-c++ perl epel-release openssl-devel libcap-devel wget
yum install libuv-devel --enablerepo=epel
```

## ソースダウンロード

ソースファイルは公式からダウンロードします。
公式：https://www.isc.org/bind/

この時は9.18.7がCurrent-Stableでした。

```
wget https://downloads.isc.org/isc/bind9/9.18.7/bind-9.18.7.tar.xz
```

## インストール

DNS-over-HTTPSは使わないので`--disable-doh`で無効化しています。

```
tar xJvf bind-9.18.7.tar.xz
cd bind-9.18.7
./configure --prefix=/usr/local/bind-9.18.7/ --disable-doh
make
make install
```

## シンボリックリンク

bindのバージョンを上げても起動スクリプトなどに影響が及ばないようにシンボリックリンクを張ります。
運用上よく使うコマンドもシンボリックリンクを貼ってPATHが通るようにしています。
ログも見やすいようにシンボリックリンクを貼っておきます。

```
ln -s /usr/local/bind-9.18.7 /usr/local/bind9
ln -s /usr/local/bind9/bin/dig /usr/local/bin/
ln -s /usr/local/bind9/sbin/rndc /usr/local/sbin/
ln -s /usr/local/bind9/var/log/named/ /var/log/
```

## ログディレクトリの作成

ログ出力先となるディレクトリを予め作成しておきます。

```
mkdir -p /usr/local/bind9/var/log/named/
```

## namedユーザ追加

Bindを動かすnamedユーザを作成します。

```
groupadd -g 53 named
useradd -u 53 -g 53 -s /bin/false -M --home-dir /dev/null named
```

## rndc設定

リモートでBindを操作できるようにrndcの設定をします。

まず、rndc-confgenを使用してrndc.confを作ります。

```
/usr/local/bind9/sbin/rndc-confgen > /usr/local/bind9/etc/rndc.conf
```

``` /usr/local/bind9/etc/rndc.conf
# Start of rndc.conf
key "rndc-key" {
        algorithm hmac-sha256;
        secret "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
};

options {
        default-key "rndc-key";
        default-server 127.0.0.1;
        default-port 953;
};
# End of rndc.conf

# Use with the following in named.conf, adjusting the allow list as needed:
# key "rndc-key" {
#       algorithm hmac-sha256;
#       secret "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
# };
#
# controls {
#       inet 127.0.0.1 port 953
#               allow { 127.0.0.1; } keys { "rndc-key"; };
# };
# End of named.conf
```

rndc.confの`key "rndc-key"`セクションをrndc_server.keyに写します。
（自分はコピーして余計なところを削除しました）

``` /usr/local/bind9/etc/rndc_server.key
key "rndc-key" {
        algorithm hmac-sha256;
        secret "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
};
```

rndc.confとrndc関連のファイルはセキュリティの観点から他ユーザには見えないほうがいいのでパーミッションを変えておきます。

```
chmod 400 /usr/local/bind9/etc/rndc.*
```

```
-r--------. 1 root root 525  9月 29 13:29 /usr/local/bind9/etc/rndc.conf
-r--------. 1 root root 101  9月 29 13:42 /usr/local/bind9/etc/rndc_server.key
```

## named.conf作成

allow-～の部分は構築する環境によって適宜変更してください。
権威サーバとして動かす想定の設定です。

``` /usr/local/bind9/etc/named.conf
include "/etc/rndc_server.key";

acl slave-servers {
        xxx.xxx.xxx.xxx;
        xxx.xxx.xxx.xxx;
};

acl manage-network {
        127.0.0.1;
        xxx.xxx.xxx.xxx/xx;
};

controls {
        inet 127.0.0.1 port 953
        allow { 127.0.0.1; } keys { "rndc-key"; };
};

options {
        directory "/var/named";
        pid-file "/var/run/named/named.pid";
        allow-transfer { slave-servers; manage-network; };
        allow-notify { slave-servers; };
        allow-query { any;};
        allow-recursion { none; };
        allow-query-cache { none; };
        recursion no;
        version "";};

logging {
        channel "default-log" {
                file "/var/log/named/named.log" versions 5 size 10M;
                severity info;
                print-time yes;
                print-severity yes;
                print-category yes;
        };
        channel "queries-log" {
                file "/var/log/named/query.log" versions 10 size 5M;
                severity info;
                print-time yes;
                print-severity yes;
                print-category yes;
        };
        category queries { "queries-log"; };
        category default { "default-log"; };
};

zone "." {
        type hint;
        file "root.hint";
};

zone "localhost" {
        type master;
        file "localhost.zone";
};

zone "0.0.127.in-addr.arpa" {
        type master;
        file "0.0.127.in-addr.arpa";
        notify no;
};

zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" {
        type master;
        file "localhost.ip6_rev.zone";
        notify no;
};

zone "example.com" {
        type master;
        file "zone/e/example.com";
        notify yes;
};
```

## root.hint

Rootサーバの一覧となるroot.hintはinternicが公開しています。
ダウンロードして配置します。
（稀に変わることもあるようですので、情報収集をしてください）

```
mkdir -p /usr/local/bind9/var/named/
cd /usr/local/bind9/var/named/
wget https://www.internic.net/domain/named.root -O root.hint
```

## zoneファイル準備

localhost用のゾーンファイルを用意します。

``` /usr/local/bind9/var/named/localhost.zone
$TTL 86400
@       IN SOA localhost. admin.localhost. (
        0000000001 ; serial
        28800      ; refresh 8hr
        14400      ; retry 4hr
        604800     ; expire 1w
        86400 )    ; default_ttl 24hr
        IN      NS      localhost.
        IN      A       127.0.0.1
        IN      AAAA    ::1

```

127.0.0.1用の逆引きゾーンファイルを用意します。

``` /usr/local/bind9/var/named/0.0.127.in-addr.arpa
$TTL 86400
@       IN SOA localhost. admin.localhost. (
        0000000001 ; serial
        28800      ; refresh 8hr
        14400      ; retry 4hr
        604800     ; expire 1w
        86400 )    ; default_ttl 24hr
        IN      NS      localhost.
1       IN      ptr     localhost.
```

::1用の逆引きゾーンファイルを用意します。

``` /usr/local/bind9/var/named/localhost.ip6_rev.zone
$TTL 86400
@       IN SOA localhost. admin.localhost. (
        0000000001 ; serial
        28800      ; refresh 8hr
        14400      ; retry 4hr
        604800     ; expire 1w
        86400 )    ; default_ttl 24hr
        IN      NS      localhost.
1       IN      ptr     localhost.
```

権威を持つドメイン(ここでは`example.com`)のゾーンファイルを作成します。
ディレクトリは管理しやすいように別ディレクトリとしています。

```
mkdir -p /usr/local/bind9/var/named/zone/e/
```

``` /usr/local/bind9/var/named/zone/e/example.com
$TTL 86400
@       IN SOA name-server. admin.example.com. (
        2022100300 ; serial
        28800      ; refresh 8hr
        14400      ; retry 4hr
        604800     ; expire 1w
        86400 )    ; default_ttl 24hr
        IN      NS      name-server.
        IN      A       192.0.2.1
        IN      AAAA    2001:db8::1
```

## パーミッション変更

今回はChrootで動かすので、インストールディレクトリ以下をすべてnamedユーザに所有者を変更します。

```
chown -R named.named /usr/local/bind-9.18.7/
```

ただし、rndc.confはrndcコマンドを実行するユーザが見えればいいので、rootユーザに戻します。

```
chown root.root /usr/local/bind-9.18.7/etc/rndc.conf
```


## 起動設定

systemctlの起動設定を行います

`/etc/sysconfig/named`に下記のオプションを記載します

``` '/etc/sysconfig/named'
OPTIONS="-t /usr/local/bind9/ -c /etc/named.conf"
```

Unitファイルを設定します

``` /etc/systemd/system/named.service
[Unit]
Description=Berkeley Internet Name Domain (DNS)

[Service]
Type=forking
EnvironmentFile=/etc/sysconfig/named
ExecStartPre=/bin/bash -c 'if [ ! "$DISABLE_ZONE_CHECKING" == "yes" ]; then /usr/local/bind9/bin/named-checkconf -t /usr/local/bind9/ -z /etc/named.conf; else echo "Checking of zone files is disabled"; fi'
ExecStart=/usr/local/bind9/sbin/named -u named $OPTIONS
ExecReload=/bin/sh -c '/usr/local/sbin/rndc reload > /dev/null 2>&1 || /bin/kill -HUP $MAINPID'
ExecStop=/bin/sh -c '/usr/local/sbin/rndc stop > /dev/null 2>&1 || /bin/kill -TERM $MAINPID'
PrivateTmp=true

[Install]
WantedBy=multi-user.target
```

自動起動を有効にします。

```
systemctl enable named.service
```

## コンフィグチェック

起動前にコンフィグチェックを行います。
何も出力されなければ正常です。

```
/usr/local/bind9/bin/named-checkconf -t /usr/local/bind9/ /etc/named.conf
```

## zoneチェック

ゾーンファイルに誤りがないかチェックします。
`OK`とシリアルが表示されればOK。

```
/usr/local/bind9/bin/named-checkzone -t /usr/local/bind9/ example.com /var/named/zone/e/example.com
```

実行結果

```
zone example.com/IN: loaded serial 2022100300
OK
```


## サービス起動

```
systemctl start named.service
```