純規の暇人趣味ブログ

首を突っ込んで足を洗う

Unboundで内向きDNSを建てる

      2018/04/07    HimaJyun

サーバーの台数が増えてきて、「いい加減IP直打ち/hostsで管理するの限界」という状況になったのでUnboundで内向きDNSを建てました。(状況がDNSというものが誕生した時に辿った歴史と全く同じですね)

という訳で、設定その他諸々、備忘録兼ねて記事に。

スポンサーリンク

内向きDNSを建てる

内向きDNSなら何でも良い訳ですが、BINDはひたすらに辛いとかそういう話題をたまに聞くのでパス。

という訳で候補がUnboudとPowerDNSになったのですが、今回は設定が簡単(そう)だとか、軽量(そう)だとかいう噂のUnboundを選択(PowerDNSもWebUIみたいなのが充実しててなかなか魅力的だった)

バージョン

そう極端な負荷は掛からないだろうと判断したので、ハードにはRaspberry Pi3を使っています。(それでも下手な民生用ルーターよりは高性能だし)

バージョンなどは以下の通り。

  • Raspberry Pi 3B
  • Raspbian Stretch
  • Unbound 1.6.0(aptでインストール)

要は「RasPiにRaspbian入れてaptでUnboundインストールした」です。

Unboundのインストール

とにもかくにもインストールしないと始まらない。

sudo apt-get install unbound

インストールすれば動く、素晴らしい。

基本的な設定

