Unbound を使っていた
vnet jail で ipfw を動かして外への gateway にして、cache DNS server として unbound を動かしていた。
Unbound が死ぬ
難儀なのが、この Unbound が時々異常終了することである。 何が効いたか分からないが、最近は jail を道連れにするようになってかなり困っていた。 私一人なら jail を起動しなおせば済むのだが、 「実家ではインターネットの通信が切れることなんてまずないのに、なんでこのうちはしょっちゅう切れるの?」 と言われるとつらい。 つらいだけでなく、趣味で gateway を FreeBSD host にしているのをやめるところまで追い込まれるかもしれない。
Unbound が死ぬ時のログはこんな感じである。
Jun 14 08:51:11 gate unbound[51935]: [51935:0] notice: sendto failed: No buffer space available Jun 14 08:51:11 gate unbound[51935]: [51935:0] notice: remote address is 2001:0DB8::53 port 53
前は月に1回くらいであったが、ここのところ、ログからすると 5/27, 5/31, 6/2, 6/6, 6/8, 6/14 と切れている。 外部とつながる cache DNS server が死んだら実質使えなくなるし、gateway の jail が落ちた日には通信が遮断されるので、 そりゃユーザーとしては頭にくるであろう。
原因がはっきりしないなりに対策はした
”sendto failed"、"No buffer space available" というのを手がかりに、sysctl の kern.ipc.maxsockbuf の値を増やしてみたり、 kern.maxfiles と kern.maxfilesperproc を増やしてみたり。 でまあ、効き目はあまりなかった。2日で落ちていたのが、6日保つようになったくらい。
検索してもそれらしい話には当たらない。
https://forum.netgate.com/topic/144487/unbound-and-traffic-shaping-cause-sendto-failed-no-buffer-space-available では "traffic shaper" が悪さをしているという話になっているので、同じ jail の中で ipfw を動かしているのがあかん可能性はあるけど、traffic shaping にあたることはしていない。
Pfsense on Esxi--sudden loss in dns resolving : PFSENSE にも似た話はあるが、コメントに "No real solution was found." とかあって泣く。
解決策がみつからないとはいえ、上記2例を見るに、Unbound に問題があると言ってもよさそうである。 ならば cache DNS server を変えてみるという手はあるだろう。
knot-resolver
knot-resolver を試すことにした。
Authoritative DNS server と比べて、cache DNS server には検索して出てくる選択肢が少ない。 私が見つけられたのは、BIND、Unbound、knot-resolver だけである。 というわけで、試すのは自動的に knot-resolver になる。 こいつが駄目なら、古きよき BIND に還ることになる。
sysctl.conf の設定
起動するといきなり、kern.maxfilesperproc を 524288 以上にしろとかいうメッセージが出るので、
kern.maxfiles=1048576 kern.maxfilesperproc=524288
に設定する。host 側で設定すると jail にも効くので、host の /etc/sysctl.conf に書く。
kresd を rc.d で制御する
FreeBSD ports にある knot-resolver は、2020/06/21 現在は rc.d スクリプトをインストールしてくれないので、 自分で作成する。
まず /var/run/kresd
を owner kresd で作成し、/usr/local/etc/rc.d/kresd
を次の内容で作成する。
#!/bin/sh # # PROVIDE: kresd # REQUIRE: SERVERS cleanvar # KEYWORD: shutdown # # Add the following lines to /etc/rc.conf to enable kresd: # # kresd_enable="YES" # optional: # kresd_config="/usr/local/etc/knot-resolver/kresd.conf" . /etc/rc.subr name=kresd rcvar=kresd_enable load_rc_config ${name} : ${kresd_enable:="NO"} : ${kresd_config:="/usr/local/etc/knot-resolver/kresd.conf"} : ${kresd_rundir:="/var/run/kresd"} command=/usr/sbin/daemon procname=/usr/local/sbin/${name} pidfile=/var/run/${name}/${name}.pid command_args="-fS -T ${name} -p ${pidfile} ${procname} -c ${kresd_config} -n ${kresd_rundir}" required_files=${kresd_config} run_rc_command "$1"
これであとは、/etc/rc.conf
に kresd_enable="YES"
を入れればよい。
現状
とりあえず、1週間は落ちることなしに動いた。 次は1ヶ月を越えて動き続けてくれるかである。
追記 (2020/06/23)
デフォルトの kresd.conf だとローカルホストからしか引けない。
さらに、現在の FreeBSD ports&packages の設定だと、更新時に kresd.conf を上書きする。
そういうわけで、設定ファイルを /usr/local/etc/knot-resolver/kresd-gate.conf
に用意する。
/etc/rc.conf
の記述は次のようになる。
kresd_enable="YES" kresd_config="/usr/local/etc/knot-resolver/kresd-gate.conf"
この kresd-gate.conf の記述については (knot-resolver のドキュメント)https://knot-resolver.readthedocs.io/en/stable/index.html を参考に書けばよいが、私の設定の概略は以下のような感じになる。
-- Network interface configuration -- 内部ネットワークは IPv4 -- 内部ネットワーク向けには DNS over TLS もサービスする net.listen('127.0.0.1', 53, { kind = 'dns' }) net.listen('192.0.2.1', 53, { kind = 'dns' }) net.listen('192.0.2.1', 853, { kind = 'tls' }) net.listen('::1', 53, { kind = 'dns', freebind = true }) net.outgoing_v6('2001:db8:a::1') net.outgoing_v4('192.0.2.1') home_trees = policy.todnames({ 'home.example.jp.', '2.0.192.in-addr.arpa.' }) policy.add(policy.suffix( -- DNSSEC の verification を行わないので、FORWARD ではなく STUB policy.STUB('192.0.2.53), home_trees )) policy.add(policy.all(policy.FORWARD({ '2001:db8:b:53', '198.51.100.53' }))) -- Load useful modules modules = { 'hints > iterate', -- Load /etc/hosts and allow custom root hints 'stats', -- Track internal statistics 'predict', -- Prefetch expiring/frequent records } -- ユーザ権限を root から一般ユーザーに落とす user('kresd', 'kresd') -- Cache size cache.size = 100 * MB