こういう技術系記事ってQiitaとかに乗せたほうがいい気がするんだけど、このブログをずっと使い続けているので、ここで紹介。
基本Unboundはapt installでも最新バージョンがインストールできるが、自分でファイルを落としてきてコンパイルする際にオプション引数でECS対応を明示することで、ECSに対応するためのモジュールを含んだ状態でコンパイル、インストールすることが出来る。
ECSとは
という話以前にDNSの仕組みについてちょっと説明をば。
DNSの説明は端折るので(このページにたどり着いてるなら分かってる気もするが)、調べてみてね。
利用者に最適なIPアドレスを応答する
利用者が相手のサーバに接続するために名前解決という手順を踏むが、DNSサーバを利用して名前解決を行い、相手のサーバに接続するという流れになる。
その際に、DNSサーバ(キャッシュDNSサーバ)が権威サーバ(権威DNSサーバ)に再帰的に問い合わせて、権威サーバが利用者が要求したドメインのIPアドレスを応答する。これが名前解決。
その際に、権威サーバは「問い合わせてきたIPアドレス」をもとに応答するIPアドレスを選択することがある。
それは、「利用者と応答するIPアドレスが最もネットワーク的に近い位置であってほしい」からである。近い方が速いので、権威サーバは問い合わせ元のIPアドレスをもとに、なるべく近くなるように応答を変える仕組みがある。
例えば、google.com。有名なドメインではあるが、これに名前解決を要求すると、日本にいる場合は日本においてあるサーバのIPアドレスが応答されるし、アメリカとかならアメリカにあるサーバのIPアドレスが応答される。
日本からアメリカのサーバって、物理的に遠いからそりゃ遅くなるし、当たり前のことを言っているようだがこれは権威サーバが自動で選択してIPアドレスを応答してくれているからこの仕組みが成り立っているのである。
利用者に最適なIPアドレスの選択は出来る?
さて、権威サーバは「問い合わせてきたIPアドレス」をもとに応答するIPアドレスを選択すると書いた。
これ実は利用者のIPアドレスではない。なぜなら代理で再帰的に名前解決を要求して結果を得ているキャッシュDNSサーバが権威サーバに問い合わせているため、権威サーバはキャッシュDNSサーバのIPアドレスしか知らないのである。つまり利用者と応答するIPアドレスが最もネットワーク的に近い位置であってほしいはより細かく言えば名前解決を要求しているキャッシュDNSサーバと応答するIPアドレスが最も ネットワーク的に近い位置となる。
「利用者とキャッシュDNSサーバが遠く離れていたら利用者と応答するIPアドレスのサーバが近くないのでは?」
その通り。
だけれど、利用者はDHCPから降ってきたDNSサーバを利用する。一般のご家庭の場合は、契約したプロバイダー(ISP)が自社のキャッシュDNSサーバを提供しており、利用者は無意識にそれを利用している。何かというと、利用者は無意識に利用者とネットワーク的に近いキャッシュDNSサーバを使っている。そのため、キャッシュDNSサーバのIPアドレスをもとに権威サーバが選んで応答しても、利用者はキャッシュDNSサーバとほぼ同じ位置という前提があるため、利用者と応答するIPアドレスが最もネットワーク的に近い位置が達成されるのである。
・・・
おはよう!!!!!⚡⚡⚡
なんか色々と書いたが、まあこれらの前提があるのでDNSというものが成り立ってるし、自動で最適なサーバを選択できる。
ここまで問題点を語る前の前提知識。
パブリックDNSサーバを使った時の問題
ここで「8.8.8.8」とか「1.1.1.1」が出てくる。
使ったことは無いだろうか。「パブリックDNSサーバ」。
これはCloudflareやGoogleが提供している物。「ネットの調子が悪い時DNSとかいうやつを8.8.8.8にするとはやくなるよ!」的な話を聞いたことがあるのではないか。
これはプロバイダが提供しているDNSサーバが不調な時、超大手が運用しているDNSサーバに変更すると、ネットワーク的な距離は置いておいて、まあデカいから安定はしてるよね。ってことで、安定してネットを利用できるようになるよというもの。
「ネットワーク的な距離は置いて」と言ったが、よく考えると置いておけない。
利用者はキャッシュDNSサーバとほぼ同じ位置という前提があると言ったが、パブリックDNSを使ったら、どうやって権威サーバが応答を返すのか?
利用者のIPアドレスは通知されない。そんでもって、権威サーバはパブリックDNSから来たという情報しかない。パブリックDNSは、利用者に近くない。
つまり、利用者とネットワーク的に近いIPアドレスが選択できないのである。
前提知識を踏まえて、このような問題が起きるため、ECSが必要になってくるのである。
ここまでECSの前提知識。
ECSとは
ここでECSが出てくる。ECSとはEdns Client SubnetのことでありDNSの拡張方式であるEDNS0に付与することが出来る情報である。
具体的に、利用者のIPアドレスの一部(サブネット)を付与することが出来る。
ECSが必要になる理由
権威サーバは利用者のIPアドレスを知ることが出来ない。よって、利用者とキャッシュDNSサーバがネットワーク的に近いという前提で
キャッシュDNSサーバのIPアドレスを使って選択し、権威サーバは応答を返す。
しかしパブリックDNSの普及で、利用者とキャッシュDNSサーバがネットワーク的に近いという前提が成り立たず、適切に応答できないシチュエーションが起こるようになった。そのため、ECSで利用者のIPアドレスを通知することで、パブリックDNSサーバを利用したとしても、権威サーバは利用者のIPアドレスをもとに選択して応答を返すことが出来るようになった。
というのが概要。
もっとわかりやすく簡潔にまとまってそうなページも参考にしてね
Unboundのsubnetモジュール
ようやく本題ではあるが。
UnboundはデフォルトでECSの関する機能をサポートしていないので、enable-subnetオプションをつけてインストールすることで、ECS関連の設定が出来るようになる。設定それぞれの詳細は後述する。
インストール手順
enable-subnetオプションがとにかく必要なので、自分でコンパイルすることになる。
また、apt installの時とディレクトリが異なる(chrootされてる)ので、それも注意。
また、Ubuntu 22.04 LTSを前提としているのでそれも注意。
また、公式のインストール手順に従っているため、他OSであればこちらを参考にしてほしい。
まずコンパイルに必要なものをインストールし、makeできるような状態にする
sudo apt-get update
sudo apt install -y build-essential libssl-dev libexpat1-dev bison flexそしたらunbound-latestを落としてきて解凍する。
wget https://nlnetlabs.nl/downloads/unbound/unbound-latest.tar.gz
tar xzf unbound-latest.tar.gz
rm unbound-latest.tar.gz終わったら、ディレクトリを移動し、enable-subnetを設定しmakeする。
※今回はlatestが1.21.1のため、このディレクトリ名だがバージョンを確認して移動する。
cd unbound-1.21.0
./configure --enable-subnet
make
sudo make installそしたらunbound -Vでバージョンを確認し、Configure lineに--enable-subnetが表記されていることを確認したら成功。
unbound -V
Version 1.21.0
Configure line: --enable-subnet
Linked libs: mini-event internal (it uses select), OpenSSL 3.0.2 15 Mar 2022
Linked modules: dns64 subnetcache respip validator iterator
Linked libs: mini-event internal (it uses select), OpenSSL 3.0.2 15 Mar 2022
Linked modules: dns64 subnetcache respip validator iterator
BSD licensed, see LICENSE in source package for details.
Report bugs to unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues
Report bugs to unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues
service化とchroot
/lib/systemd/system/unbound.serviceに以下のように書き込む。
[Unit]
Description=Unbound DNS Resolver
After=network.target[Service]
Type=simple
ExecStart=/usr/local/sbin/unbound -d
ExecReload=/bin/kill -USR1 $MAINPID
Restart=on-failure[Install]
WantedBy=multi-user.targetそしたらポート的に競合するsystemd-resolvedを停止させてdaemon-reloadしてenable, startする。
sudo systemctl stop systemd-resolvedsudo systemctl disable systemd-resolvedsudo systemctl daemon-reloadsudo systemctl enable unboundsudo systemctl start unboundこれでUnboundが起動していることをstatusで確認出来れば完了!
chrootは環境によって異なる可能性はあるが、私の場合は
/usr/local/etc/unbound/だった。参考までに。chrootしているため、logfile: "unbound.log"とすると実際は
/usr/local/etc/unbound/unbound.logになり、configファイルは/usr/local/etc/unbound/unbound.confに配置された。systemd-resolvedはUbuntu 22.04 LTSのスタブリゾルバなので、止めると名前解決できなくなる。(スタブリゾルバではなく、ローカルDNSスタブリスナとして127.0.0.53に渡してるだけ説もあるが、よく分かってない。)
/run/systemd/resolve/stub-resolv.confを変更すると自身のUnboundか使用するDNSサーバを設定することで名前解決が出来るようになる。変更は即時適用される。systemd-resolvedを起動すると書き換えられる?よく分からないが、systemd-resolvedを再起動する場合は注意。
各種オプション
公式ドキュメントのEDNS Client Subnet Module Optionsに書いてあるので参考までに。
解釈違いな箇所があればコメントで指摘していただければ幸いです。
send-client-subnet: <IP address>
クライアントのIPアドレスを指定した宛先サーバにのみ送信する
for example like 10.2.3.4/24
おそらく0.0.0.0指定で常にECSを付与する設定になる。
client-subnet-zone: <domain>
クライアントのIPアドレスをdomainに対して送信する
特定のドメインの時だけECSを付与するの意?
client-subnet-always-foward: <yes or no>
send-client-subnetで設定された宛先にECSを常に付与して送信するか
yes: 既にECSを含んでいても無視してECSを新たに付与
no(default): ECSが含まれていない場合のみECSを付与する
max-client-subnet-ipv4: <num>
numまでプレフィックス長を削って送信する。デフォルトは24
min-client-subnet-ipv4: <num>
プレフィックス長が設定より短いとREFUSED応答を返す。デフォルトは0
max-ecs-tree-size-ipv4: <num>
1つのクエリ名、クラス、タイプに対してどれだけの異なるECS対応のレスポンスをキャッシュするかの制御。デフォルトは100
より多いほどキャッシュヒット率が上がるが、小さくすると最大キャッシュ数を超えた古い情報が削除される。
この記事へのコメント