鯖memo

主にDebianを使って色々と遊んでみます

Debian wheezy 7 にUnboundをインストール

f:id:log134:20150111012730p:plain

Debian wheezy に DNSキャッシュサーバのUnboundをインストールしてみます。
Unboundは簡易的なコンテンツDNSサーバとしても使えますが、用途はキャッシュDNSサーバに特化しており、その分設定が容易で高速で動くと言われています。

シェアNo.1と言われるbindはコンテンツサーバとキャッシュサーバが混在して設定が可能なこともあり、度々脆弱性が報告されています。
その点、キャッシュ用途に特化したUnboundはbindに比べ比較的セキュアであるとも言われています。

djbdnsが最もセキュアだと言われていますが、DNSSECとIPv6に未対応ということでunboundを選択しました。
現時点でDNSSECとIPv6は必須ではないですが・・・
なので、今回インストールするunboundはDNSSEC対応です。

ISPが用意したDNSやGoogleなどのパブリックDNSを使うのもいいですが、自前でDNSを用意してみたいと思います。
今回は最新バージョンを使うため、ソースからインストールします。

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

Debianを素の状態でインストールしたのでコンパイル、インストールに必要な環境を整えます。

apt-get install make gcc perl-modules libexpat-ocaml-dev dnsutils libevent-dev ca-certificates

UnboundのインストールにはOpenSSLとldnsが必要なので次にこれらをインストールしていきます。

OpenSSLのインストール

cd /usr/local/src/
wget https://www.openssl.org/source/openssl-1.0.1j.tar.gz
tar -xzvf openssl-1.0.1j.tar.gz
cd openssl-1.0.1j
./config shared
make
make install

特別な事情がなければ、公式サイトで最新バージョンを確認し、make&installします。

OpenSSL: The Open Source toolkit for SSL/TLS

ldnsのインストール

cd /usr/local/src/
wget http://www.nlnetlabs.nl/downloads/ldns/ldns-1.6.17.tar.gz
tar -xzvf ldns-1.6.17.tar.gz
cd ldns-1.6.17
./configure 
make
make install

こちらも最新バージョンを確認してインストールします。

nlnetlabs.nl :: ldns ::

Unboundのインストール

OpenSSLとldnsのインストールが終わったら、いよいよUnboundのインストールです。

cd ../
wget http://unbound.net/downloads/unbound-1.5.1.tar.gz
tar -xzvf unbound-1.5.1.tar.gz
cd unbound-1.5.1/
./configure --with-libevent
make
make install

with-libevent オプションをつけているのはこういう理由です。

libeventはプラットホーム特有のイベント通知システムコールのBSDライセンスのクロスプラットフォーム ラッパーです。
Unboundは1024個より多くのファイル記述子を効率よく使うためにlibeventを使うことができます。お好みのパッケージ マネージャでlibeventを(もしあればlibevent-develも)インストールします。unboundをコンパイルする前に、./configure --with-libeventを実行します。

最適化の方法 | 日本Unboundユーザー会

不要であればいりませんが、よく分からない場合は後々のために--with-libevent をつけておくといいでしょう。

ライブラリの呼び出し

/usr/local/lib 以下にldnsおよびunboundで使用するライブラリ等がインストールされるので、ここが検索できるようにします。

vi /etc/ld.so.conf

ファイルの末尾に以下を記述するだけです。

/usr/local/lib

ライブラリを認識させます。

ldconfig

unboundユーザーの作成

unboundを実行するグループとユーザーを作成します。

groupadd unbound
useradd -g unbound -d /usr/local/etc/unbound/ -s /bin/false unbound

このユーザーはログインする必要がないので、ログインシェルには/bin/falseを指定します。

resolv.confの編集

このサーバ自身の名前解決を自分で行うため、resolv.confを編集し、自分自身を参照するようにします。

vi /etc/resolv.conf 

ここを以下に変更します。

nameserver 127.0.0.1

下記のコマンドでルートゾーンのトラストアンカーファイルを取得しておきます。

unbound-anchor -a /usr/local/etc/unbound/root.key

設定ファイルの編集

下記の設定ファイルを編集し、unboundを設定します。

