1. KnotDNS / Dnstap とは
KnotDNS は CZ-NIC 社によって開発された権威DNSサーバです.
Dnstap は パケットキャプチャを利用せずに高速にDNSクエリを取得出来る仕組み及びツールです.
KnotDNS はDNSクエリログを取得する機能を標準で持たないため, Dnstap を外部モジュールという形で呼び出す必要があります. Bind や Unbound では参考記事があったのですが, KnotDNS に関する記事は無かったので, 備忘録として残してみます.
2. 想定環境
- OS: Debian 9.3 (Stretch)
- Utilities (Main):
- Gcc: 6.3.0 20170516 (Debian 6.3.0-18+deb9u1)
- G++: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
- Fstrm: v0.4.0
- Protobuf: v3.5.2
- Protobuf-c: v1.3.0
- Golang: go1.10.3 linux/amd64
- Tools:
- KnotDNS: v2.6.8
- Dnstap: ? (Master Branch)
上記環境を構築していきます. 今回の作業は全て root ユーザで行います.
※ 但し, OSに関しては予め展開されている事を想定しています.
3. 環境構築
ビルド用ツールの展開
# apt install -y tar wget curl unzip git vim resolvconf
# apt install -y git-core make gcc g++ libtool \
autoconf pkg-config liburcu-dev liblmdb-dev \
libgnutls28-dev libedit-dev libidn11-dev libevent-dev
Fstrm の展開
# git clone -b v0.4.0 https://github.com/farsightsec/fstrm.git /opt/fstrm
# cd /opt/fstrm
# ./autogen.sh
# ./configure
# make
# make install
# ldconfig
Protobuf の展開
Protobuf 3.6.x はビルドエラーにより断念, 代替として v3.5.2 を利用した
# git clone -b v3.5.2 https://github.com/google/protobuf.git /opt/protobuf
# cd /opt/protobuf
# ./autogen.sh
# ./configure
# make
# make install
# ldconfig
Protobuf-c の展開
# git clone -b v1.3.0 https://github.com/protobuf-c/protobuf-c.git /opt/protobuf-c
# cd /opt/protobuf-c
# ./autogen.sh
# ./configure
# make
# make install
KnotDNS の展開
# git clone -b v2.6.8 https://gitlab.labs.nic.cz/knot/knot-dns.git /opt/knot
# cd /opt/knot
# autoreconf -if
# ./configure \
--sysconfdir=/etc
--localstatedir=/var/lib
--bindir=/usr/sbin
--libexecdir=/usr/sbin
--sbindir=/usr/sbin
--with-rundir=/var/run/knot
--with-storage=/var/lib/knot
--enable-dnstap
--with-module-dnstap=yes
--enable-fastparser
--enable-recvmmsg=yes
--disable-silent-rules
--disable-static
--disable-documentation
# make
# make install
# ldconfig
KnotDNS の Systemd 設定
# cat << EOS > /lib/systemd/system/knot.service
[Unit]
Description=Knot DNS server
Wants=network-online.target
After=network-online.target
[Service]
EnvironmentFile=/etc/default/knot
ExecReload=/usr/sbin/knotc reload
ExecStart=/usr/sbin/knotd $KNOTD_ARGS
Restart=on-abort
[Install]
WantedBy=multi-user.target
EOS
# systemctl daemon-reload
# systemctl status knot.service
Golang の展開
# wget https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz -P /tmp
# cd /tmp
# tar -zxvf go1.10.3.linux-amd64.tar.gz
# mv go /usr/local/bin
Golang の有効化
Golang におけるルートプロジェクトを /root/dnstap-golang
に設定していますが,
本番環境では適切なディレクトリに設定すべきです
# mkdir -p /root/dnstap-golang
# echo "export GOROOT=/usr/local/bin/go" >> ~/.bash_proifle
# echo "export GOPATH=/root/dnstap-golang" >> ~/.bash_profile
# echo "export PATH=$GOPATH/bin:$GOROOT/bin:$PATH" >> ~/.bash_profile
# source ~/.bash_profile
Dnstap の展開
# go get -u github.com/dnstap/golang-dnstap/dnstap
4. KnotDNS の初期起動及び設定
# knotc conf-init
# systemctl start knot.service
# systemctl status knot.service
5. KnotDNS への Dnstap の設定
現在の KnotDNS では静的な設定ファイルからの Dnstap モジュール読込が何故か出来ないようです.
なので, Dnstap 有効化の設定はCLI上から一つ一つ行う必要があります.
# knotc conf-begin
# knotc conf-set mod-dnstap.id capture_all
# knotc conf-set mod-dnstap.sink unix://var/run/knot/dnstap.sock
# knotc conf-set template.id default
# knotc conf-set template.global-module mode-dnstap/capture_all
# knotc conf-diff
# knotc conf-commit
# knotc reload
6. Dnstap の起動
dnstap を実行する事で, 以下のログを得る事が出来るはずです.
また, dnstap は何らかの方法 (Systemd, Supervisorctl) を利用して, BackGround で実行した方が良さそうです.
ちなみに, オプション -y
はデバッグモードでの起動を意味しています.
# dnstap -u /var/run/knot/dnstap.sock -w /var/log/dnstap.log -y
dnstap: opened input socket /var/run/knot/dnstap.sock
dnstap.FrameStreamSockInput: accepted a socket connection
7. DNSリクエストの送信
dnstap を維持した状態で下記コマンドを実行します.
レコード未登録の場合でも, クエリログは閲覧出来るため, 適当にDNSへリクエストを送信します
# kdig @localhost www.hogehoge.com
# kdig @localhost www.example.com
8. Dnstap でのクエリログの確認
mod-dnstap の標準オプションでは, リクエスト及びレスポンスの両方が出力されます.
# cat /var/log/dnstap.log
type: MESSAGE
identity: "stretch.localdomain"
version: "Knot DNS 2.6.8"
message:
type: AUTH_QUERY
query_time: !!timestamp 2018-07-16 08:46:37
socket_family: INET6
socket_protocol: UDP
query_address: ::1
query_port: 42718
query_message: |
;; opcode: QUERY, status: NOERROR, id: 1116
;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.example.com. IN A
---
type: MESSAGE
identity: "stretch.localdomain"
version: "Knot DNS 2.6.8"
message:
type: AUTH_RESPONSE
response_time: !!timestamp 2018-07-16 08:46:37
socket_family: INET6
socket_protocol: UDP
query_address: ::1
query_port: 42718
response_message: |
;; opcode: QUERY, status: REFUSED, id: 1116
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.example.com. IN A
---
type: MESSAGE
identity: "stretch.localdomain"
version: "Knot DNS 2.6.8"
message:
type: AUTH_QUERY
query_time: !!timestamp 2018-07-16 08:46:40
socket_family: INET6
socket_protocol: UDP
query_address: ::1
query_port: 35661
query_message: |
;; opcode: QUERY, status: NOERROR, id: 61958
;; flags: rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.hogehoge.com. IN A
---
type: MESSAGE
identity: "stretch.localdomain"
version: "Knot DNS 2.6.8"
message:
type: AUTH_RESPONSE
response_time: !!timestamp 2018-07-16 08:46:40
socket_family: INET6
socket_protocol: UDP
query_address: ::1
query_port: 35661
response_message: |
;; opcode: QUERY, status: REFUSED, id: 61958
;; flags: qr rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;www.hogehoge.com. IN A
---
9. おまけ
dnstap のオプションに -q
を付けると以下のようなクエリログ結果を出力する事が出来ます.
# cat /var/log/dnstap.log
08:51:13.000000 AQ ::1 UDP 34b "www.hogehoge.com." IN A
08:51:13.000000 AR ::1 UDP 34b "www.hogehoge.com." IN A
08:51:19.000000 AQ ::1 UDP 33b "www.example.com." IN A
08:51:19.000000 AR ::1 UDP 33b "www.example.com." IN A
10. 所感
- CLI 上で動的にゾーンを変更出来るのはとても良い (予め定義した設定ファイルを読み込む事も出来る)
- ネットワークデバイスへの設定を彷彿とさせるようなコマンドの使用感が良い
- ドキュメントに一通り設定方法が書かれているが, 内容が割とざっくりなので読み解く必要があるのは辛い
- レートリミットの設定や Any リクエストを無効化する方法など, DNSを介した攻撃への対策も一通りある (気がする)
- RestAPI とかあったら良かったかな... PowerDNS を使えと言われればそれまでだけど...