よく、Hyper-Vで雑にVMでUbuntuをいれたりミニPCにLinuxいれたりしているが、固定のプライベートIPを振って運用している。しかし、よく使わないものはIPアドレスを忘れるようになった。でもDNSサーバはなんか立てるのも面倒だしIPに変更があったとき追従してくれないのも面倒。ということでmDNSの出番。(設定したホスト名を忘れるという問題は見なかったことにします)
マルチキャストDNS(mDNS)はマルチキャストを利用してDNSサーバ無しに名前解決する。mDNSの要求に対して、ホスト名.local を持つサーバがマルチキャストに応答することで実現するため、同一ネットワークに属するような小規模なネットワーク向きらしい。類似のプロトコルにLLMNRがある。
mDNSを動かすには、リクエストを送る側とリクエストを受けるためにデーモンを動かす必要があり、mDNSリクエストを送るためにリゾルバも対応が必要なので注意。(mDNSにおいては相互に同じ立場なので呼び名がないっぽい?ものの、2つの役割で成り立ってるので、デーモンとリゾルバと呼んで区別している。デーモン=サーバ、リゾルバ=クライアントというようなイメージ。)
細かい話はあるかもしれないけど、とにかく使える状態にするための手順をメモ。
mDNS設定
実現するには、avahiを使うか、systemdを使うかの2つが主らしい。
ファイアウォールがある場合はUDP:5353を開ける必要がある。
Ubuntu + avahi の場合
デーモン
sudo apt install avahi-daemon sudo systemctl start avahi-daemon sudo systemctl enable avahi-daemon
これだけでよい。
リゾルバ
/etc/nssswitch.conf で設定することになる。avahiをインストールすると依存でlibnss-mdnsもインストールされる。
あとは使うだけ。インストール後に以下のように設定されており、IPv4のみでよければすぐに使える。
hosts: files mdns4_minimal [NOTFOUND=return] dns # 参考: インストール前 # hosts: files dns
環境によるが、mdns_minimalが良い場合もあるはず。適宜設定すること。
他にもあり、挙動についてはこの辺をよむ。でもほとんど上記のどれかでいいはず。
Ubuntu + Systemd-resolve/Systemd-networkdの場合
Systemdでも行える。パッケージを増やしたくない場合はこちらがいいかもしれない。
デーモン
/etc/systemd/resolved.conf を修正する。
[Resolve] MulticastDNS=yes
その後、 反映させるために systemd-resolved.service で再起動
sudo systemctl restart systemd-resolved.service
resolvectl mdns でmDNSの設定状況を確認できる
$ resolvectl mdns Global: yes Link 2 (eth0): no
noがあるネットワークインターフェースはmDNSのリクエストを受けても返さないのでうまくいかない模様。なので、次はその設定をしていく。(リゾルバとしてはこの時点でも使える。)
まず設定対象のファイルを調べる。ネットワークインタフェース名を含むので、設定したいネットワークインタフェースの数だけ設定。
$ ls /run/systemd/network/ 10-netplan-eth0.network
この場合、 /etc/systemd/network/${FILENAME}.d/override.conf にファイルを作る。(/etc/systemd/network/${FILENAME} だと再起動時にダメになった)
NETWORK_FILE_NAME="10-netplan-eth0.network" sudo mkdir "/etc/systemd/network/${NETWORK_FILE_NAME}.d" cat << __EOF__ | sudo tee "/etc/systemd/network/${NETWORK_FILE_NAME}.d/override.conf" [Network] MulticastDNS=yes __EOF__
その後、 反映させるために systemd-networkd.service を再起動
sudo systemctl restart systemd-networkd.service
resolvectl mdns で設定状況を確認し、yesになっていればOK。
$ resolvectl mdns Global: yes Link 2 (eth0): yes
リゾルバ
リゾルバだけでいい場合は、/etc/systemd/resolved.conf をMulticastDNS=resolve とすればよい。
その他
疎通確認方法
Linux: getent
getent hosts ホスト名.local がよいでしょう。GLIBCについてくるっぽいので大抵の環境で使えるはず。
getent hosts test3.local
出力例
$ getent hosts test3.local fe80::215:5dff:fe01:a605 test3.local
当たり前かもしれないけど、nslookupやdigはDNS用っぽいので機能しなかった。(wgetであればgetentと同じような雰囲気)
Windows: PowerShellのResolve-DnsName
PowerShellのResolve-DnsName ホスト名.local がよいでしょう。
Resolve-DnsName test3.local
出力例
> Resolve-DnsName test3.local Name Type TTL Section IPAddress ---- ---- --- ------- --------- test3.local AAAA 120 Answer fe80::215:5dff:fe01:a605 test3.local A 120 Answer 172.28.21.94
IPv6を無効にすればIPv4で解決するようになる
当たり前だけど、IPv4とIPv6のどちらも有効な場合、IPv6を使うっぽいので、この挙動が困る場合はIPv6のサポートを切ればよい
- デーモン側でIPv6を無効にする場合
- avahi:
/etc/avahi/avahi-daemon.confの[server]セクションでuse-ipv6=noを設定する - systemd-networkd ではわからない
- avahi:
- リゾルバ側でIPv6を無効にする場合
- avahiならnsswitch.conf では msdn4_minimal を使う
- systemd-networkd ではわからない
- 共通
以下はtest3.local上でtest2.localを探す際にsysctl net.ipv6.conf.all.disable_ipv6=1としてIPv6を無効にした場合とその前後のgetentの結果。(test2.localはIPv6/IPv4のmDNSをサポートしている)
ryozi@test3:~$ getent hosts test2.local fe80::215:5dff:fe01:a604 test2.local ryozi@test3:~$ sudo sysctl net.ipv6.conf.all.disable_ipv6=1 net.ipv6.conf.all.disable_ipv6 = 1 ryozi@test3:~$ getent hosts test2.local 172.28.18.148 test2.local