CentOS サーバー管理・運用 ネームサーバー BIND

(最終更新日時:2013-02-04 21:15:47)
外向け(インターネット)用のプライマリーネームサーバー、および内向きネームサーバー(内部LAN)をBINDで運用します。
内向きネームサーバーにより、LAN内のクライアントPCから自サーバーへFQDNでアクセスできるようになります。
なお、キャッシングネームサーバーとしても動作させ、さらにDHCPサーバーとの連携も行います。

bind 9.8.xになりましたので、セキュリティ拡張機能 DNSSEC に対応しました。

インストール

chroot環境で動作するネームサーバー bind-chroot をインストールします。
# yum -y install bind-chroot

※ 以下の内容は bind-chroot-9.8.2-0.10.rc1.el6_3.6.x86_64 を対象に記述しています。

設定ファイルの準備

サンプルが準備されていますので、それをchroot環境にコピーして設定ファイルの準備を行います。
# cd /var/named/chroot
# cp /usr/share/doc/bind-*/sample/etc/*        etc/
# cp /usr/share/doc/bind-*/sample/var/named/*  var/named/
# rm var/named/my.*
# mkdir var/named/dynamic                                     # DDNS(Dynamic DNS)を行うゾーンファイル用のディレクトリを作成します

rndcの設定

BINDの制御ツール rndc の定義ファイルを編集して、BIND初回起動時に作成される rndc.key を使用するように設定します。
# # 定義ファイルを設定します
# vi /etc/rndc.conf
----------(vi ここから)----------
# Start of rndc.conf
#key "rndc-key" {                                             # rndc-key定義をコメントアウトまたは削除します
#        algorithm hmac-md5;
#        secret "FOcx8CK0oZxBGZp/a/337w==";
#};
include "/etc/rndc.key;"                                      # BIND初回起動時に作成されるrndc.keyを取り込みます----------(vi ここまで)----------

# rm /etc/rndc.key                                            # BIND初回起動時に作成させますので削除します

TSIGキーの作成

DHCPサーバーとの連携のため、Dynamic DNS用の TSIG(Transaction Signature) キーを作成します。
# cd /var/named/chroot/etc

# dnssec-keygen -a HMAC-MD5 -b 512 -n HOST client.localnet > key-ddns
                                                              # 赤字箇所にはDHCPサーバーで管理するドメイン名を指定します
                                                              # 2分程度の時間がかかります

# 作成した秘密鍵をTSIGキーに変換します
# grep Key: `cat key-ddns`.private | sed -e 's/^Key: //' > key-tsig
# echo -e "key \"ddnskey\" {\n\talgorithm\tHMAC-MD5;\n\tsecret\t\t\"`cat key-tsig`\";\n};" > ddns.key
# rm `cat key-ddns`.{key,private}
# rm key-{ddns,tsig}

# chown named ddns.key
# chmod 400   ddns.key

DNSSECの設定

DNSレコードの改ざんを防ぐための拡張機能である DNSSEC の設定を行います。
ZSK(Zone Signing Key:ゾーンに署名するための鍵)の更新はスマート署名機能を利用した「事前公開法」で行います。
# cd /var/named/chroot/var/named
# mkdir keys                                                  # KSK,ZSKを保管するディレクトリを作成します
# mkdir keys/deleted
# mkdir signed                                                # 署名済ゾーンファイルを保管するディレクトリを作成します

# 各公開ドメインごとに、KSK(Key Signing Key:ゾーン内の公開鍵情報に署名するための鍵)を作成します
# 赤字の箇所は各々のドメインに読み替えてください
# dnssec-keygen -K keys -a RSASHA256 -b 2048 -f ksk system-act.com > keys/ksk-system-act.com          # KSKを作成します
Generating key pair........+++ ...............+++             # /dev/random を使用して乱数を発生させていますので、かなり時間が
                                                              # かかります
                                                              # マシン本体のマウスを動かすことにより、時間を短縮できます

# 各公開ドメインごとに、事前公開の最初に使うZSKを作成します
# (すぐにゾーンに出力、すぐに署名を開始、30日後に署名を停止、31日後にゾーンから削除)
# 事前公開の2番目に使うZSKはキーロールオーバーの仕組みで作成します
# dnssec-keygen -K keys -a RSASHA256 -b 1024 -P now -A now \
>               -I `date -d '29 days' '+%Y%m%d150000'` -D `date -d '30 days' '+%Y%m%d150000'` \
>               system-act.com \
>             >  keys/zsk2-system-act.com
Generating key pair..++++++ .....++++++

