「俺様サーバー構築記 - 基本方針」に基づく作業の続き。LTS版Linuxカーネルの使用を決心してから、私の手持ちで生きているマシンをすべてフォーマットし直しました。
その中で、家庭内サーバ用の古いデスクトップマシンに対し、家庭内DNSサーバを構築します。
数年前に、Bindを使って似たような事をやったんですが。私なりにちょっと勉強しまして、今回は軽量で簡単と名高いUnboundを使ってみます。
参考文献1: 自宅サーバを立てる際の家庭内名前解決の落とし穴
参考文献2: Unbound,知ってる? この先10年を見据えたDNS 第2回 Unboundの導入(新規導入編)
準備
事前にアップデート。
# zfs snapshot tank/main@$(date +%Y%m%d_%H%M%S)_before_update
# zfs list -t snapshot -S name | head -n2
NAME USED AVAIL REFER MOUNTPOINT
tank/main@20200813_164238_before_update 111K - 1.78G -
# pacman -Syu --noprogessbar --noconfirm
アップデートが完了したら、インストール前にスナップショットを撮りましょう。
# zfs snapshot tank/main@$(date +%Y%m%d_%H%M%S)_before_Unbound
# zfs list -t snapshot -S name | head -n2
NAME USED AVAIL REFER MOUNTPOINT
tank/main@20200813_165104_before_Unbound 0B - 2.02G -
起動
インストール
参考文献: Unbound - ArchWiki
今回は、DNSSECはしません。本当はやっといた方がいいんでしょうけども。
# pacman -S unbound --noprogressbar --noconfirm
インストールできたら、/etc
をバージョン管理します。
# cd /etc
# svn st
M group
M gshadow
M ld.so.cache
M passwd
M shadow
? trusted-key.key
? unbound
# svn add trusted-key.key unbound
A trusted-key.key
A unbound
A unbound/trusted-key.key
A unbound/unbound.conf
# svn ci -m"installed Unbound"
drill コマンド
ちなみに、unboundをインストールすると、drill
というコマンドも同時にインストールされます。
# drill -v | head -n2
drill version 1.7.1 (ldns version 1.7.1)
Written by NLnet Labs.
こいつはDNSの名前解決をするコマンドだそうです。キャッシュDNSサーバのIPアドレスを指定しなければならないのですが、OSインストール時のネットワーク設定の設定により、systemd-resolvedが127.0.0.53で待ち受けています。127.0.0.1じゃないんですよね。どうしてこんな変な設定になっているのか理解に苦しみます。正確にはlocalhostは127.0.0.0/8なので、RFC的には正しいんですけども… systemdのこういう所が私は嫌(以下略)
参考文献: 2.1 DNS - 2 設定 - systemd-resolved - ArchWiki
# grep nameserver /run/systemd/resolve/stub-resolv.conf
nameserver 127.0.0.53
# drill archlinux.jp @127.0.0.53
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 18649
;; flags: qr rd ra ; QYERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; archlinux.jp. IN A
;; ANSWER SECTION:
archlinux.jp. 2559 IN A 160.16.119.98
;; AUTHORITY SECTION:
;; Query time: 0 msec
;; SERVER: 127.0.0.53
;; WHEN: Fri Aug 14 14:51:28 2020
;; MSG SIZE rcvd: 46
設定
systemd-resolved
上述の通り、OSインストール時のネットワーク設定の設定によって、現在はsystemd-resolved
が名前解決してます。まずはこれを修正します。
参考文献: systemd-resolved - ArchWiki
DNSサーバの設定と共に、ついでにDomainsもhomeに設定しときましょう。corpでも何でも構いませんが、一応localは避けておきたいですね。っていうかlocalじゃなくてhomeも望ましくはないですかね?
LAN内だけで解決するドメイン名であって非公開ならhomeでいいんじゃないかと思ってますが、正式には、きちんと自分ドメインを買うのが正しいですな。特に会社その他公的組織の場合は予算を組みましょう。個人だと財布が気になりますが(個人的には月に缶ジュース1~2本分くらい払えよって考えてますが)、会社なら気にしたら負けって位の安値です。
参考文献: Mac が参加するADのドメイン名で .local を使わないでください。
参考文献: TLDにおける名前衝突 (Name Collision)問題
# sed -i -e"/^#DNS=/c DNS=127.0.0.1" -e"/^#Domains=/c Domains=home" /etc/systemd/resolved.conf
# sed -i -e"/^DNS=/c DNS=127.0.0.1" /etc/systemd/network/*.network
書き換えの確認:
# svn up /etc
Updating '.':
At revision 5.
# svn di --diff-cmd diff -x -U0 /etc
Index: /etc/systemd/network/enp0s25.network
==================================================================
--- /etc/systemd/network/enp0s25.network (revision 5)
--- /etc/systemd/network/enp0s25.network (working copy)
@@ -7 +7 @@
-DNS=172.16.0.1
+DNS=127.0.0.1
Index: /etc/systemd/network/enp2s1.network
==================================================================
--- /etc/systemd/network/enp2s1.network (revision 5)
+++ /etc/systemd/network/enp2s1.network (working copy)
@@ -7 +7 @@
-DNS=172.16.0.1
+DNS=127.0.0.1
Index: /etc/systemd/resolved.conf
==================================================================
--- /etc/systemd/resolved.conf (revision 5)
+++ /etc/systemd/resolved.conf (working copy)
@@ -15 +15 @@
-#DNS=
+DNS=127.0.0.1
@@ -17 +17 @@
-#Domains=
+Domains=home
Unbound
ArchWikiには下記のように書いてあるんですがね…
サンプル設定ファイルが /etc/unbound/unbound.conf.example に存在します。
ありませんね~サンプルファイル。
# cd /etc/unbound
# ls
trusted-key.key unbound.conf
という訳で、デフォルト設定もちょっと心配なので、念の為中身を見ておきます。
# grep -vE "#|^$" unbound.conf
server:
verbosity: 1
trust-anchor-file: /etc/unbound/trusted-key.key
python:
dynlib:
remote-control:
ほとんど何も書かれていません。Unboundはデフォルト設定そのままでも実用に耐えるらしいので、OKと考えましょう。
今回は、下記のように修正しました。
待ち受けるIPアドレスは、外部からの問い合わせも全部受けるなら0.0.0.0
を指定するのが一般的だと思うのですが。systemd-resolved
と衝突して色々面倒です… このサーバマシンのIPアドレスは172.16.0.3
で固定にしたので、それを指定します。
ルートヒントは、世界的に使用されているグローバル標準 https://www.internic.net/domain/named.cache がある訳ですが。家庭内LANなので、プロバイダが指定してくる物を上位DNSとすれば十分かなと。という訳で、ルートヒントは家庭内LANのルータ172.16.0.1
を指定するだけのファイルを用意しました。定期的な更新なんかも不要ですしね。
# cd /etc/unbound
# vi unbound.cond
〈編集内容は下記を参照〉
# grep -vE "#|^$" unbound.conf
server:
verbosity: 1
interface: 172.16.0.3
interface: 127.0.0.1
access-control: 172.16.0.0/16 allow
root-hints: "/etc/unbound/parent.hints"
trust-anchor-file: /etc/unbound/trusted-key.key
python:
dynlib:
remote-control:
# cat >parent.hints <<___
> . 3600000 NS ROUTER.HOME.
> ROUTER.HOME. 3600000 A 172.16.0.1
> ___
起動
# systemctl enable unbound
Created symlink /etc/systemd/system/multi-user.target.wants/unbound.service -> /usr/lib/systemd/system/unbound.service.
# systemctl start unbound
# systemctl restart systemd-networkd
# systemctl resatrt systemd-resolved
完了後はdrill
コマンドで確認します。最初の、DNSサーバとして127.0.0.53
を指定した場合の出力と比較します。
# for s in 127.0.0.1 172.16.0.3; do diff -U0 <(drill archlinux.jp @127.0.0.53) <(drill archlinux.jp @$s); done
--- /dev/fd/63 2020-08-14 15:32:29.731482151 +0900
+++ /dev/fd/62 2020-08-14 15:32:29.731482151 +0900
@@ -1 +1 @@
-;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 22290
+;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 48461
@@ -14 +14 @@
-;; SERVER: 127.0.0.53
+;; SERVER: 127.0.0.1
--- /dev/fd/63 2020-08-14 15:32:29.741482151 +0900
+++ /dev/fd/62 2020-08-14 15:32:29.741482151 +0900
@@ -1 +1 @@
-;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 357
+;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 33999
@@ -14 +14 @@
-;; SERVER: 127.0.0.53
+;; SERVER: 172.16.0.3
差分が予想の範囲内なのでOKですね。
後処理
一応大丈夫そうなので、/etc
をコミットしましょう。
# cd /etc
# svn up
Updating '.':
At revision 5.
# svn st | grep "^?" | cut -b9- | xargs -rt svn add
A systemd/system/multi-user.target.wants/unbound.service
A unbound/dev
A unbound/parent.hints
A unbound/run
# svn ci -m"Unbound initial settings"
Sending systemd/network/enp0s25.network
Sending systemd/network/enp2s1.network
Sending systemd/resolved.conf
Sending systemd/system/multi-user.target.wants/unbound.service
Adding unbound/dev
Adding unbound/parent.hints
Adding unbound/run
Sending unbound/unbound.conf
Transmitting file data ....done
Committing transaction...
Committed revision 6.
内向きDNS
これです。これの為に、家庭内名前解決とか面倒臭い事をするんです。
設定
参考文献: 2.5 内向きDNS - 2 Unboundのインストール - Unboundで内向きDNSを建てる - 純規の暇人趣味ブログ
# cd /etc/unbound
# cat >server.conf <<___
> local-data: "taro.home. 3600000 IN A 172.16.0.2"
> local-data: "hanako.home. 3600000 IN A 172.16.0.3"
> local-data-ptr: "172.16.0.2 3600000 taro.home."
> local-data-ptr: "172.16.0.3 3600000 hanako.home."
> ___
# vi unbound.conf
〈編集内容は下記差分を参照〉
# svn di --diff-cmd diff -x -U0
Index: unbound.conf
=============================================================
--- unbound.conf (revision 6)
+++ unbound.conf (working copy)
@@ -858,0 +859 @@
+ include: "/etc/unbound/server.conf"
実行
設定ファイルを読み込みます。
# systemctl reload unbound
ちょっと確認。
# drill hanako.home @127.0.0.1
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 38567
;; flags: qr aa rd ra ; QYERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; hanako.home. IN A
;; ANSWER SECTION:
hanako.home. 3600000 IN A 172.16.0.3
;; AUTHORITY SECTION:
;; Query time: 0 msec
;; SERVER: 127.0.0.1
;; WHEN: Fri Aug 14 16:53:22 2020
;; MSG SIZE rcvd: 52
外部のドメイン名 archlinux.jp も、引き続ききちんと名前解決できる事を確認します。
# drill archlinux.jp @127.0.0.1
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 63596
;; flags: qr rd ra ; QYERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;; archlinux.jp. IN A
;; ANSWER SECTION:
archlinux.jp. 2559 IN A 160.16.119.98
;; AUTHORITY SECTION:
;; Query time: 0 msec
;; SERVER: 127.0.0.1
;; WHEN: Fri Aug 14 16:20:36 2020
;; MSG SIZE rcvd: 46
家中の設定
DHCPサーバを立てた場合にはそちらを設定します。まずは無線LANの親機ですな。これは機種毎に異なりますが、多くの場合は下記2点かと。
- DHCPサーバから通知するDNSサーバアドレスを設定
- DNSルーティング設定とかいう機能で、家庭内で解決する名前のドメイン毎に、Unboundを立てたサーバのIPアドレスを設定
また、他にも固定IPアドレスを設定したサーバマシンがあれば、そこのネットワーク設定も指定しておきます。
で、クライアントマシンからnslookup
やping
などのコマンドを実行。うまくいけばOKです。
> ping hanako
hanako.home [172.16.0.3]に ping を送信しています 32 バイトのデータ:
172.16.0.3 からの応答: バイト数 = 32 時間 <1ms TTL=64
172.16.0.3 からの応答: バイト数 = 32 時間 <1ms TTL=64
172.16.0.3 からの応答: バイト数 = 32 時間 <1ms TTL=64
172.16.0.3 からの応答: バイト数 = 32 時間 <1ms TTL=64
172.16.0.3 の ping 統計:
パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
最小 = 0ms、最大 = 0ms、平均 = 0ms
なお私のOS設定手順だと/etc/resolv.conf
を無視している為に、drill
コマンド実行時にはDNSサーバを指定しないとうまく動きません。対応方法は下記の3通りになります。
- 上述の通り、
drill
コマンド実行時にDNSサーバを明示的に指定 -
drill
コマンド実行時に/run/systemd/resolve/resolv.conf
を指定 -
/etc/resolv.conf
を、/run/systemd/resolve/resolv.conf
へのシンボリックリンクとする
本当はこの3番目の方法、/etc/resolv.conf
をシンボリックリンクにしてしまうのが正しいのでしょう。
2番目の方法の場合は、下記のような指定になります。
# drill hanako.home -c /run/systemd/resolve/resolv.conf
実行結果は省略。
いずれにしてもこれで設定完了となります。やったね