/etc/unbound/unbound.confが設定ファイル、aptでインストールしている場合は恐らく「unbound.conf.d/*.conf」をincludeするようになっているはず。なので、設定はそこに入れていく。

とりあえず基本的な設定を「unbound.conf.d/unbound.conf」などのファイル名で作成。内容に関してはコメントを参照。

(ちなみに設定ファイルはYAMLっぽい(というかそのもの?)、文章で書く時はYAMLのシンタックスハイライトを使うと捗るかも?)

server:
    # 外部からアクセスできる必要があるので0.0.0.0(::0)を指定する
    interface: 0.0.0.0
    interface: ::0
    # IPv4、v6両方使う
    do-ip4: yes
    do-ip6: yes
    # UDP/TCP両方使う
    do-udp: yes
    do-tcp: yes

    # デフォルトで外部からのアクセス不可っぽいので、ローカルからの問い合わせを許可
    #access-control: 0.0.0.0/0 refuse
    #access-control: ::1/0 refuse
    access-control: 127.0.0.1/8 allow
    access-control: ::1/128 allow
    access-control: 192.168.0.0/16 allow
    access-control: fd00::/8 allow

    # バージョンを知られないようにする
    hide-version: yes
    hide-identity: yes

    # roothintを指定する
    #sudo curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
    root-hints: "/etc/unbound/root.hints"

    # syslogは使わずにログファイルにログを出す
    logfile: "/var/log/unbound/unbound.log"
    use-syslog: no
    log-time-ascii: yes

remote-control:
    # unbound-controlとか使う
    control-enable: yes
    # ローカルから使うだけなので127.0.0.1(::1)でバインドして外からアクセスさせない
    control-interface: 127.0.0.1
    control-interface: ::1

    # 鍵はデフォルトのもの
    server-key-file: "/etc/unbound/unbound_server.key"
    server-cert-file: "/etc/unbound/unbound_server.pem"
    control-key-file: "/etc/unbound/unbound_control.key"
    control-cert-file: "/etc/unbound/unbound_control.pem"

root-hintsは以下のコマンドで取得して配置しておく。

sudo curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache

remote-controlは無効でも良いのですが、ルートヒントの自動更新時やログローテーションの時にダウンタイムなしにリロードするため、Zabbixなんかで監視するために使うのでローカルからしかアクセスできないように(127.0.0.1をバインド)して有効にしておく。

パフォーマンス調整

6台くらいあるサーバーから使うだけなので別にパフォーマンスは要らないのですが、高められるものはとりあえず高めておけばいいでしょう。

「unbound.conf.d/performance.conf」辺りにでも以下のようなファイルを作成。

server:
    # CPU論理コア数
    num-threads: 4

    # num-threadsに近い「2の累乗」
    msg-cache-slabs: 4
    rrset-cache-slabs: 4
    infra-cache-slabs: 4
    key-cache-slabs: 4

    # rrset-cache-size = msg-cache-size*2
    # 最大で指定値の2.5倍くらい消費する(らしい)ので余裕をもって
    rrset-cache-size: 128m
    msg-cache-size: 64m

    # libeventを使う
    # outgoing-range = num-queries-per-thread*2
    outgoing-range: 8192
    num-queries-per-thread: 4096

    # カーネルパラメータの「net.core.{r,w}mem_max」を制限解除する必要があるかも
    so-rcvbuf: 4m
    so-sndbuf: 4m

    # 基本的にyesで良いはず
    prefetch: yes
    prefetch-key: yes

    # ラウンドロビン使う
    rrset-roundrobin: yes
    # minimal-responsesはA/AAAAだけを引く環境ならyesで
    # MXを大量に引きまくる大規模なメールサーバーみたいなのが居るならnoの方が良い?
    minimal-responses: yes
    # 基本的にyesで良さそう?
    # 別のファイル(qname-minimisation.conf)で既にyesになっているかも
    qname-minimisation: yes
    # パフォーマンス上がるらしいが、イマイチ情報が見つからなかったのでとりあえずナシで
    #so-reuseport: yes

こんな感じかな?どこをどう設定すべきか割と苦戦する。

ルートヒントの自動更新

ルートヒントを1ヶ月おきに自動で更新する。

普通だったらcronを使う所なんだけど、ここは最近の流れに合わせてsystemdのtimerで自動更新する。(ArchWikiに載っていたのでそれを採用しただけ)

まずはサービスを作成、「/etc/systemd/system/roothints.service」にでも

[Unit]
Description=Update root hints for unbound
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/curl -S -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
ExecStartPost=/usr/sbin/unbound-control reload

curlとunbound-controlのパスはwhichで調べるといい。

タイマーを作成、「/etc/systemd/system/roothints.timer」にでも

[Unit]
Description=Update root.hints monthly

[Timer]
OnCalendar=monthly
Persistent=true     
Unit=roothints.service

[Install]
WantedBy=timers.target

タイマーを有効化

sudo systemctl start roothints.timer
sudo systemctl enable roothints.timer

これで定期更新されるはず。

ログローテーション

ログローテーションも設定しておく。

ログディレクトリを作成。

sudo mkdir -v /var/log/unbound
sudo chown -v unbound:unbound /var/log/unbound

「/etc/logrotate.d/unbound」を作成

/var/log/unbound/*.log {
    weekly
    rotate 10
    create 644 unbound unbound
    missingok
    notifempty
    compress
    delaycompress
    sharedscripts
    postrotate
        /usr/sbin/unbound-control log_reopen > /dev/null 2>&1 || true
    endscript
}

恐らくこれで問題ないはず。

内向きDNS

一番肝心な奴。

「unbound.conf.d/example.com.conf」みたいな感じで、1ドメイン1ファイルにするのがベストかと思う。

server:
    # 「transparent」は該当のlocal-dataが存在しない時に普通に問い合わせする設定
    # 外部のサーバーに自分のドメインを割り当てて使う事もあるかも知れないので、普通はこれで良いと思う
    local-zone: "example.com." transparent

    # 末尾のドットを忘れないように注意。
    # <domain>. [TTL] IN <Type> <Value>
    local-data: "example.com. 300 IN A 192.168.1.1"
    local-data: "foo.example.com. IN A 192.168.1.2"

    # 逆引きの設定
    # <IP> [TTL] <domain>.
    local-data-ptr: "192.168.1.1 300 example.com."
    local-data-ptr: "fd00:192f:168f:1::1 300 example.com."
    local-data-ptr: "192.168.1.2 foo.example.com."
    local-data-ptr: "fd00:192f:168f:1::2 foo.example.com."

    # もちろんラウンドロビンも可能
    local-data: "roundrobin.example.com. IN A 192.168.1.3"
    local-data: "roundrobin.example.com. IN A 192.168.1.4"

ちなみに「local-data(-ptr)」でTTLを省略すると3600(1時間)になる

総評

これで便利になったし、最近本当にIP直打ちとかで色々仕様変更が厳しくて苦戦していたので速を上げて巻き返したい

内向きDNSは必要、IP直打ち/hostsは無駄な刻苦でしかない。

近いうちにZabbixで監視するのも設定しておこうと思う。(まだやってない)

参考

大いに助けになるので一緒に読んでおくべき。

 - サーバー