vi /usr/local/etc/unbound/unbound.conf 

以下、最低限の設定です。

interface: 127.0.0.1
interface: 192.168.10.100

access-control: 192.168.100.0/24 allow 

auto-trust-anchor-file: "/usr/local/etc/unbound/root.key"

interface: には待ち受けるIPアドレスを指定します。
access-control: へはこのDNSを参照できるIPアドレスを指定します。
ここでは、192.168.100.0/24 のみこのDNSサーバを利用できます。

auto-trust-anchor-file: はルートゾーンのトラストアンカー用ファイルです。
これを指定することでDNSSECが有効になります。

ファイルのオーナー、グループを変更します。

chown -R unbound:unbound /usr/local/etc/unbound/

起動スクリプトの作成と自動起動の設定

unboundの起動スクリプトと起動時/再起動時にunboudが自動で起動するように設定を行います。

#! /bin/sh
### BEGIN INIT INFO
# Provides: unbound
# Required-Start: $network $local_fs
# Required-Stop: $network $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: unbound recursive Domain Name Server.
# Description:  unbound is a Domain Name Server (DNS)
#               that is used to resolve host names to IP addresses.
### END INIT INFO

exec="/usr/local/sbin/unbound"
prog="unbound"
config="/usr/local/etc/unbound/unbound.conf"
pidfile="/usr/local/etc/unbound/unbound.pid"
rootdir="/usr/local/etc/unbound"

case "$1" in
    start)
        [ -x $exec ] || exit 5
        [ -f $config ] || exit 6
        echo -n $"Starting $prog: "

        # setup root jail
        if [ -s /etc/localtime ]; then
            [ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
            if [ ! -e ${rootdir}/etc/localtime ] || /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
                cp -fp /etc/localtime ${rootdir}/etc/localtime
            fi;
        fi;
        if [ -s /etc/resolv.conf ]; then
            [ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
            if [ ! -e ${rootdir}/etc/resolv.conf ] || /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
                cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
            fi;
        fi;
        if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
            [ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
            [ -e ${rootdir}/dev/log ] || touch ${rootdir}/dev/log
            mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
        fi;
        if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
            [ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
            [ -e ${rootdir}/dev/random ] || touch ${rootdir}/dev/random
            mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
        fi;

        # if not running, start it up here
        start-stop-daemon --start --quiet --pidfile $pidfile --exec $exec -- -c $config
        echo
        ;;

    stop)
        echo -n $"Stopping $prog: "
        start-stop-daemon --stop --quiet --oknodo --pidfile $pidfile
        echo
        if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
            umount ${rootdir}/dev/log >/dev/null 2>&1
        fi;
        if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
            umount ${rootdir}/dev/random >/dev/null 2>&1
        fi;
        ;;

    restart)
        start-stop-daemon --stop --quiet --oknodo --pidfile $pidfile
        start-stop-daemon --start --quiet --pidfile $pidfile --exec $exec -- -c $config
        ;;

    reload)
        start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile $pidfile --exec $exec
        ;;

    force_reload)
        start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile $pidfile --exec $exec
        ;;

    *)
        echo $"Usage: $0 {start|stop|restart|reload|force-reload}"
        exit 2
        ;;
esac

exit 0

実行権限を追加します。

chmod 755 /etc/init.d/unbound 

自動起動するように設定します。

insserv unbound

insservコマンドの場合、何も反応がなくコマンドが終了しますが問題ありません。
不安な場合は、/etc/rc.x/ を確認してunboundがあるか確認すればいいでしょう。

OpenSSLのシンボリックリンクを作成

上の手順をなぞった場合、opensslの場所が違うというエラーがでるので、下記のようにシンボリックリンクを貼っておきます。

ln -s /usr/local/ssl/bin/openssl /usr/local/sbin/openssl

unboundを起動

いざ、起動です。

/etc/init.d/unbound start

起動して、nslookup google.co.jp などを打ち、名前解決ができていれば完了です。

業務レベルで自前キャッシュDNSサーバを立てる場合、複数台の冗長化構成を取る必要があります。
最も簡単な方法は2台のDNSキャッシュサーバを作り、resolv.confにその2台を指定するだけなので特に難しいことはありません。