Unboundは内部向けのDNSリゾルバを構築するためのソフトウェアです。
DNSはホームページのURLをIPアドレスに変換してくれるシステムです。(サーバ公開のためにDNSレコードを作成しているはずなので、なんとなくは分かるかと思います)
しかし、URLを打つ度に大元のDNSサーバ(権威DNSサーバ)に問い合わせていては、権威DNSサーバの負荷が大変なことになります。
このため、権威DNSサーバから得た情報を保管して代わりに回答するDNSリゾルバが存在しています。
PCの設定項目などに存在するDNSサーバは基本的には全てこのDNSリゾルバで、権威DNSサーバはDNSリゾルバからの問い合わせに答えるという形になります。
物流で例えると、製造元(権威DNSサーバ)⇒小売(DNSリゾルバ)⇒消費者(クライアントPC)という感じでしょうか?(多分違う)
これを自宅サーバに立てることで、よく行くサイトのIPアドレスがキャッシュとして記憶され、URLからIPアドレスに変換する時間が3ミリ秒ほど短くなります。(つまり趣味です)
また、RSPAMDなどのDNSを頻繁に参照するソフトが動いている場合、内部にDNSリゾルバがないと、ことある毎に外部に問い合わせてしまうので立てることを推奨します。
この記事で行うこと
1. Unboundのインストール
UnboundはCentOSのリポジトリで配布されているため、インストールするだけで大丈夫です。
[root@localhost ~]# dnf install unbound
2. Unboundの設定
Unboundの設定ファイルはCentOSのリポジトリからインストールした場合、 /etc/unbound/unbound.conf
となります。
ここではこのファイルを設定していきます。
2-1. 応答するIPアドレスの設定
最初に、どのIPアドレスに対して応答するかを設定します。
ここで設定されていないIPアドレスから問い合わせが来ても応答をしません。
初期設定だと、自身の問い合わせにのみ応答する設定となります。(このため、サーバ内でのみ使う場合はこの設定は不要です)
ここではネットワーク単位での設定が出来ないので一旦、全てのIPアドレスに対して応答する設定にします。( access-control
という設定にて外部からの問い合わせは制限します)
+
は追加する行。 -
は削除する行となります。
- # interface: 0.0.0.0
+ interface: 0.0.0.0
- # interface: ::0
+ interface: ::0
0.0.0.0
は全てのIPv4アドレスに応答する設定。 ::0
は全てのIPv6に応答する設定となります。
2-2. DNS問い合わせ時のポートの設定
次に外部DNSに問い合わせする際に使うポートを設定します。
このポートが特定のポートに決まっていたりすると、問い合わせを行ったタイミングで悪意を持った人に嘘を吹き込まれたりするので、注意が必要です。
CentOSでインストールしたときの初期設定ではポートの許可設定と拒否設定が同居していますが、後に記載されている拒否設定が優先されています。
しかし、拒否設定の方はSELinuxを考慮していない設定なので、SELinuxでエラーを生じます。
このため、拒否設定をコメントアウトして、許可設定を有効にさせます。
# permit unbound to use this port number or port range for
# making outgoing queries, using an outgoing interface.
# Only ephemeral ports are allowed by SElinux
outgoing-port-permit: 32768-60999
# deny unbound the use this of port number or port range for
# making outgoing queries, using an outgoing interface.
# Use this to make sure unbound does not grab a UDP port that some
# other server on this computer needs. The default is to avoid
# IANA-assigned port numbers.
# If multiple outgoing-port-permit and outgoing-port-avoid options
# are present, they are processed in order.
# Our SElinux policy does not allow non-ephemeral ports to be used
- outgoing-port-avoid: 0-32767
+ # outgoing-port-avoid: 0-32767
2-3. キャッシュ容量の設定
保管しておくDNSレコードのキャッシュ容量を設定します。
少ないと頻繁に権威DNSサーバに問い合わせに行くことになり、DNSリゾルバとしての意義が薄くなります。
ただ、このキャッシュ容量はサーバのメモリを使うので、サーバのメモリ容量と相談しながら設定してください。
# the amount of memory to use for the message cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
- # msg-cache-size: 4m
+ msg-cache-size: 100m
ここでは例としてとりあえず100MBを設定しました。個人で使う分にはこれだけあれば十分というか、設定値まで行かずに実質無制限となるかと思います。(DNSレコードには有効期限があるので)
2-4. 問い合わせ可能なネットワークの制限
2-1で全てのIPアドレスに対して応答する設定にしていますが、このままでは誰でも使えるDNSリゾルバ(オープンリゾルバ)となります。
オープンリゾルバは攻撃の踏み台とされやすいです。
偽のIPアドレスを教えられたり、勝手にDDoS攻撃をしかけさせられたりと被害者にも加害者にもなり得ます。
このため、自ネットワーク内のユーザにだけ使えるよう制限を行います。
# control which clients are allowed to make (recursive) queries
# to this server. Specify classless netblocks with /size and action.
# By default everything is refused, except for localhost.
# Choose deny (drop message), refuse (polite error reply),
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
# allow_snoop (recursive and nonrecursive ok)
# deny_non_local (drop queries unless can be answered from local-data)
# refuse_non_local (like deny_non_local but polite error reply).
- # access-control: 0.0.0.0/0 refuse
access-control: 0.0.0.0/0 refuse
- # access-control: 127.0.0.0/8 allow
+ access-control: 192.168.0.0/8 allow
- # access-control: ::0/0 refuse
+ access-control: ::0/0 refuse
- # access-control: ::1 allow
+ access-control: ::1 allow
# access-control: ::ffff:127.0.0.1 allow
refuse
は拒否、 allow
は許可となります。
上記設定では、全てのネットワークからの問い合わせを拒否とし、 192.168.0.0/8
の範囲にあるIPアドレスと ::1
からのみ許可をしています。
192.168.0.0/8は192.168.0.0 ~ 192.168.255.255の範囲を表し、これはクラスCのプライベートアドレスの範囲となります。
一般的に個人レベルでは内部IPアドレスはこの範囲で振られているので、内部IPアドレス全てとなります。
::1 はIPv6で自身のみを表します。もしIPv6で内部IPアドレスを指定したい場合は自身のIPアドレスを調べて、その前半(4つ目のコロンまで)の部分にコロンをもう一つ足して /64
と付けると大体合います。
例としてIPv6アドレスが 1111:2222:3333:4444:5555:6666:7777:8888
だった場合は、 1111:2222:3333:4444::/64
と設定すると大体大丈夫なのですが……仕組みを分かった上で指定した方が安全だと思います。
2-5. ルート・ヒントの設定
自身の知らないURLが来たときにそれを誰に聞けば良いか分からないと問い合わせに対応できません。
この誰に聞くかのリストがルート・ヒント(root hint)となります。
これは後ほど取得しますが、今は取得する予定のファイル名で設定を行っておきます。
# file to read root hints from.
# get one from https://www.internic.net/domain/named.cache
- # root-hints: ""
+ root-hints: "/etc/unbound/named.cache"
3. ルート・ヒントの自動取得の設定
2-5でルート・ヒントの場所を設定しましたが、まだそのファイルは存在しません。
ここでは、ルート・ヒントを定期的に自動で取得するように設定します。
定期的に行うものはsystemdのタイマ機能で設定することが出来ます。(このサイトでは他にNextcloudのバックグラウンドジョブでも使いました)
以下の2つのファイルを作成します。
/etc/systemd/system/roothints.service
[Unit]
Description=Update root hints for unbound
After=network.target
[Service]
ExecStart=/usr/bin/wget -O /etc/unbound/named.cache https://www.internic.net/domain/named.cache
Description
: どういうサービスか説明のため部分です。systemctl status
コマンドで指定したときに表示されます。After
: 起動条件です。この場合ネットワーク起動後に起動出来るようになるという意味です。ExecStart
: 実行するコマンドです。/usr/bin/wget
:wget
コマンドですが、フルパスで指定しなくてはいけないので、こうなります。wget
コマンドはファイルをダウンロードするコマンドです。-O /etc/unbound/named.cache
:-O
はダウンロードしたファイルの保存先を指定するオプションです。ここでは2-5で指定した通り、/etc/unbound/named.cache
に保存します。https://www.internic.net/domain/named.cache
: ファイルのダウンロード元です。
/etc/systemd/system/roothints.timer
[Unit]
Description=Run root.hints monthly
[Timer]
OnCalendar=monthly
Persistent=true
Unit=roothints.service
[Install]
WantedBy=timers.target
OnCalendar
: 実行間隔を指定します。他にもweekly
やdaily
を指定したり、詳しく日時を設定することも出来ます。Persistent
:true
の場合は電源が切れていたなどで実行できなかった場合は実行できるようになった時点ですぐに実行します。Unit
: このtimerで制御するserviceの名前を指定します。実は同名のserviceとtimerの組み合わせでは不要なのですが、分かりやすくするためにあえて設定しています。WantedBy
: このタイマー起動の前提条件です。Timersが起動していなければこれも起動しようがないので、このように設定しています。
あとは、作成したタイマーを起動します。
[root@note ~]# systemctl daemon-reload
[root@note ~]# systemctl enable --now roothints.timer
daemon-reload
: 新しく作ったtimerやserviceを読み込ませる為のコマンドです。
roothints.service
は roothints.timer
が指定したスケジュールに沿って起動してくれるので起動する必要はありません。
起動させたら、 /etc/unbound/named.cache
ファイルが出来たことを確認してください。
4. ファイアウォールの設定
DNSサーバ用のポートを開放します。
ちなみに、DNSのポート番号は53です。
[root@localhost ~]# firewall-cmd --add-port=dns --permanent
[root@localhost ~]# firewall-cmd --reload
5. Unboundの起動
先ほどタイマーを起動したときと同じようにsystemctlで起動します。
[root@www ~]# systemctl enable --now unbound
まとめ
これでDNSリゾルバを構築できました。
しかし、実際にDNSリゾルバを使用するにはPCやルータの設定で明示的にDNSサーバを指定してあげる必要があります。
この部分は環境によって大きく異なるので解説はしませんが、DNSサーバのアドレスを指定する部分に構築したDNSサーバのIPアドレスを入れてあげれば大丈夫なはずです。
DNSサーバのアドレスを入れる場所が2つある場合は2つ目には適当なパブリックDNSのアドレスを入れてあげると、構築したDNSサーバが完全に落ちたときにはパブリックDNSに聞きに行ってくれます。