上位権威サーバーへの登録

上位の権威サーバーにDSレコードを登録して、権威の連鎖を構築すべきなのですが、当サイトのレジストラはDNSSECに対応していないため ISC(Internet Systems Consortium) の DLV(DNSSEC Look-aside Validation) に登録することにします。

ISCのDLVサイト にアクセスします。
(※)クリックすると別画面で拡大画像が開きます。画像は Windows7 64bit のものです。
iscdlv01.gif Register』でアカウントを作成します。
iscdlv02.gif User name(a-z, 0-9, - が使用可能です)、Email、Password、Confirm(Passwordの確認用再入力)を入力します。

Sign Up』でアカウントを登録します。
iscdlv03.gif 確認用のメールが届きますので、

Visit this url to activate your account:

で指定されたURLにアクセスし、アカウントの登録を完了させます。
iscdlv11.gif アカウント登録の完了画面です。

Manage Zones』でゾーン(ドメイン)の管理を行います。
iscdlv12.gif add a zone』で管理するゾーン(ドメイン)の登録画面に遷移します。
iscdlv13.gif 登録するゾーン(ドメイン)を入力します。

Add Zone』でキーレコードの登録画面に遷移します。
iscdlv14.gif Add Record』の Record に

# cd /var/named/chroot/var/named/keys
# grep DNSKEY `cat ksk-system-act.com`.key

で表示される内容(KSK公開鍵)を入力します。

Add DNSKEY』でKSK公開鍵を登録します。
iscdlv15.gif KSK公開鍵の登録完了画面です。

表示されている TXT レコードの内容をドメインのゾーン定義ファイル

/var/named/chroot/var/named/system-act.com.ext

に追加します。
ISC DLVが TXT レコードの登録を検知すると Status が 『Good に変わります。

外部向けゾーンファイルの作成

外部向けの正引きゾーンファイルを作成します。
セカンダリネームサーバとして、マイハマネット さんのサービスを利用しています。
また、メールのSPF認証用TXTレコードを作成しています。

※定義内容は例示です。適宜読み替えてください。
# vi /var/named/chroot/var/named/system-act.com.ext
----------(vi ここから)----------
$TTL            1D                                            ; キャッシュの有効期間
@               IN      SOA     ns1     root (
        0               ; Serial                              ; DNSSECの署名時に設定しますので 0 にしておきます
        1H              ; Refresh  1H                         ; ゾーン転送のリフレッシュ間隔
        15M             ; Retry    15M                        ; リフレッシュに失敗した時の再試行間隔
        1W              ; Expiry   1W                         ; ゾーンデータの有効期間
        1D              ; Minimum  1D                         ; ネガティブキャッシュの有効期間
)
                IN      NS      ns1
                IN      NS      ns.maihama-net.com.

                IN      A       203.189.48.125

                IN      MX 10   mail
                IN      TXT     "v=spf1 mx:system-act.com ~all"

ns1             IN      A       203.189.48.125

mail            IN      A       203.189.48.125
                IN      TXT     "v=spf1 a:mail.system-act.com -all"
smtp            IN      CNAME   mail
pop3            IN      CNAME   mail
imap            IN      CNAME   mail
smtps           IN      CNAME   mail
pop3s           IN      CNAME   mail
imaps           IN      CNAME   mail

www             IN      A       203.189.48.125
ssh             IN      A       203.189.48.125
ftp             IN      A       203.189.48.125
svn             IN      A       203.189.48.125

dlv.system-act.com. 0 IN TXT  "DLV:1:xxxxxxxxxxxx"            ; ISC-DLVの認証用レコード
----------(vi ここまで)----------
※他の公開サーバーも同様の定義を作成しています。

ゾーンファイルにDNSSECの署名を行い、署名付きゾーンファイルを作成します。
※それぞれの環境に合わせて適宜変更してください。
# cronでも実行しますので、ゾーン署名用のスクリプトを作成します
# vi /usr/local/sbin/signzone
----------(vi ここから)----------
#!/bin/sh
# 変数を設定します
DOMAIN=$1
ZONEFILE=$2

