Unboundで内向きDNSを建てる
2019/05/29
サーバーの台数が増えてきて、「いい加減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: 192.168.0.0/16 allow
access-control: ::1/128 allow
access-control: fd00::/8 allow
access-control: fe80::/64 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で監視するのも設定しておこうと思う。(まだやってない)
参考
大いに助けになるので一緒に読んでおくべき。