Chienomi

IPv4アドレスを返すmDNS名の解決が遅い問題をなんとかする

Live With Linux::dailyhack

.localというドメインを持つmDNS名(Zeroconf, Avahi)だが、実際にこのmDNS名で解決しようとしたときにかなり時間がかかるケースがある。

これはSSHでローカルネットワーク内のマシンにアクセスしようとしたときに感じやすいが、あらゆる場面で発生する状況ではある。

そしてこれは典型的には、AvahiでIPv4を返そうとした場合に発生する。

先に結論

IPv4アドレスを返したいホストの/etc/avahi/avahi-daemon.conf

use-ipv4=yes
use-ipv6=yes
publish-a-on-ipv6=yes

する。

解説

デフォルト設定ではAvahiはIPv6が有効になっていればAAAAレコードのみを返す。 このため、mDNS名前解決はIPv6で行われる。 つまり、IPv4アドレスは返さない。

一方、例えば/etc/avahi/hosts

192.168.0.64 foohost.local

のようにした場合、IPv6アドレスを持たないため、最終的にはIPv4アドレスを返すが、これはAvahiのIPv4ソケット経由で行われるものであり、IPv6が有効なZeroconfクライアントはIPv6経由で行うため、ここで名前解決に失敗し、タイムアウトしてからIPv4での解決にフォールバックする。

このことから、単にIPv4だけを返すようにすると名前解決に時間がかかるようになる。

この場合にできることとして、解決する側でIPv4を使うようにすれば良い。 これは、/etc/nsswitch.confmdnsの代わりにmdns4を、mdns_minimalの代わりにmdns4_minimalを使うことで実現できる。

ただしこの場合はmDNS名での解決をIPv4で行う前提となり、ネットワーク自体がIPv6環境である場合は整合性における懸念点になってしまう。

それを防ぐためにはネットワーク全体でIPv6を無効化すれば整合性は取れるわけだが、ZeroconfクライアントはWindowsやスマートフォンも存在していることや、端末の中には持ち運んで別のネットワークを利用するものもあるだろう。 特にスマートフォンはIPv6アドレスを使わせないようにするのも難しければ、mDNS名前解決にIPv4を強制するのも難しい。 また、スマートフォンであればモバイルネットワークではIPv6を使いたい、あるいは公共Wi-FiではIPv6が必要といったケースも考えられるため、なおさらIPv6の無効化はできたとしてもやりづらい。 このため、現実的にはなかなか難しい。

そこでベストなのがpublish-a-on-ipv6=yesを有効にすることでIPv6での名前解決でIPv4アドレス(Aレコード)を返すこととなる。 これによりIPv6経由での名前解決でタイムアウトすることなく即座にIPv4アドレスを返してもらうことが可能になる。 また、IPv6経由での解決になったことで、IPv6無効化といった厳しい制約を発生させることなく意図を達成できる。

補足

publish-a-on-ipv6=yes

はIPv6でのmDNS名前解決においてIPv4アドレス(Aレコード)を返す。

このため、

use-ipv6=yes
publish-a-on-ipv6=yes

で十分そうに見えるかもしれないが、Avahi自身がIPv4アドレスを持っていないと返すべきAレコードの内容が作れないため、

use-ipv4=yes

も必要となる。

これによりIPv4ソケットが使われるようになり、AvahiにIPv4アドレスがある状態となる。 これで、publish-a-on-ipv6によってAレコードを返す際に使われるアドレスが得られるわけである。