# ソルト文字列を生成します
cat /dev/urandom | tr -c -d "[:xdigit:]" | head -c 6 | tr "[:lower:]" "[:upper:]" > /tmp/salt

# NSEC3方式で署名を行います
cd /var/named/chroot/var/named
dnssec-signzone -K keys -H 3 -3 `cat /tmp/salt` -N unixtime -S -o $DOMAIN -f signed/$DOMAIN $ZONEFILE

rm -f /tmp/salt
----------(vi ここまで)----------
# chmod 755 /usr/local/sbin/signzone

# 鍵を作成したドメイン名と署名の元になるゾーンファイルを指定して署名用のスクリプトを実行します
# signzone system-act.com system-act.com.ext
Verifying the zone using the following algorithms: RSASHA256.
Zone signing complete:
Algorithm: RSASHA256: KSKs: 1 active, 0 stand-by, 0 revoked
                      ZSKs: 1 active, 0 stand-by, 0 revoked
signed/system-act.com
※他の公開サーバーも同様に行います。

内部向けゾーンファイルの作成

内部LANクライアント向けの正引きゾーンファイルを作成します。

※定義内容は例示です。適宜読み替えてください。
# vi /var/named/chroot/var/named/system-act.com.int
----------(vi ここから)----------
$TTL            1D
@               IN      SOA     ns1     root (
        2012102201      ; Serial
        1H              ; Refresh  1H
        15M             ; Retry    15M
        1W              ; Expiry   1W
        1D              ; Minimum  1D
)
                IN      NS      ns1

                IN      A       192.168.11.11

                IN      MX 10   mail

ns1             IN      A       192.168.11.11

mail            IN      A       192.168.11.11
smtp            IN      CNAME   mail
pop3            IN      CNAME   mail
imap            IN      CNAME   mail
smtps           IN      CNAME   mail
pop3s           IN      CNAME   mail
imaps           IN      CNAME   mail

www             IN      A       192.168.11.11
ssh             IN      A       192.168.11.11
ftp             IN      A       192.168.11.11
ntp             IN      A       192.168.11.11
----------(vi ここまで)----------
※内部LAN用ですので、SPF用のTXTレコードは定義していません。
※他の公開サーバーも同様の定義を作成しています。

内部LANクライアント向けの逆引きゾーンファイルを作成します。
※定義内容は例示です。適宜読み替えてください。
# vi /var/named/chroot/var/named/11.168.192.rev
----------(vi ここから)----------
$TTL            1D
@               IN      SOA     ns1.system-act.com.     root.system-act.com. (
        2012102201      ; Serial
        1H              ; Refresh  1H
        15M             ; Retry    15M
        1W              ; Expiry   1W
        1D              ; Minimum  1D
)
                IN      NS      ns1.system-act.com.

11              IN      PTR     system-act.com.
----------(vi ここまで)----------

仮想サーバーセグメント用のゾーンファイルの作成

当サイトでは、仮想サーバー用のネットワークセグメント 192.168.101.0/24 を定義しています。
仮想サーバーセグメント用の正引きゾーンファイルを作成します。

※定義内容は例示です。適宜読み替えてください。
# vi /var/named/chroot/var/named/server.localnet
----------(vi ここから)----------
$TTL            1D
@               IN      SOA     ns1     root.system-act.com. (
        2012111401      ; Serial
        1H              ; Refresh  1H
        15M             ; Retry    15M
        1W              ; Expiry   1W
        1D              ; Minimum  1D
)
                IN      NS      ns1

                IN      A       192.168.101.11

ns1             IN      A       192.168.101.11
ntp             IN      A       192.168.101.11
gateway         IN      A       192.168.101.11

actmysql        IN      A       192.168.101.101
actpgsql        IN      A       192.168.101.111
----------(vi ここまで)----------

仮想サーバーセグメント用の逆引きゾーンファイルを作成します。
※定義内容は例示です。適宜読み替えてください。
# vi /var/named/chroot/var/named/101.168.192.rev
----------(vi ここから)----------
$TTL            1D
@               IN      SOA     ns1.server.localnet.    root.system-act.com. (
        2012102201      ; Serial
        1H              ; Refresh  1H
        15M             ; Retry    15M
        1W              ; Expiry   1W
        1D              ; Minimum  1D
)
                IN      NS      ns1.server.localnet.

                IN      PTR     server.localnet.
                IN      A       255.255.255.0

