はじめに
LAN内にキャッシュDNSサーバーを作るのにかんたん・はやい・あんぜんなunboundを選択しました。
unboundをdnfでインストールして最適化しようとしたところ、libeventを使わないとスレッドの制限がある…というのを見たのでソースインストールしてみました。
参考資料
Unboundの最適化(unbound.jp)
最適化の方法(unbound.jp)
環境
CentOS Linux release 8.0.1905 (Core)
unbound 1.9.4
# cd /usr/local/src
# mkdir unbound
# cd !:1
# wget https://github.com/NLnetLabs/unbound/archive/release-1.9.6.tar.gz
# tar xf release-1.9.6.tar.gz
# chown -R root. unbound-release-1.9.6
# cd !:3
展開した中身の確認
LICENSE aclocal.m4 compat configure.ac dnstap ipset pythonmod systemd.m4 winrc
Makefile.in acx_nlnetlabs.m4 config.guess contrib doc iterator respip testcode
README acx_python.m4 config.h.in daemon edns-subnet libunbound services testdata
README.md ax_pthread.m4 config.sub dns64 install-sh ltmain.sh sldns util
ac_pkg_swig.m4 cachedb configure dnscrypt ipsecmod makedist.sh smallapp validator
コンフィグの確認
configureオプションを見ていきます。
prefixなど設定するものと、パフォーマンスに影響しそうなものをピックアップしていきます。
--prefix=PREFIX
インストール先。
--enable-systemd
systemdで監理できるようになります。
--disable-sha1
Disable SHA1 RRSIG support,
does not disable nsec3 support
DNSSECのRRset(各FQDN)に使われる署名のアルゴリズムで、SHA1を使わないようにする(その場合はDNSSECの連鎖が止まる?)もの。
sha1をセキュリティ強度が下がっているということなので、無効にしたほうが良さそうです。
不在証明で使われるnsec3のリソースレコードのハッシュで使われるSHA1は無効にしないもののようです。
RRSIGリソースレコード(jprs.jp)
DNESSECの基礎概要(nic.ad.jp)
が、SHA1も多いよう(2017年末現在)なので、無効化するのはやめておいたほうが良さそうです。
世界と日本のDNSSEC(www.slideshare.net/IIJ_PR)
--enable-subnet
EDNSを有効にする設定のようです。
EDNS Client Subnetとは(nic.ad.jp)
--disable-gost
GOST署名なるものあるようですが、ほとんど記事がなくなんのことだかわかりません。
GOSTにも 94と2012があるようです。
Use of GOST Signature Algorithms in DNSKEY and RRSIG Resource Records for DNSSEC(tools.ietf.org)
GOST (hash function)(en.wikipedia.org)
古いOpenSSLを使うようなときに設定するもののようです。
Unboundの紹介(unbound.jp)
--disable-ed448
そうなるとSHA3のED448もOPENSSLに対応していないので無効化する必要があるかもしれません。
# openssl version
OpenSSL 1.1.1 FIPS 11 Sep 2018
# openssl genpkey -algorithm ed448
-----BEGIN PRIVATE KEY-----
MEcCAQAwBQYDK2VxBDsEOboQuO93oGq4RioFUosg3GUWNGQOZW2u7t1Jm7G0CSDp
swrd/ZXXLwGV190JYfPv+fpffkgMG3mP6g==
-----END PRIVATE KEY-----
組み込みのOpenSSLでも使えました。無効化する必要はありません。
--enable-fully-static
enable to compile fully static
静的にコンパイルしてくれます。
実行速度は速くなりそうです。
--enable-cachedb
キャッシュスdbモジュールを外部のキャッシュストレージを使って有効にする。
[Unbound][redis][自分用メモ] Unboundでbackendにredisを利用できることを今さらながら知った(blog.komeho.info)
のちのwith-libhiredisをつかえるようです
--with-libevent=pathname
本命です。
--with-libexpat=path
Unboundの紹介では、1.4.7移行で必要になるとあります。
--with-libhiredis=path
hiredisを追加します。
ライブラリのインストール
libevent
dnf install -y libevent libevent-devel
libexpat
dnf install -y expat expat-devel
libhiredis
epelにあるようなので、epelリポジトリを追加します。
https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/e/
最新は epel-release-8-7.el8.noarch.rpm でした。
cd /usr/local/src
dnf install -y https://dl.fedoraproject.org/pub/epel/8/Everything/x86_64/Packages/e/epel-release-8-7.el8.noarch.rpm
dnf install -y hiredis hiredis-devel
Configureまとめ
./configure \
--prefix=/usr/local/unbound-1.9.4 \
--enable-systemd \
--enable-fully-static \
--enable-cachedb \
--with-libexpat \
--with-libhiredis
configureを実行します。
configure: error: systemd enabled but libsystemd not found
systemd-develを入れてみます。
dnf install -y systemd-devel
checking for SSL... configure: error: Cannot find the SSL libraries in /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr
Opensslのライブラリがないそうです。
入れます。
dnf install make gcc perl git expat-devel pcre-devel zlib-devel lksctp-tools lksctp-tools-devel kernel-modules-extra -y
cd /usr/local/src ; wget https://www.openssl.org/source/openssl-1.1.1d.tar.gz
tar xf openssl-1.1.1d.tar.gz
chown -R root. openssl-1.1.1d ; cd openssl-1.1.1d
./config --prefix=/usr/local/openssl-1.1.1d --openssldir=/usr/local/openssl-1.1.1d/shared enable-md2 enable-rc5 sctp zlib -fPIC
make -j3 && make install
cd /usr/local ; ln -s openssl-1.1.1d openssl
echo -e "/usr/local/openssl/lib" > /etc/ld.so.conf.d/openssl-1.1.1d.conf
echo -e 'OPENSSL_111D_PATH=/usr/local/openssl/bin\nPATH=$OPENSSL_111D_PATH:$PATH\nexport PATH' > /etc/profile.d/openssl-1.1.1d.sh
source /etc/profile.d/openssl-1.1.1d.sh ; ldconfig
opensslのパスを追加して、unboundのconfigureを通します。
./configure \
--prefix=/usr/local/unbound-1.9.4 \
--enable-systemd \
--enable-fully-static \
--enable-cachedb \
--with-ssl=/usr/local/openssl \
--with-libexpat \
--with-libhiredis
checking for libexpat... configure: error: Could not find libexpat, expat.h
libexpatが見つからないと怒られました。
しかしインストール済みです。
Package expat-2.2.5-3.el8.x86_64 is already installed.
Package expat-devel-2.2.5-3.el8.x86_64 is already installed.
# ls -la /usr/include/expat*
-rw-r--r-- 1 root root 43512 5月 11 2019 /usr/include/expat.h
-rw-r--r-- 1 root root 3517 5月 11 2019 /usr/include/expat_config.h
-rw-r--r-- 1 root root 5532 5月 11 2019 /usr/include/expat_external.h
.configureを見てみます。
19377 # check for libexpat
19378
19379 # Check whether --with-libexpat was given.
19380 if test "${with_libexpat+set}" = set; then :
19381 withval=$with_libexpat;
pathの指定ありなしで挙動が変わるようです。
19382 else
19383 withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
19384 fi
指定がないと、上記のディレクトリが検索対象になりそうな感じです。
19386 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libexpat" >&5
19387 $as_echo_n "checking for libexpat... " >&6; }
19388 found_libexpat="no"
19389 for dir in $withval ; do
19390 if test -f "$dir/include/expat.h"; then
19391 found_libexpat="yes"
19392 if test "$dir" != "/usr"; then
19393 CPPFLAGS="$CPPFLAGS -I$dir/include"
19394 LDFLAGS="$LDFLAGS -L$dir/lib"
19395 fi
19396 { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
19397 $as_echo "found in $dir" >&6; }
19398 break;
19399 fi
19400 done
--with-libexpat
で configureすると、 1回目の$dirには yes
が入っていました。
yes/include/expat.hは見つからないわけです。
libexpatのpathに/usrを指定してみます。
$dirに無事 /usr
が入りました。
チェックも通りました。
checking for expat.h... yes
hiredisも問題ないようです。
checking for libhiredis... found in /usr
checking for hiredis/hiredis.h... yes
通ったconfigureオプション
./configure \
--prefix=/usr/local/unbound-1.9.4 \
--enable-systemd \
--enable-fully-static \
--enable-cachedb \
--with-ssl=/usr/local/openssl \
--with-libexpat=/usr \
--with-libhiredis
libtool: warning: complete static linking is impossible in this configuration
libtool: link: gcc -I. -I/usr/local/openssl/include -DSRCDIR=. -g -O2 -flto -pthread -o unbound-host .libs/unbound-host.o .libs/keyraw.o .libs/sbuffer.o .libs/wire2str.o .libs/parse.o .libs/parseutil.o .libs/rrdef.o .libs/str2wire.o .libs/strlcat.o .libs/strlcpy.o -L/usr/local/openssl/lib -L. -L.libs /usr/local/src/unbound/unbound-release-1.9.6/.libs/libunbound.a -lssl -lsystemd -lcrypto -lhiredis -pthread -Wl,-rpath -Wl,/usr/local/openssl/lib
/usr/bin/ld: Dwarf Error: Could not find abbrev number 4628.
/tmp/ccoIVbCd.ltrans0.ltrans.o: In function `check_ub_res.part.0':
<artificial>:(.text+0x42f5): undefined reference to `ub_strerror'
/tmp/ccoIVbCd.ltrans0.ltrans.o: In function `dnslook':
<artificial>:(.text+0x4524): undefined reference to `ub_resolve'
<artificial>:(.text+0x4973): undefined reference to `ub_resolve_free'
<artificial>:(.text+0x4aa3): undefined reference to `ub_strerror'
/tmp/ccoIVbCd.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x20): undefined reference to `ub_ctx_create'
<artificial>:(.text.startup+0x42): undefined reference to `ub_ctx_set_option'
<artificial>:(.text.startup+0x9e): undefined reference to `ub_ctx_add_ta'
<artificial>:(.text.startup+0xdb): undefined reference to `ub_ctx_resolvconf'
<artificial>:(.text.startup+0xfe): undefined reference to `ub_ctx_add_ta_file'
<artificial>:(.text.startup+0x15e): undefined reference to `ub_ctx_trustedkeys'
<artificial>:(.text.startup+0x17b): undefined reference to `ub_ctx_add_ta_file'
<artificial>:(.text.startup+0x19e): undefined reference to `ub_ctx_config'
<artificial>:(.text.startup+0x1c2): undefined reference to `ub_ctx_set_option'
<artificial>:(.text.startup+0x1f2): undefined reference to `ub_ctx_set_option'
<artificial>:(.text.startup+0x21c): undefined reference to `ub_ctx_debuglevel'
<artificial>:(.text.startup+0x238): undefined reference to `ub_ctx_get_option'
<artificial>:(.text.startup+0x26a): undefined reference to `ub_ctx_set_option'
<artificial>:(.text.startup+0x4e8): undefined reference to `ub_ctx_delete'
collect2: error: ld returned 1 exit status
make: *** [Makefile:339: unbound-host] エラー 1
おや…
undefined reference to `ub_resolve'
で検索するとそれっぽいのが出てきました。
Unbound configuration --enable-static-exe breaks linker #3(github.com)
--disable-flto
をconfigureで入れろとのことです。
./configure \
--prefix=/usr/local/unbound-1.9.4 \
--disable-flto \
--enable-systemd \
--enable-fully-static \
--enable-cachedb \
--with-ssl=/usr/local/openssl \
--with-libexpat=/usr \
--with-libhiredis
通りました。
make test
(略)
./testdata/version_bind.rpl OK
./testdata/version_bind_hide.rpl OK
./testdata/views.rpl OK
test OK
通っています。
# make install
(略)
# echo $?
0
インストールされました。
起動スクリプトをdnfで入れたものをコピーします。
元のスクリプト
cat /usr/lib/systemd/system/unbound-anchor.service
[Unit]
Description=Unbound recursive Domain Name Server
After=network.target
After=unbound-keygen.service
Wants=unbound-keygen.service
Wants=unbound-anchor.timer
Before=nss-lookup.target
Wants=nss-lookup.target
[Service]
Type=simple
EnvironmentFile=-/etc/sysconfig/unbound
ExecStartPre=/usr/sbin/unbound-checkconf
ExecStartPre=-/usr/sbin/unbound-anchor -a /var/lib/unbound/root.key -c /etc/unbound/icannbundle.pem -f /etc/resolv.conf -R
ExecStart=/usr/sbin/unbound -d $UNBOUND_OPTIONS
ExecReload=/usr/sbin/unbound-control reload
[Install]
WantedBy=multi-user.target
修正したもの
[Unit]
Description=Unbound recursive Domain Name Server
After=network.target
#After=unbound-keygen.service
#Wants=unbound-keygen.service
#Wants=unbound-anchor.timer
Before=nss-lookup.target
Wants=nss-lookup.target
[Service]
Type=simple
#EnvironmentFile=-/etc/sysconfig/unbound
ExecStartPre=/usr/local/unbound-1.9.4/sbin/unbound-checkconf
#ExecStartPre=-/usr/sbin/unbound-anchor -a /var/lib/unbound/root.key -c /etc/unbound/icannbundle.pem -f /etc/resolv.conf -R
ExecStart=/usr/local/unbound-1.9.4/sbin/unbound -d $UNBOUND_OPTIONS
ExecReload=/usr/local/unbound-1.9.4/sbin/unbound-control reload
[Install]
WantedBy=multi-user.target
confファイルはほとんど設定されていないので、ローカルから引けるようにします。
access-control: 0.0.0.0/0 refuse
access-control: 127.0.0.0/8 allow
do-not-query-localhost: no
スタートします。
# systemctl start unbound
# systemctl status unbound
● unbound.service - Unbound recursive Domain Name Server
Loaded: loaded (/usr/lib/systemd/system/unbound.service; disabled; vendor preset: disabled)
Active: active (running) since Fri 2019-12-20 13:29:59 JST; 18s ago
Process: 13455 ExecStartPre=/usr/local/unbound-1.9.4/sbin/unbound-checkconf (code=exited, status=0/SUCCESS)
Main PID: 13458 (unbound)
Tasks: 1 (limit: 26213)
Memory: 3.5M
CGroup: /system.slice/unbound.service
└─13458 /usr/local/unbound-1.9.4/sbin/unbound -d
12月 20 13:29:59 unbound systemd[1]: Starting Unbound recursive Domain Name Server...
12月 20 13:29:59 unbound unbound-checkconf[13455]: unbound-checkconf: no errors in /usr/local/unbound-1.9.4/etc/unbound/unbound>
12月 20 13:29:59 unbound systemd[1]: Started Unbound recursive Domain Name Server.
12月 20 13:29:59 unbound unbound[13458]: [13458:0] notice: init module 0: validator
12月 20 13:29:59 unbound unbound[13458]: [13458:0] notice: init module 1: iterator
12月 20 13:29:59 unbound unbound[13458]: [13458:0] info: start of service (unbound 1.9.6).
# dig google.com @localhost
; <<>> DiG 9.11.4-P2-RedHat-9.11.4-17.P2.el8_0.1 <<>> google.com @localhost
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48229
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;google.com. IN A
;; ANSWER SECTION:
google.com. 300 IN A 216.58.197.174
;; Query time: 86 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: 金 12月 20 13:31:24 JST 2019
;; MSG SIZE rcvd: 55
引けました。
最適化の設定を入れてみます。
# some optimisation options.
server:
# use all CPUs
num-threads: 4
# power of 2 close to num-threads
msg-cache-slabs: 4
rrset-cache-slabs: 4
infra-cache-slabs: 4
key-cache-slabs: 4
# more cache memory, rrset=msg*2
rrset-cache-size: 100m
msg-cache-size: 50m
# more outgoing connections
# depends on number of cores: 1024/cores - 50
outgoing-range: 950
# Larger socket buffer. OS may need config.
so-rcvbuf: 4m
こちらも問題なく動くようです。
負荷テストをしてみます。
参考
フリーのDNSストレスツール の紹介(dnsops.jp)
# wget ftp://ftp.isc.org/isc/bind9/9.9.3-P1/bind-9.9.3-P1.tar.gz
# tar xf bind-9.9.3-P1.tar.gz
# cp bind-9.9.3-P1/lib/isc/include/isc/hmacsha.h /usr/include/isc
dnf install bind-devel openssl-devel libcap-devel libxml2-devel -y
cd /usr/local/src
wget https://www.dns-oarc.net/files/dnsperf/dnsperf-2.3.2.tar.gz
tar xf dnsperf-2.3.2.tar.gz
chown -R root. dnsperf-2.3.2
cd !:3
./configure --prefix=/usr/local/dnsperf-2.3.2
(略)
configure: error: BIND 9 libraries must be installed
注)↑は修正済みのコマンドです
さくっといかないものです。
bindのdevelをインストールします。
dnf install bind-devel -y
参考資料
DNSに負荷をかけるテスト(kinneko.hatenadiary.org)
またひっかかります。
configure: error: Package requirements (libssl) were not met:
Package 'libssl', required by 'virtual:world', not found
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
Alternatively, you may set the environment variables libssl_CFLAGS
and libssl_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.
いろいろ調べましたが、こういう設定が必要なようです。
libssl detection fails late on macos sierra #246(github.com)
./configure libssl_LIBS=-I/usr/local/openssl/lib libssl_CFLAGS=-I/usr/local/openssl/include/openssl --prefix=/usr/local/dnsperf-2.3.2
Making all in src
make[1]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' に入ります
make all-recursive
make[2]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' に入ります
make[3]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' に入ります
depbase=`echo datafile.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
gcc -DHAVE_CONFIG_H -I. -I. -I.. -pthread -I/usr/local/openssl/include/openssl -g -O2 -I/usr/include/bind9 -D_REENTRANT -I/builddir/build/BUILD/bind-9.11.4-P2/build/unit/atf/include -DDIG_SIGCHASE -D_GNU_SOURCE -MT datafile.o -MD -MP -MF $depbase.Tpo -c -o datafile.o datafile.c &&\
mv -f $depbase.Tpo $depbase.Po
In file included from os.h:20,
from datafile.c:34:
net.h:25:10: 致命的エラー: openssl/ssl.h: そのようなファイルやディレクトリはありません
#include <openssl/ssl.h>
^~~~~~~~~~~~~~~
コンパイルを停止しました。
make[3]: *** [Makefile:588: datafile.o] エラー 1
make[3]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' から出ます
make[2]: *** [Makefile:665: all-recursive] エラー 1
make[2]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' から出ます
make[1]: *** [Makefile:431: all] エラー 2
make[1]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' から出ます
make: *** [Makefile:465: all-recursive] エラー 1
検索していくと ubuntuならlibssl-devを入れろ!というものばかりでしたが、
openssl-develを入れたらすんなり通りました。
/usr/bin/ld: cannot find -lcap
/usr/bin/ld: cannot find -lxml2
/usr/bin/ld: cannot find -llzma
collect2: error: ld returned 1 exit status
make[3]: *** [Makefile:531: dnsperf] エラー 1
make[3]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' から出ます
make[2]: *** [Makefile:665: all-recursive] エラー 1
make[2]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' から出ます
make[1]: *** [Makefile:431: all] エラー 2
make[1]: ディレクトリ '/usr/local/src/dnsperf-2.3.2/src' から出ます
make: *** [Makefile:465: all-recursive] エラー 1
必要なものをインストールします。
dnf install libcap-devel libxml2-devel
無事、コンパイルが通りインストールができました。
テストしてみます。
cd /usr/local/dnsperf-2.3.2/bin
wget ftp://ftp.nominum.com/pub/nominum/dnsperf/data/queryfile-example-current.gz
gzip -d queryfile-example-current.gz
./resperf -s localhost -d queryfile-example-current
Statistics:
Queries sent: 102765
Queries completed: 40394
Queries lost: 62371
Response codes: NOERROR 27710 (68.60%), SERVFAIL 33 (0.08%), NXDOMAIN 12651 (31.32%)
Run time (s): 56.104757
Maximum throughput: 6306.000000 qps
Lost at that point: 64.81%
ソースインストールてチューニングしたほうが、DNFでそのまま入れたunboundより4、5倍以上Maximum Throughputが出ていました。
おまけ
dnfでインストールしたプログラムも、libeventを読み込んでいるようです。
# which unbound
/usr/sbin/unbound
# ldd /usr/sbin/unbound
linux-vdso.so.1 (0x00007ffd210dd000)
libssl.so.1.1 => /lib64/libssl.so.1.1 (0x00007f77aa103000)
libevent-2.1.so.6 => /lib64/libevent-2.1.so.6 (0x00007f77a9eaa000)
libpython3.6m.so.1.0 => /lib64/libpython3.6m.so.1.0 (0x00007f77a9952000)
libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007f77a947a000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f77a925a000)
libc.so.6 => /lib64/libc.so.6 (0x00007f77a8e96000)
libz.so.1 => /lib64/libz.so.1 (0x00007f77a8c7f000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f77a8a7b000)
libutil.so.1 => /lib64/libutil.so.1 (0x00007f77a8877000)
libm.so.6 => /lib64/libm.so.6 (0x00007f77a84f5000)
/lib64/ld-linux-x86-64.so.2 (0x00007f77aa6d7000)
が、/usr/sbin/unboundをエディタで見ると
too many file descriptors requested.
The builtinmini-event cannot handle more than 1024.
Config for less fds or compile with libevent
こんな記述がありました。やはりソースで入れないと有効にならなさそうです。