この記事では、Linux サーバー上に Unbound で DNS over TLS(DoT)サーバーを構築し、Android 端末のプライベート DNS として利用する手順を示します。
構築の目的は明記しませんが、察してください。
今回は以下の環境で構築しました。
- マシンスペック(ConoHa VPS のメモリ 2 GB プランを利用)
- CPU:3 コア
- メモリ:2 GB
- ディスク:100 GB
- OS
- Oracle Linux 10.2
以下に前提条件を示します。
- TLS のサーバー証明書/秘密鍵は事前に準備する必要があります。
- Andorid ではプライベート DNS を IP アドレスでは指定できないため、Android 端末から名前解決できるホスト名がサーバーに必要です。
1. Unbound のインストール
DoT を実現するソフトウェアはさまざまありますが、今回は Oracle Linux で RPM が提供されている Unbound を利用します。
以下のコマンドでインストールできます。
sudo dnf install unbound
2. Unbound の設定
設定ファイルは /etc/unbound/conf.d/ 以下に配置します。今回は dot.conf という名前で作成します。
rpz:
name: "allowlist"
zonefile: "/etc/unbound/allowlist.rpz"
rpz:
name: "blocklist"
zonefile: "/etc/unbound/blocklist.rpz"
rpz-action-override: nxdomain
server:
module-config: "respip validator iterator"
# 待ち受け
interface: 0.0.0.0@853
interface: ::0@853
# DoT(TLS)用ポート
tls-port: 853
# IPv4のみ(必要に応じてyesに)
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
# 証明書
tls-service-key: "<TLS サーバー秘密鍵>"
tls-service-pem: "<TLS サーバー証明書>"
# アクセス制御(制限なし)
access-control: 0.0.0.0/0 allow
# ログ
verbosity: 1
#log-queries: yes
#log-replies: yes
#log-tag-queryreply: yes
#log-destaddr: yes
#logfile: "/var/log/unbound.log"
use-syslog: yes
# キャッシュなど一般的な推奨値
num-threads: 2
msg-cache-size: 64m
rrset-cache-size: 128m
cache-min-ttl: 0
cache-max-ttl: 86400
# プライバシー/堅牢化
hide-identity: yes
hide-version: yes
qname-minimisation: yes
prefetch: yes
以下で 2 点ほど補足します。
RPZ ファイルの利用
とあるドメインに対して NXDOMAIN(ドメイン名が存在しない)を返すようにするには、以下のように設定することもできます(example.com とそのサブドメインに対して NXDOMAIN を返す)。
local-zone: "example.com." always_nxdomain
ただし、この方式で大量(100 以上)のドメインを指定すると DoT のレスポンスが遅くなります。そこで今回は高速化のために RPZ(Response Policy Zones)ファイルを作成します。
正確にどれぐらい高速化されるかは測定していませんが、Android 端末から利用すると、
-
local-zone使用時はブラウザの動作がもたつく - RPZ ファイル使用時はプライベート DNS なしと比べて差を感じない
となるので、効果はあると思います。
許可リストと拒否リストの分離
今回、allowlist.rpz で許可するドメインを、blocklist.rpz で拒否するするドメインを明示的に指定しています。
Bind などでは PASSTHRU を利用して拒否用の RPZ ファイル 1 つで許可/拒否を指定できるようです(一部のドメインを例外的に拒否しない)。ただし、Unbound だと正常に動作しませんでした。PASSTHRU が動かないという Issue が GitHub にはいくつか挙がってはいて全てクローズされているようなのですが。
そこで今回は許可リストファイル(/etc/unbound/allowlist.rpz)と拒否リストファイル(/etc/unbound/blocklist.rpz)を明確に分けることにしました。
3. Firewalld と SELinux の許可
DoT は 853 番ポートを利用します。まずは Firewalld の穴あけをします。
sudo firewall-cmd --permanent --add-port=853/tcp
sudo firewall-cmd --reload
また、Oracle Linux 10.2 のデフォルトでは SELinux により Unbound プロセスの 853 番ポート待ち受けが禁止されています。そこで SELinux の設定を変更します。
sudo dnf install -y policycoreutils-python-utils
sudo semanage port -a -t dns_port_t -p tcp 853 2>/dev/null || \
sudo semanage port -m -t dns_port_t -p tcp 853
4. サーバー起動と
ここまでくると設定完了なので、Unbound を起動します。
sudo systemctl enable unbound -now
Andorid 端末から動作確認してもよいのですが、まずは Linux 上から動作確認します。そのためには kdig というコマンドが必要なのでそれをインストールします(確か EPEL リポジトリに含まれているので、事前に EPEL リポジトリを有効にしてください)。
sudo dnf install knot-utils
その後、以下のコマンドで DoT の問い合わせをします。結果は dig コマンドとほぼ同じなので割愛します。
kdig @[DoTサーバーのホスト名 or IP アドレス] +tls +tls-hostname=[DoTサーバーのホスト名] [解決したいホスト名]
問題なければ、Android 端末のプライベート DNS にサーバーのホスト名を指定してください(IP アドレスは不可)。