11              IN      PTR     gateway.server.localnet.

101             IN      PTR     actmysql.server.localnet.
111             IN      PTR     actpgsql.server.localnet.
----------(vi ここまで)----------

クライアントPCセグメント用のゾーンファイルの作成

当サイトでは、サーバー機をゲートウェイサーバーとして運用しています。
そのため、クライアントPCを接続するLANについてもネットワークセグメント 192.168.201.0/24 を定義しています。

クライアントPCセグメント用の正引きゾーンファイルを作成します。
※定義内容は例示です。適宜読み替えてください。
# クライアントPCセグメントでは、DHCPと連携したDDNSによるゾーンファイルの更新が発生します
# そのため、dynamic ディレクトリにゾーンファイルを配置します
# vi /var/named/chroot/var/named/dynamic/client.localnet

$TTL            1D
@               IN      SOA     ns1     root.system-act.com. (
        2012102201      ; Serial
        1H              ; Refresh  1H
        15M             ; Retry    15M
        1W              ; Expiry   1W
        1D              ; Minimum  1D
)
                IN      NS      ns1

                IN      A       192.168.201.11

ns1             IN      A       192.168.201.11
gateway         IN      A       192.168.201.11

ep-803a         IN      A       192.168.201.21
whr-g301n       IN      A       192.168.201.31

rd-xs40         IN      A       192.168.201.201
regza-32c3000   IN      A       192.168.201.211

playstaion3     IN      A       192.168.201.221
nintendo-wii    IN      A       192.168.201.222
----------(vi ここまで)----------

クライアントPCセグメント用の逆引きゾーンファイルを作成します。
※定義内容は例示です。適宜読み替えてください。
# vi /var/named/chroot/var/named/dynamic/201.168.192.rev
----------(vi ここから)----------
$TTL            1D
@               IN      SOA     ns1.client.localnet.    root.system-act.com. (
        2012102201      ; Serial
        1H              ; Refresh  1H
        15M             ; Retry    15M
        1W              ; Expiry   1W
        1D              ; Minimum  1D
)
                IN      NS      ns1.client.localnet.

                IN      PTR     client.localnet.
                IN      A       255.255.255.0

11              IN      PTR     gateway.client.localnet.

21              IN      PTR     ep-803a.client.localnet.
31              IN      PTR     whr-g301n.client.localnet.

201             IN      PTR     rd-xs40.client.localnet.
211             IN      PTR     regza-32c3000.client.localnet.

221             IN      PTR     playstation3.client.localnet.
222             IN      PTR     nintendo-wii.client.localnet.
----------(vi ここまで)----------

定義ファイルの編集

内向けのゾーン定義を2つの view で行うため、当サイトでは取り込み用のファイルを作成しています。
# vi /var/named/chroot/etc/internal.zonef
----------(vi ここから)----------
        zone "system-act.com"
        {
                type            master;
                file            "system-act.com.int";         // 内部向けゾーンファイルを指定します
                allow-update    { none; };                    // ゾーンファイルの更新は許可しません
        };

        zone "11.168.192.in-addr.arpa"
        {
                type            master;
                file            "11.168.192.rev";
                allow-update    { none; };
        };

        zone "server.localnet"
        {
                type            master;
                file            "server.localnet";
                allow-update    { none; };
        };

        zone "101.168.192.in-addr.arpa"
        {
                type            master;
                file            "101.168.192.rev";
                allow-update    { none; };
        };

        zone "client.localnet"
        {
                type            master;
                file            "dynamic/client.localnet";
                allow-update    { key ddnskey; };             // DHCPによるゾーンファイルの更新を許可します
                check-names     ignore;                       // Android端末のホスト名がエラーになるのを回避します
        };

        zone "201.168.192.in-addr.arpa"
        {
                type            master;
                file            "201.168.192.rev";
                allow-update    { key ddnskey; };
                check-names     ignore;
        };
----------(vi ここまで)----------

