mDNSを使ってローカルDNSサーバーを廃止する

#はじめに
ローカルネットワーク内のホスト名でのアクセスはNetBIOS時代から試みてきたものの、WindowsとmacOSの間は統一された規格がなく相互通信が出来ない状態が続いてきた。

[突然消失するかもしれないブログさんの記事の説明を拝借](https://typex2.wordpress.com/2009/09/27/windows-mac-os-x-linux%E9%96%93%E3%81%A7dns%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%9A%E3%81%AB%E3%83%9B%E3%82%B9%E3%83%88%E5%90%8D%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%EF%BC%9Amd/)

その状態が、Windows10 1803(April 2018 Update/Redstone 4/RS4)が出荷されたことで、ようやくmDNSという規格により統一され、Windows macOS Linux間のホスト名でのアクセスが可能になりました。
mDNSはDNSの代わりにIPアドレスを返してくれるため、今までローカルにDNSサーバーを立て、ローカルエリア内の名前解決をされていた方はDNSサーバーの撤去が出来ます。

Windows10 1803でもほぼ動作に支障ない状態でしたが、Windows10 1909(Windows 10 November 2019 Update/19H2)ではResolve-DnsNameコマンドの動作が改善されています。1903までで非対応であったIPv6でのホスト名逆引きも正常に動くようになっています。
後述するsshの標準搭載と合わせて、Windows10 1909はLinuxと非常に相性が良いOSとして仕上がっているので、いろいろバグレポートは上がってきているものの、アップグレードして損はなかったと筆者は考えています。



#サーバー、デスクトップ用OSからの検索
macOS、Windows、Linuxでは、相互にホスト名での通信が可能です。
ブラウザに「[http://hogehoge.local]()」と入力したり、sshに入るのに「[ssh root@hogehoge.local]()」と入力したりすればアクセスできます。もちろんサーバー側にサービスが立ち上がっていることが前提です。
後記しますが、pingは相互にホスト名で打ち合うことが可能です。
以下では、名前だけ解決したい場合のコマンドと設定方法をまとめます。

##クライアントがmacOSの場合
mDNSのご本家のAppleでなのですが、初期の対応は早かった。しかし、現在は1周回ってサーバー、デスクトップ用OSで一番機能が不十分な状態です。

macOSに向かっての問い合わせは、IPv6では応答しません。
また、digを用いた正引き/逆引きもIPv6では応答がありません。
この動作はHigh SierraからCatalinaまで変わっていないです。それ以前は未検証です。

今後修正されたらと期待をこめ、一応コマンドとエラーを書いておきます。
digで引こうとするとブロードキャストアドレスを忘れるため、そろそろ専用のコマンドが欲しいです。

```
#正引き(1)
$ dns-sd -G v4v6 hogehoge.local
DATE: ---Tue 01 May 2018---
12:34:56.789  ...STARTING...
Timestamp     A/R Flags if Hostname             Address                                      TTL
12:34:56.789  Add     3  7 hogehoge.local.      192.168.1.10                                 120
12:34:56.789  Add     2  7 hogehoge.local.      2100:000A:000A:0000:0000:0000:0001:0001%<0>  120
```

```
#正引き(2)
$ dig hogehoge.local. @224.0.0.251 -p 5353
; <<>> DiG 9.10.6 <<>> hogehoge.local. @224.0.0.251 -p 5353
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7851
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;hogehoge.local.		IN	A

;; ANSWER SECTION:
hogehoge.local.		10	IN	A	192.168.1.10

;; Query time: 1 msec
;; SERVER: 192.168.1.10#5353(224.0.0.251)
;; WHEN: Thu Aug 01 21:00:36 JST 2019
;; MSG SIZE  rcvd: 46

$ dig hogehoge.local. @ff02::fb -p 5353
; <<>> DiG 9.10.6 <<>> hogehoge.local. @ff02::fb -p 5353
;; global options: +cmd
;; connection timed out; no servers could be reached
```

```
#逆引き
$ dig -x 192.168.1.10 @224.0.0.251 -p 5353
; <<>> DiG 9.10.6 <<>> -x 192.168.1.10 @224.0.0.251 -p 5353
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64092
;; flags: qr aa; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;10.1.168.192.in-addr.arpa.	IN	PTR

;; ANSWER SECTION:
10.1.168.192.in-addr.arpa. 10	IN	PTR	hogehoge.local.

;; Query time: 1 msec
;; SERVER: 192.168.1.10#5353(224.0.0.251)
;; WHEN: Thu Aug 01 21:15:52 JST 2019
;; MSG SIZE  rcvd: 69

$ dig -x 2100:a:a::1:1 @ff02::fb -p 5353
; <<>> DiG 9.10.6 <<>> -x 2100:a:a::1:1 @ff02::fb -p 5353
;; global options: +cmd
;; connection timed out; no servers could be reached
```


##クライアントがwindows10の場合
Windows10 1607/1703/1709(RS1~3)でもmDNSが実装されていたようですが、ファイアウォールの設定がおかしかったようです。以下の手順でファイアウォールを正しく設定すれば正常に動くようになるようです。

[マイクロソフト Network & AD サポートチーム公式ブログ参照](https://blogs.technet.microsoft.com/jpntsblog/2018/04/28/%E6%97%A2%E5%AE%9A%E3%81%AE%E5%8F%97%E4%BF%A1%E3%81%AE%E8%A6%8F%E5%89%87-mdns-udp-%E5%8F%97%E4%BF%A1-%E3%81%8C%E6%A9%9F%E8%83%BD%E3%81%97%E3%81%AA%E3%81%84%E5%95%8F%E9%A1%8C/)

Windows10 1803(April 2018 Update/Redstone 4/RS4)では初期状態でmDNSがほぼ正常に動くようになりました。

Windows10 1511以前(8.1/7/vistaも含む)でmDNSが使いたい場合は「Bonjour for Windows」をインストールしてください。ただし、こいつはIPv4でしか引けません。

Windows10 1909までアップグレードするとmDNS周りの不具合は解消されているように見えます(執筆時点ではですが・・・)
1903までで対応していなかったResolve-DnsNameを使ったIPv6での逆引きも1909では正常動作しました。

ちなみにWindows10 1803にBonjourをインストールすると不具合大発生の模様。中には解決に1日消費した人もいるそうで・・・。それならWindowsを初期化したほうが早くないってなります。筆者も何台か初期化で問題解決してます。
[Windows 10 April 2018 Update (バージョン 1803) で共有フォルダの不具合【Ver1803】](https://answers.microsoft.com/ja-jp/windows/forum/windows_10-networking/windows-10-april-2018-update/06a66719-4d0b-4b25-a8b9-87af56dca640?page=3)
[1803 にアップデート後，Bonjour (mDNS) で IPv6 のアドレス解決ができません。 ](https://answers.microsoft.com/ja-jp/windows/forum/windows_10-networking/1803/ea4e4025-d83b-4e45-a7aa-16da4ad96a99)
[windows10からLAN接続されている機器に対してpingが通らないのである。](http://john-rama01.hatenablog.com/entry/2018/06/16/011155)

さて正常動作状態であれば、Windows PowerShellを開いてResolve-DnsNameで名前が引けます。このコマンドはIPv6/4の両方で問合せを行うコマンドです。逆引きも可能です。

ちなみに、おなじみnslookupではIPv6でもIPv4でも引けませんので悪しからず。
Resolve-DnsNameは通常のサーバー問合せを行うDNSも回答できるため、nslookupはもう用済みかも・・・。

linuxやmacOSに対してでも.localを省略して問い合わせができます。

ホスト名に.localをつけると1909以前のWindows10において、Resolve-DnsNameコマンドが変な動作をすることがありますので、.localを付けない方をお勧めします。
.localをつけると動きがおかしいのは、逆引きしたときには.localがついていないアドレスを返してくるのと関係があるものと筆者は推察しています。

```
#正引き
> Resolve-DnsName hogehoge
Name                                           Type   TTL   Section    IPAddress
----                                           ----   ---   -------    ---------
hogehoge.local                                 AAAA   120   Answer     2100:a:a::1:1
hogehoge.local                                 A      120   Answer     192.168.1.10
```


```
#逆引き
> Resolve-DnsName 192.168.1.10
Name                                           Type   TTL   Section    NameHost
----                                           ----   ---   -------    ---------
10.1.168.192.in-addr.arpa.                     PTR    1200  Question   HOGEHOGE

> Resolve-DnsName 2100:a:a::1:1
Name                           Type   TTL   Section    NameHost
----                           ----   ---   -------    --------
1.0.0.0.1.0.0.0.0.0.0.0.0.0.0. PTR    30    Answer     hogehoge
0.0.0.0.0.a.0.0.0.a.0.0.0.0.0.
1.2.ip6.arpa
```


##クライアントがLinuxの場合
まずパッケージがインストールされていないと始まらないので、avahiとnss-mdnsをインストールします。Ubuntu18.04やDebian9では標準でインストールされている模様ですが、念の為。
CentOSでは追加リポジトリの設定が必要で、minimalだとインストールされていない模様です。

```
$ apt install avahi-daemon libnss-mdns
$ dnf install avahi avahi-tools nss-mdns
```

Firewallが原因で名前解決に失敗することがあるため、一時的にFirewallを無効にします。正しく動くことが確認できたら、Port5353を開けてください。最適な設定は後日追記します。(宛先は224.0.0.251とff02::fbにすればいいのかな?)

```
$ systemctl stop ufw
$ systemctl stop firewalld.service
```

標準だとIPv4では正常に動作しますが、IPv6ではIPv4射影アドレスで返事をしてくるので、nsswitch.confのhostsの項目を編集します。

```
# nano /etc/nsswitch.conf
hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4

上記を以下に書き換え
hosts:          files mdns_minimal [NOTFOUND=return] dns mdns
```

これで設定完了です。
あとは、Terminalからgetentコマンドで名前を引くことが出来ます。
動作は明示しないとIPv6通信が優先されます。
インストールすればdigコマンドも使えるが、使い方はmacOSの項で説明したため、それより簡単なavahi-resolveを使う。

```
#正引き(1)
$ avahi-resolve -n hogehoge.local
hogehoge.local	2100:a:a::1:1

$ avahi-resolve -n hogehoge.local -4
hogehoge.local	192.168.1.10
```

```
#正引き(2)
$ getent ahosts hogehoge.local
2100:a:a::1:1 STREAM hogehoge.local
2100:a:a::1:1 DGRAM  
2100:a:a::1:1 RAW 
192.168.1.10    STREAM
192.168.1.10    DGRAM  
192.168.1.10    RAW   
```

```
#逆引き
$ avahi-resolve -a 2100:a:a::1:1
2100:a:a::1:1	hogehoge.local

$ avahi-resolve -a 192.168.1.10
192.168.1.10	hogehoge.local
```

##サーバー、デスクトップ用OS全般
設定が終わってしまえば、相互にホスト名での通信が可能です。
例としてWindowsでpingをIPv6で送信してみます。macOSの場合はping6コマンドを使ってください。
ちなみに明示しない場合は、WindowsとLinuxはIPv6でmacOSはIPv4でアクセスする模様です。

```
> ping -6 hogehoge.local
hogehoge.local [2100:a:a::1:1]に ping を送信しています 32 バイトのデータ:
2100:a:a::1:1 からの応答: 時間 =2ms
2100:a:a::1:1 からの応答: 時間 =1ms
2100:a:a::1:1 からの応答: 時間 =1ms
2100:a:a::1:1 からの応答: 時間 =1ms

2100:a:a::1:1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 1ms、最大 = 2ms、平均 = 1ms
```


もちろんping+IPv4でも問題ありません。

```
> ping -4 hogehoge.local
hogehoge.local [192.168.1.10]に ping を送信しています 32 バイトのデータ:
192.168.1.10 からの応答: バイト数 =32 時間 =1ms TTL=63
192.168.1.10 からの応答: バイト数 =32 時間 =1ms TTL=63
192.168.1.10 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.10 からの応答: バイト数 =32 時間 =1ms TTL=64

192.168.1.10 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 1ms、最大 = 1ms、平均 = 1ms
```

自身に設定されている名前がわからない場合は、hostnameコマンドで調べれます。(macOS Windows Linux共通)
この名前に.localを付ければ相手から名前を調べてもらえます。

```
> hostname
hogehoge
```


あと、OpenSSHには隠しオプションがあって、「[ssh -4 root@hogehoge.local]()」で明示的にIPv4でアクセスできます。
OpenSSHはLinux版はもとより、macOS Sierra以上、Windows10 1803以上でv7が標準搭載されていますので、気兼ねなく使うことが可能です。


| 問い合わせ元　　   | 優先通信方式 |
|:----------------:|:-----------------:|
| macOS10.14 Catalina| IPv4 |
| Windows10 1909   | IPv6 |
| Ubuntu18.04.3    | IPv6(nsswitch.confを書き換えた場合) |

| 問い合わせ先　　   | 発生する問題 |
|:----------------:|:-----------------:|
| macOS10.14 Catalina| IPv6で応答しない |
| Windows10 1909   | 特に問題なし |
| Ubuntu18.04.3    | 特に問題なし |

まとめると以下のようになります。

| 問い合わせ元\先    | macOS10.14 Catalina | Windows10 1909     | Ubuntu18.04.3      |
|:----------------:|:-----------------:|:------------------:|:------------------:|
| macOS10.14 Catalina| 特に問題なし| 特に問題なし | 特に問題なし |
| Windows10 1909   | IPv4を明示しないと通信不能 | 特に問題なし | 特に問題なし | 
| Ubuntu18.04.3    | IPv4を明示しないと通信不能 | 特に問題なし | 特に問題なし |

#モバイル用OSの場合
まだ問題があるのが、モバイル用のOSである。
以下、動作状況だけ説明しておく。

##iOSの場合
ブラウザに「[http://hogehoge.local]()」と入力したり、sshアプリなどで、hogehoge.localでアクセスは可能である。
しかし、iOSに対してホスト名でのアクセスが出来ない。
例えば、ping iPhone's-ip-addressはpingが返ってくるが、ping iPhone's-hostname.localでは名前解決に失敗する。

##Androidの場合
まったく動かない。

Android9でも対応していただけないので、自力でアプリを作ってみました。
Hostnameを入力するとIPアドレスをv6かv4で返してくれる簡単なソフトです。面倒なので広告もなしです。
https://play.google.com/store/apps/details?id=com.dokoden.dotlocalfinder&hl=ja

オープンソースにしたので、使ってください
https://github.com/NetworkRevolution/DotLocalFinder

だけど、OSレベルで対応してくれると、こんな面倒はないんだけどな。Qなら治っているのかな？
google様・・・お願い

##ボヤキ
ああ、熱心なApple信者も、UbuntuやDebianな人も、中にはAndroid好きな人もメジャーアップデートやLTSが出るたびに初期化の儀式を行っていたけど、Windowsもその流れなのね。
後方互換こそWindowsの強みだった時代はどこへやら。

オシャレが売りのmacOSですが、OSインストール時にユーザーアカウントHOGEに設定するとHOGEnomakku.localというオシャレとは程遠い名前になるのは如何なもんじゃいな。