#author("2020-10-25T00:11:42+09:00","default:nowsky","nowsky")
*NSD [#qa4dbf83]
権威DNSに特化したサーバアプリケーションであり、オランダ企業とRIPE NCCの共同開発が行われている。
RFCに準拠した最低限の機能のみ実装している為、脆弱性が少なく堅牢で応答速度も早いのが特徴となる。
最低限の機能しか無い為、&color(#ff0000){DNSクエリを取得出来ない};欠点がある。
また、NSDをslaveとして構築した際にserialの比較を行わない[[ケース:+https://blog.akagi.jp/archives/4152.html]]がある。
 
DNSルートサーバでも採用されており、グローバルの稼働実績も多い。
BINDとNSDのハイブリッド構成を取って脆弱性対策をするケースも多い上、
BIND脱却としてオールNSD構成を取る日本企業も増えてきた。
#author("2020-10-25T01:31:30+09:00","default:nowsky","nowsky")
*Knot DNS [#x03b5c41]
チェコで開発している権威DNSサーバ用アプリケーション。
KルートDNSで利用されておりチューニング次第でNSD相当の応答速度が出る。
Knotの特長として、DNSSECのKSK/ZSKロールオーバーを自動化する&color(#ff0000){Online DNSSEC signing};機能がある。
~
*参考サイト [#t68206d0]
-[[NLnet Labs:+https://nlnetlabs.nl/]]
-[[NSD Documentation:+https://nlnetlabs.nl/documentation/nsd/]]
-[[日本Unboundユーザー会:+https://unbound.jp/nsd4/nsd-conf/]]
*参考サイト [#p413258d]
-[[Knot DNS:+https://www.knot-dns.cz/]]
-[[Knot Documentation:+https://www.knot-dns.cz/documentation/]]
-[[IIJ Engineers Blog:+https://eng-blog.iij.ad.jp/archives/5739]]
~
*構築環境 [#ue5d480a]
OSはCentOSを利用。普通は出来ないDNSクエリ取得を実現すべくパッチを適用する為、
ソースコードからビルドを実施している。
*構築環境 [#dafbb252]
OSはCentOSを利用。今回はバックエンドでDNSゾーンへのDNSSEC署名付与と、
KSKロールオーバー・ZSKロールオーバー専用機として構築する。
OS標準パッケージで対応していない機能があるのでソースビルドが必須となる。
- 共通環境
 OS    : CentOS 8.2.2004 x86_64
 NSD   : NSD v4.3.3
 user  : nsd
 group : nsd
 chroot: /var/nsd/chroot
 NSD   : Knot v3.0.0
 user  : knot
 group : knot
 data  : /var/knot/data
 listen: 127.0.0.1
 port  : 20053
~
*インストール [#j15e4b9c]
-&size(16){&font(b){0. ソース改変};};
NSDでDNSクエリを取得する事は出来ないが、
下記サイトで公開している独自パッチを適用する事でログ取得が可能となる。
サポート外となるが、ログ取得が必要な時はソースコードを変更した上でビルドする。
#region(&color(#ff0000){変更部分};)

-参考サイト
[[あ~ゆ~どりま~:+http://ayd.jp/p_blog/archive-201410/article-1413696054.html]]
[[どさにっき:+http://ya.maya.st/d/201305b.html#s20130517_2]]
 

-NSD v4.3.3
 [root@server nsd-4.3.3]# diff -up query.c query.c-4.3.3
 --- query.c             2020-10-08 16:14:25.000000000 +0900
 +++ query.c-4.3.3       2020-10-10 14:20:49.000000000 +0900
 @@ -1406,6 +1406,7 @@ query_process(query_type *q, nsd_type *n
         nsd_rc_type rc;
         query_state_type query_state;
         uint16_t arcount;
 +       char address[128];
  
         /* Sanity checks */
         if (buffer_limit(q->packet) < QHEADERSZ) {
 @@ -1543,6 +1544,19 @@ query_process(query_type *q, nsd_type *n
                 return QUERY_PROCESSED;
         }
  
 +       /* Query logging. */
 +       addr2str(&q->addr, address, sizeof(address));
 +       log_msg(LOG_INFO, "client %s: query %s %s %s %s%s%s%s%s",
 +               address,
 +               q->qname ? dname_to_string(q->qname, NULL) : "(null)",
 +               rrclass_to_string(q->qclass),
 +               rrtype_to_string(q->qtype),
 +               RD(q->packet) ? "+" : "-",
 +               q->edns.status == EDNS_OK ? "E" : "",
 +               q->tcp ? "T" : "",
 +               q->edns.dnssec_ok ? "D" : "",
 +               CD(q->packet) ? "C" : "");
 +
         query_prepare_response(q);
  
         if (q->qclass != CLASS_IN && q->qclass != CLASS_ANY) {
#endregion
~
*インストール [#k792398c]
-&size(16){&font(b){1. インストール};};
systemdを用いるOSを使っている場合、configure時にオプション指定する事でfork対応する事が出来る。
だが、NSDのconfigureスクリプトに相性があり、必要なパッケージがインストール済みなのにも関わらず、
未インストールと判定されるケースがある。
その場合はsystemd有効化オプションを無効化し、起動スクリプトをsimple判定にする事で対応する。
今回は相性問題が発生した為、CentOSを用いているがsystemdを無効化している。
 # dnf install libevent-devel
 # ./configure --prefix=/usr/local/nsd-4.3.3 --enable-pie \
     --enable-relro-now --enable-ratelimit-default-is-off \
     --disable-nsec3 --disable-radix-tree
KnotではGeoIPなど便利な機能が存在するが、
今回はDNSSEC専用のバックエンドとして構築するので不要な機能を無効化する。
 # dnf install gnutls-devel userspace-rcu-devel lmdb-devel libedit-devel
 # ./configure --prefix=/usr/local/knot-3.0.0 --disable-documentation         \
     --with-module-dnsproxy=no --with-module-geoip=no --with-module-dnstap=no \
     --with-module-whoami=no --with-module-synthrecord=no
 # make
 # make install
 # vi /usr/lib/systemd/system/nsd.service
 # cp -a knot-3.0.0/distro/common/knot.tmpfiles /usr/lib/tmpfiles.d/knot.conf
 # cp -a knot-3.0.0/distro/common/knot.service /usr/lib/systemd/system/knot.service
 # vi /usr/lib/systemd/system/knot.service
 ---
 [Unit]
 Description=Name Server Daemon
 After=network-online.target
 Description=Knot DNS server
 Wants=network-online.target
 After=network-online.target
 Documentation=man:knotd(8) man:knot.conf(5) man:knotc(8)
 
 [Service]
 Type=simple
 EnvironmentFile=-/etc/sysconfig/nsd
 ExecStartPre=/usr/local/nsd/sbin/nsd-checkconf /etc/nsd/nsd.conf
 ExecStart=/usr/local/nsd/sbin/nsd -d -c /etc/nsd/nsd.conf -t /var/nsd/chroot
 ExecReload=/usr/local/nsd/sbin/nsd-control -c /etc/nsd/nsd.conf reload
 ExecStop=/usr/local/nsd/sbin/nsd-control -c /etc/nsd/nsd.conf stop
 Type=notify
 PrivateTmp=false
 User=knot
 Group=knot
 EnvironmentFile=-/etc/sysconfig/knot
 ExecStartPre=/usr/local/knot/sbin/knotc -c /etc/knot.conf conf-check
 ExecStart=/usr/local/knot/sbin/knotd -c /etc/knot.conf $KNOTD_ARGS
 ExecReload=/usr/local/knot/sbin/knotc -c /etc/knot.conf reload
 ExecStop=/usr/local/knot/sbin/knotc -c /etc/knot.conf stop
 Restart=on-abort
 LimitNOFILE=1048576
 LimitNPROC=1048576
 
 [Install]
 WantedBy=multi-user.target
~
-&size(16){&font(b){2. ディレクトリ作成};};
NSDのデフォルト動作はchroot無しを想定しているので、chrootを含めた絶対パスで作成する。
リモート操作やローカルAPIを実行する為の公開鍵も作成し、chroot配下に配置する。
 # mkdir /var/nsd/chroot
 # mkdir /var/nsd/chroot/tmp
 # mkdir /var/nsd/chroot/etc/nsd
 # mkdir /var/nsd/chroot/var/log
 # mkdir /var/nsd/chroot/var/run
 # mkdir /var/nsd/chroot/var/db/nsd
自動署名を行う都合上、パーミッションを緩くしたディレクトリが必要となる。
ディレクトリを汚さない様にする為、chrootのディレクトリを作成しパスを変更する。
 # mkdir /var/knot/data
 # mkdir /var/knot/data/var/log
 # mkdir /var/knot/data/run/knot
 # mkdir /var/knot/data/lib/knot
 # mkdir /var/knot/data/lib/knot/signed
 
 # ln -s /usr/local/nsd-4.3.3 /usr/local/nsd
 # ln -s /var/nsd/chroot/etc/nsd /etc/nsd
 # ln -s /var/nsd/chroot/var/log /var/log/nsd
 # ln -s /usr/local/knot-3.0.0 /usr/local/knot
 # ln -s /usr/local/knot/etc/knot/knot.conf /etc/knot.conf
 # ln -s /var/knot/data/var/log /var/log/knot
 # mv /usr/local/knot/etc/knot/knot.sample.conf /usr/local/knot/etc/knot/knot.conf
 
 # groupadd nsd
 # useradd -g nsd -d /var/nsd -s /sbin/nologin nsd
 # chown -R nsd.nsd /var/nsd/chroot/tmp
 # chown -R nsd.nsd /var/nsd/chroot/var/run
 # chown -R nsd.nsd /var/nsd/chroot/var/log
 # groupadd knot
 # useradd -g knot -d /var/knot -s /sbin/nologin knot
 # chown -R knot.knot /var/knot/data/var/log
 # chown -R knot.knot /var/knot/data/run/knot
 # chown -R knot.knot /var/knot/data/lib/knot
 # chown -R knot.knot /var/knot/data/lib/knot/signed
 
 # /usr/local/nsd/sbin/nsd-control-setup
 # cp -a /usr/local/nsd/etc/nsd/* /var/nsd/chroot/etc/nsd/
 # vi /etc/logrotate.d/nsd
 # vi /etc/logrotate.d/knot
 ---
 /var/log/nsd/*.log {
     create 0644 nsd nsd
 /var/log/knot/*.log {
     create 0644 knot knot
     missingok
     sharedscripts
     postrotate
         systemctl restart nsd > /dev/null 2>/dev/null || true
         systemctl reload knot > /dev/null 2>/dev/null || true
     endscript
 }
~
-&size(16){&font(b){3. 設定ファイル};};
サンプルでは、example.comをDNSゾーンマスター、example.netをDNSゾーンスレーブとしている。
LISTEN-IPは実際にDNSクエリに応答するグローバルIPと、
ゾーン転送用のプライベートIP(クラスA)を書いている。
 # vi /etc/nsd/nsd.conf
 ---
コンフィグの元ネタは、&font(b){[[IIJ Engineers Blog:+https://eng-blog.iij.ad.jp/archives/5739]]};を参照。
DNSゾーン編集用のローカルDNSサーバ(127.0.0.1:10053)からDNSゾーンを受け取り、
KnotでDNSSEC署名を施した物を、フロントエンドのDNSサーバ(127.0.0.1:53)にゾーン転送させる。
また、サブミッション設定を行い上位の権威DSNにDSレコードが追加されたかを自動判定させる。
サブミッション確認用キャッシュDNSはプロバイダの物などを設定する。
 
#region(&color(#ff0000){サンプル};)
 ## Knot DNS Config
 ##
 ## Copyright (C) 2001-2020, NLnet Labs. All rights reserved.
 ##
 ## See LICENSE for the license.
 ##
 server:
     server-count: 1
     ip-address: 192.168.0.1
     ip-address: 203.0.113.1
     ip-address: 2001:db8::203:0:113:1
     port: 53
     version: "unknown"
     rundir:  "/var/knot/data/run/knot"
     user:    knot:knot
     listen:  127.0.0.1@20053
 
     username: nsd
     chroot: "/var/nsd/chroot"
     zonesdir: "/var/nsd/chroot/etc/nsd"
     zonelistfile: "/var/nsd/chroot/var/db/nsd/zone.list"
     database: "/var/nsd/chroot/var/db/nsd/nsd.db"
     logfile: "/var/nsd/chroot/var/log/nsd.log"
     pidfile: "/var/nsd/chroot/var/run/nsd.pid"
     xfrdfile: "/var/nsd/chroot/var/db/nsd/xfrd.state"
     xfrdir: "/var/nsd/chroot/tmp"
 database:
     storage: "/var/knot/data/lib/knot"
 
     version: "unknown"
     identity: "unknown"
     hide-version: yes
     hide-identity: yes
 log:
   - target: "/var/knot/data/var/log/knot.log"
     any:    info
 
 remote:
   - id:      backend
     address: 127.0.0.1@10053
   - id:      frontend
     address: 127.0.0.1@53
   - id:      resolv
     address: [ 8.8.8.8, 8.8.4.4 ]
 
 remote-control:
     control-enable: yes
     control-interface: 127.0.0.1
     control-port: 8952
     server-key-file: "/var/nsd/chroot/etc/nsd/nsd_server.key"
     server-cert-file: "/var/nsd/chroot/etc/nsd/nsd_server.pem"
     control-key-file: "/var/nsd/chroot/etc/nsd/nsd_control.key"
     control-cert-file: "/var/nsd/chroot/etc/nsd/nsd_control.pem"
 acl:
   - id:      acl_backend
     address: 127.0.0.1
     action:  notify
   - id:      acl_frontend
     address: 127.0.0.1
     action:  transfer
 
 submission:
   - id:     sub_resolv
     parent: resolv
 
  zone:
     name: "example.com"
     zonefile: "master/example.com"
     # notify: 192.168.0.3@53 NOKEY
     # notify-retry: 5
     # provide-xfr: 53 NOKEY
 policy:
   - id:             nsec3
     algorithm:      ecdsap256sha256
     nsec3:          on
     ksk-submission: sub_resolv
 
 template:
   - id:      default
     master:  backend
     notify:  frontend
     storage: "/var/knot/data/lib/knot/signed"
     acl:     [ acl_backend, acl_frontend ]
     dnssec-signing: on
     dnssec-policy:  nsec3
 
 zone:
     name: "example.net"
     zonefile: "slave/example.net"
     allow-notify: 192.168.0.2 NOKEY
     request-xfr: 192.168.0.2@53 NOKEY
     allow-axfr-fallback: yes
     # outgoing-interface: 192.168.0.1
   - domain: example.com
     file:   "example.com.zone"
#endregion
~
-&size(16){&font(b){4. 動作確認};};
NSDを実際に起動させて動作確認を行う。
今回はDNSクエリログ出力パッチを適用している為、BINDの様なDNSクエリログも出力される。
 # systemctl enable nsd
 # systemctl start nsd
 # cat /var/log/nsd.log
*DNSSEC署名 [#oe95ebd1]
DNSSEC鍵が無くなると、&color(#ff0000){一度DNSSECを解除して"Chain of Trust"を解除する必要};が出てくる。
この事態を避ける為に"storage"で指定したディレクトリを定期的にバックアップする必要がある。
Knotを起動すると『notice: [example.com.] DNSSEC, KSK submission, waiting for confirmation』と表示される。
コレが表示された後に"keymgr"コマンドを打つ事で、上位権威DNSに登録するDSレコードを確認出来る。
 # /usr/local/knot/sbin/keymgr -c /etc/knot.conf example.com ds
 ---
 [2020-10-XX 13:48:52.753] nsd[100080]: notice: nsd starting (NSD 4.3.3)
 [2020-10-XX 13:48:52.813] nsd[100081]: notice: nsd started (NSD 4.3.3), pid 100080
 [2020-10-XX 13:49:51.041] nsd[100083]: info: client 192.168.0.1: query example.com. IN A +E
 example.com. DS 28302 13 2 XXXXX
 example.com. DS 28302 13 4 XXXXX

keymgrで確認したDSレコードを、&color(#ff0000){VALUE-DOMAINやゴンベエドメイン等のDSレコード対応レジストラ経由で登録する。};
 
DSレコード登録方法はレジストラによって変わるので、ドキュメントを確認するか問い合わせる。
VALUE-DOMAINを使っている場合、DSレコード登録に対応しているccTLD/gTLDならば、
ネームサーバ設定欄に次の様なDNSSEC署名鍵設定が表示されるようになる。
&ref(dnssec-vd.png,left,nowrap,50%);
 
サブミッション設定をしている場合、定期的にDSレコードを確認し自動的にDNSSEC署名が行われる。
手動でDNSSEC署名を開始する場合、DSレコードが上位権威DNSに登録されている事を確認した上で、
次のコマンドを打ち込むと署名を開始出来る。
 # /usr/local/knot/sbin/knotc -c /etc/knot.conf zone-ksk-submitted example.com