定義ファイル named.conf を編集します。
# vi /var/named/chroot/etc/named.conf
----------(vi ここから)----------
       :
        //listen-on port 53     { any; };
        listen-on port 53       { any; };                     // 全ネットワークインターフェースの IPv4 Port 53 を監視します
        //listen-on port 53     { 127.0.0.1; };

        //listen-on-v6 port 53  { any; };
        //listen-on-v6 port 53  { ::1; };                     // IPv6 は監視しません
       :
        */

        allow-query             { localnets; };               // 全ローカルネットセグメントからの問合せを許可します
        allow-query-cache       { localnets; };               // 全ローカルネットセグメントからの問合せをキャッシュします
        allow-transfer          { none; };                    // ゾーンファイル情報の更新を通知しません
        notify                  no;

        forwarders              { 192.168.11.1; };            // 解決できない問い合わせをルーターへ転送します

        // Enable/disable recursion - recursion yes/no;
       :
        dnssec-enable yes;

        /* Enable DNSSEC validation on recursive servers */
        dnssec-validation       auto                          // DNSSECの検証を有効にします

        /* Enable DLV by default, use built-in ISC DLV key. */
        dnssec-lookaside auto;
        bindkeys-file           "/etc/named.iscdlv.key";      // ISC DLVを利用するためのkeyファイルを指定します

        empty-zones-enable      no;                           // emptyゾーンによる名前解決を無効にします
        version                 "unknown";                    // バージョンの通知を unknown にします
};

logging
       :
        channel default_debug {
                file "data/named.run";
                severity dynamic;
        };
        category lame-servers   { null; };                    // 逆引きエラーのログ出力を抑止します
        category edns-disabled  { null; };                    // automatic empty zoneエラーのログ出力を抑止します
};

controls                                                      // RNDCコマンドをlocalhostのみに許可し、暗号化鍵を指定します
{
        inet 127.0.0.1          allow { 127.0.0.1; } keys { "rndckey"; };
};
       :
view "localhost_resolver"
{
       :
        include "/etc/named.rfc1912.zones";
 
        include "/etc/internal.zone";                         // 内向けのゾーン定義フィルを取り込みます
};
view "internal"
{
       :
/*                                                            // my.*ゾーンの定義を削除またはコメントアウトします
        zone "my.internal.zone" { 
                type master;
                file "my.internal.zone.db";
        };
        zone "my.slave.internal.zone" {
                type slave;
                file "slaves/my.slave.internal.zone.db";
                masters { /* put master nameserver IPs here */ 127.0.0.1; } ;
               // put slave zones in the slaves/ directory so named can update them
        };
        zone "my.ddns.internal.zone" {
                type master;
                allow-update { key ddns_key; };
                file "dynamic/my.ddns.internal.zone.db";
                // put dynamically updateable zones in the slaves/ directory so named can update them
        };
*/

        include "/etc/internal.zone";                         // 内向けのゾーン定義フィルを取り込みます
};

/*                                                            // key ddns_keyの定義を削除またはコメントアウトします
key ddns_key
{
        algorithm hmac-md5;
        secret "use /usr/sbin/dnssec-keygen to generate TSIG keys";
};
*/

        include "/etc/rndc.key";                              // RNDC用の秘密鍵を取り込みます
        include "/etc/ddns.key";                              // DHCP用の秘密鍵を取り込みます

view    "external"
{
       :
/*                                                            // my.*ゾーンの定義を削除またはコメントアウトします
        zone "my.external.zone" { 
                type master;
                file "my.external.zone.db";
        };
*/

        zone "system-act.com"
        {
                type            master;
                file            "signed/system-act.com.zone.ext";        // DNSSEC署名済の外部向けゾーンファイルを指定します
                allow-query     { any;  };
                allow-update    { none; };
                allow-transfer  { 123.50.202.226; 198.104.58.211; };     // 2nd DNSサービスへのゾーン転送を許可します
                notify          yes;                                     // 2nd DNSサービスへゾーンの更新を通知します
        };
};

