ubuntu systemd-resolved で ローカルドメインの解決をする
ubuntu でresolved を使ってる場合にローカルドメインの解決をして増え続けるLXDコンテナの名前解決をなんとかしたい。IPアドレスで覚えきれないよ。
はじめに
ubuntuは systemdに移行しているので、名前解決は systemd-resolved を使う。
ubuntu は netplanもあるのでややこしい。複数インターフェースを使う。
ubuntu のデフォルト設定 resolved
ubuntu server のDNSのデフォルト設定を見てみると、こんな感じだと思う。
- systemd-resolved が 127.0.0.53 をリッスンする
- systemd-resolved は 上流をresolved.conf と DHCPから選ぶ
- DHCP があって、 resolvedもあるとき。調べてみたとろ次のように動作していた。
- 上流設定があれば、DHCPより優先する。
- 上流設定を未設定なら、DHCPを使う。
- 上流で解決できなければ、DHCPを使う。
設定変えて動作チェックを試行した結果を見ると、netplanのDHCPで渡されたDNSはresolvedのfallbackDNSと同等の動作をしている(たぶん)
resolved がどのDNSを使っているか見る。
sudo systemd-resolve --status
status をみれば、どのDNSを使っているかわかる。複数インターフェースがある場合は、インターフェース毎にDNS設定があるのがわかる。
上記の通り、systemd-resolve は resolvectl が最初に使われるはずなので、以下のコマンドと結果がおなじになる。
sudo resolvectl status
systemd-resolve の移譲先がresolvectlである。
status でネットワーク・インタフェースごとに設定されている、DNSサーバーを確認できる。 しかし、statusで表示されたDNSリゾルバを使うとは限らない。上書き設定がある。resolvectl は上流でdnsmasqを参照したりする。
そのため、注意深く一つずつ見ていくことになる。
sudo systemd-resolve --> resolvectl --> dnsmasq --> upstream resolver --> dns of network interface config --> upstream resolver --> dns of DHCP config --> upstream resolver --> resolve.conf --> upstream
上記のようになることがある。慎重に考えないと面倒が起きる。
構成例 resolv.conf生成
すべて resolved で解決する 。
/etc/systemd/resolved.conf
[Resolve] #略 Domains=local UseDomains=true
すると、次のような resolv.confが生成される。
/etc/resolv.conf
システムは、/etc/resolve.confを使っていて、resolve.conf は systemd-resolvedを参照するように設定されている。
nameserver 127.0.0.53 options edns0 trust-ad search local
だいたいこの設定がデフォルト設定担っている。
dig example は
search を入れているので。 dig example
は dig example.local
を探しに行く。
探しに行く先は、上流である。上流に example.local
を問い合わせる。
この設定は、resolv.confを自動生成して、example → example.local を自動付記して問い合わせる設定である。
構成例 ローカルドメインの解決先を指定する。(dnsmasq を挟む)
resolved と DNSの間に dnsmasq を挟み込む。resolvedはほとんど何もしない。
resolved は dnsmasq に聞きに行く。dnsmasq がローカルドメインを解決する。
一見すると冗長に見えるが、resolvedより制御がしやすく仕方ないと思う。
準備
sudo apt install dnsmasq
dnsmasq の設定
dnsmasq の設定は、上書き設定を dnsmasq.d/
に書くと便利
sudo touch /etc/dnsmasq.d/30-overwrites.conf
/etc/dnsmasq.d/30-overwrites.conf
#server=/xxx.internal.com/10.100.100.1 server=/local/192.168.1.1 server=/lxd/10.185.93.1 server=/virt/192.168.122.1 server=192.168.1.2
.lxd
は lxc/lxd のネットワークの名前解決
.local
は ルーターからDHCPで配布されたIPの名前解決
.virt
は libvirt のネットワーク上のホスト名を名前解決
resolvedの設定
resolved 上流をdnsmasq にする
/etc/systemd/resolved.conf
[Resolve] DNS=127.0.0.1 #FallbackDNS= #Domains=
上流にdnsmasq を仕込む。
名前解決の順
dnsmasq を挟んだので、名前解決は次のようになる。
cli-->resolved(127.0.0.53#53)->dnsmasq(127.0.0.1#53)
dnsmasq がドメインを名に応じて、問い合わせ先を変えてくれる。
再起動
設定が終わったら再起動
sudo systemctl restart dnsmasq.service sudo systemctl restart systemd-resolved.service
動作チェック
それぞれのローカルドメインについて、大本・dnsmasq・resolvedにそれぞれ問い合わせる。
# 上流から順に問い合わせる dig ubuntu.virt @192.168.122.1 dig ubuntu.virt @127.0.0.1 dig ubuntu.virt @127.0.0.53 # 上流から順に問い合わせる dig debian.lxd @10.185.93.1 dig debian.lxd @127.0.0.1 dig debian.lxd @127.0.0.53
netplan のDHCP設定
netplan のDHCP設定でDNSを書いていても resolved で DNSを設定しておけば名前解決ができる。
DHCPから割り当てられたDNSは、resolvedからDNS=x.x.x.x
への解決失敗時に使われる。
私の設定の場合、次項のようにした。resolved は dnsmasq へ問い合わせる。
Global MulticastDNS setting: no Current DNS Server: 127.0.0.1 DNS Servers: 127.0.0.1 Link 4 (br0.10) Current DNS Server: 192.168.12.1 DNS Servers: 192.168.12.1 Link 3 (br-lan0) Current DNS Server: 192.168.2.2 DNS Servers: 192.168.2.2
上記の設定が適用されている時、127.0.0.1 で動作中のdnsmasq を停止後でも、名前解決ができる。
dnsmasq 停止時のresolved の動作
sudo systemctl stop dnsmasq.service # dnsmasq 停止 dig dns.google @127.0.0.1 # dnsmasq 応答なし dig dns.google @127.0.0.53 # resolved 応答あり
resolved は dnsmasq が停止しても、DHCPからのDNSがあるためそちらにDNS問合せを投げるようでした。
もっと省略した設定
systemd-resolvedで
DNS=192.168.122.1 10.185.93.1 192.168.2.2 192.168.12.1
と複数かけば、順番に問合せてくれる。 10.185.93.1 が .lxd をもってるので、そこに到達すれば応答が得られる。
とりあえず、投げつければいいのであれば、DNSを複数列挙で十分である。
ただ、その設定だとどのローカルドメインがどのサーバーかの対応が全くわからないので管理が面倒くさい。
設定ファイルは、辿れるのも大事。どこに何があるが設定をたどってわかるというのは、大事だと思う。
なぜ設定が必要なのか。
ssh で lxd や docker 内部に 多段ログインするときに名前解決をすると格段に管理がしやすい。
仮想マシン上に、lxd をインストールして、lxd 上にdocker を作り、dockerのコンテナを起動していて、
host v1 user takuya hostname ubuntu.virt host v1-docker user root hostname docker-host.lxd ProxyCommand ssh -t v1 -W %h:%p host v1-docker-ubuntu user root hostname ubuntu ProxyCommand ssh -t v1-docker -W %h:%p
v1 にssh でログインして、v1-docker にアクセスできるようにして v1-docker にsshでログインして、v1-docker-ubuntu にアクセスできるようにする。
このとき、IPアドレスを直接していると再起動時にIPアドレスが変化して不便なのでDNSから名前解決しておけば安心である。
感想
resolvedで解決するといえど、resolved は機能不足だしresolv.confを生成するだけだし。結局dnsmasqに頼ることになった。networkd/resolvedで netplanやnetwork-managerが共通化されるとはいえ、あまりに冗長じゃないか?
v6 アドレスを作るときに、なんでHEXにしたんだ。。。BASE57 とかにしてくれてば、強引に覚えやすい名前をアルファベットで付けられたからDNSなくても良かったのに・・・
resolved / networkd を調べる時、 Googleなど検索エンジンは検索キーワードをresolve / network に置き換えるので、検索は困難になる。検索インデックスにもかからない systemd-resolved と書く必要がある。めっちゃ面倒くさいし名前付けに失敗してるわけで、これを使い続けるのは初心者には、今後どんんどんしんどくなっていくのだろうなと思う。