/* Trusted keys
       :
----------(vi ここまで)----------

resolv.conf の設定を置き換えます。
# vi /etc/resolv.conf
----------(vi ここから)----------
domain     system-act.com                                     # 補完ドメインを設定しています
nameserver 192.168.11.11                                     # ネームサーバーのIPアドレスを設定します
----------(vi ここまで)----------

ファイアーウォールの設定

ファイアーウォール iptables の設定スクリプトにルールを追加します。
# vi /usr/local/sbin/firewall.sh
----------(vi ここから)----------# --- (INPUTチェイン) ---# DNS問合せを許可
iptables -A INPUT -i $EXTIF -p udp --sport  53 -j ACCEPT
iptables -A INPUT -i $EXTIF -p udp --dport  53 -j ACCEPT
iptables -A INPUT -i $EXTIF -p tcp --dport  53 -j ACCEPT# --- (OUTPUTチェイン) ---# DNS問合せを許可
iptables -A OUTPUT -o $EXTIF -p udp --sport  53 -j ACCEPT
iptables -A OUTPUT -o $EXTIF -p tcp --sport  53 -j ACCEPT----------(vi ここまで)----------

# firewall.sh                                                 # 設定を反映させます

起動

ネームサーバーを起動します。
# # ファイルの所有者とパーミッションを設定します
# chown -R named.named /var/named/chroot/var/named
# chmod -R 770         /var/named/chroot/var/named

# # SELinuxの設定を行います
# setsebool -P named_write_master_zones 1

# # ネームサーバーを起動します
# chkconfig named on
# service   named start

キーロールオーバー

cronによりキーの更新やゾーンファイルの署名を定期的に行います。

※それぞれの環境に合わせて適宜変更してください。
# vi /etc/cron.weekly/dnssec-key-rollover
----------(vi ここから)----------
#!/bin/sh

# 変数を設定する
DOMAIN=system-act.com
ZONEFILE=system-act.com.ext

cd /var/named/chroot/var/named/keys

# ZSK-1が存在し、鍵使用終了日から5日以上経過していた場合、ZSK-1を削除ディレクトリに移動する
if [ -e zsk1-$DOMAIN ]; then
  ZSK1INACTIVE=`grep Inactive \`cat zsk1-$DOMAIN\`.key | cut -d ' ' -f 3 | head -c 8`
  if [ `date -d "5 days ago" '+%Y%m%d'` -ge $ZSK1INACTIVE ]; then
    mv -v `cat zsk1-$DOMAIN`.* deleted/
    mv -v  zsk1-$DOMAIN        deleted/zsk-$DOMAIN-$ZSK1INACTIVE
  fi
fi

# ZSK-2の鍵使用終了日まで25日以内になったら、ZSK-2をZSK-1にして、新しいZSK-2を作成する
ZSK2INACTIVE=`grep Inactive \`cat zsk2-$DOMAIN\`.key | cut -d ' ' -f 3 | head -c 8`
if [ `date -d "25 days" '+%Y%m%d'` -ge $ZSK2INACTIVE ]; then
  mv zsk2-$DOMAIN zsk1-$DOMAIN
  # ZSK-2作成用の日付を求める
  ACTIVATE=${ZSK2INACTIVE}150000
  INACTIVE=`date -d "${ACTIVATE:0:4}-${ACTIVATE:4:2}-${ACTIVATE:6:2} 30 days" '+%Y%m%d150000'`
  DELETE=`date -d "${ACTIVATE:0:4}-${ACTIVATE:4:2}-${ACTIVATE:6:2} 31 days" '+%Y%m%d150000'`
  # ZSK-2を作成する
  dnssec-keygen -r /dev/urandom -a RSASHA256 -b 1024 \
    -P now -A $ACTIVATE -I $INACTIVE -D $DELETE $DOMAIN > zsk2-$DOMAIN
  cat `cat zsk2-$DOMAIN`.key
fi

# ゾーンファイルに署名を行い、反映させる
signzone $DOMAIN $ZONEFILE
rndc reload
----------(vi ここまで)----------
# chmod 755 /etc/cron.weekly/dnssec-key-rollover

フィードバック

記事の内容についてのご質問、ご指摘、その他ご意見等は、公式ブログ/Twitter にて受け付けております。

System House ACT 公式ブログ内記事 : サーバー管理・運用 ネームサーバー BIND

トラックバックまたはコメントにてお寄せください。

Twitter では .@systemact 宛につぶやいてください。
また、こちら から、この記事についてつぶやくことができます。
a System House to build an Accounting system by the Computer Technology