例えば、上図のような環境があったとする。
Windows Server 2016 がインストールされた “192.168.1.16/24” のサーバと Windows 10 がインストールされた “192.168.1.10/24” のクライアントが1台のスイッチに接続されている。本当にそれだけの環境だ。その他のホストは存在しない。
2台は同じネットワークに所属するため、以下のような ping コマンドは問題なく通る。(Windows Server 2016 から実行)
では、以下のようにコンピュータ名を指定して ping を実行した場合どうなろだろうか。
結論から言うと、ping は成功する。
Windows は、DNS サーバが存在しなくても同一ネットワーク内の名前を解決するためのプロトコルを備えているからだ。
それが、「LLMNR(Link-local Multicast Name Resolution)」と「NBT(NetBIOS over TCP/IP)」だ。
※2つの機能が連携して名前解決を行うのではなく、どちらも単独で Windows の名前解決が行える。
Windows の名前解決の方法と優先順位
上述したように、Windows の名前解決手段は DNS のみではない。「LLMNR」や「NBT」といったプロトコルで名前解決を行うこともできる。
これらは優先順位が厳密に定義されている。例えば、Windows Server 2008 以降の名前解決は次の順序で行われる。
- ホスト名解決
- GlobalNames ゾーン
- LLMNR(Link-local Multicast Name Resolution)
- NBT(NetBIOS over TCP/IP)
DNS サーバによる名前解決(1.ホスト名解決)に失敗したとしても、「LLMNR」か「NBT」のいずれかの手段で名前解決ができればいいわけだ。
DNS サーバが必要な DNS とは異なり、「LLMNR」と「NBT」はブロードキャスト(マルチキャスト)を利用することでクライアント同士で直接名前解決ができるというメリットがある。
GlobalNames ゾーン
「GlobalNames ゾーン」はDNS サーバありきの名前解決方法なので本記事では取り上げない。簡単に言うと、DNS サーバ に WINS の役割を押し付けるためにゾーンを作成する技術だ。TCP/IP によるホスト名解決ができない古い環境で利用する。
まずは、それぞれの概要を簡単に説明する。
NBT(NetBIOS over TCP/IP)
- NetBEUI を TCP/IP の世界でも使えるようにしたもの
- NetBEUI はルーティング機能が実装されていなかったため、ルータ越えができなかった
- TCP/IP に相乗りしたおかげでルータを超えて NetBIOS 名解決が可能になった(ただし lmhostsファイル もしくは WINSサーバ が必要)
- 今ではわざわざ WINS を用意してまでネットワーク間の NetBIOS 名解決をすることはあまりないが、DNS がいなくても同一ネットワーク内であれば NetBIOS 名でコンピュータにアクセスすることができるという利点を提供してくれる
※1 WINS = NBT の世界における DNS のようなもの
NetBEUI(ネットビューイ)
初めて Windows にネットワーク機能が標準搭載された Windows95 の既定のプロトコルは、TCP/IP ではなく NetBEUI というものでした。NetBEUI は NetBIOS という API を利用していました。NetBEUI は TPC/IP とはまったく異なる考え方のプロトコルです。IP アドレスはなく、ルーティングも行いません。名前だけ決めておけばアクセスできるという、非常にシンプルな考え方のプロトコルです。
NetBEUI は現在ではほとんど使われません。それは、次の点で現在のネットワーク環境に合わなくなってしまったからです。
- ルーティング機能がないため大規模なネットワークには向かない。
- インターネットが普及し、NetBEUI との相互接続性に問題がある。
Microsoft は、TCP/IP の上で NetBIOS の API を使えるようにするという戦略をとりました。これを NetBIOS over TCP/IP といいます。
Windowsインフラ管理者入門 P123-124 より引用
LLMNR(Link-local Multicast Name Resolution)
- NBT より新しい名前解決プロトコル
- IPv6 の名前解決に対応(NBT は IPv6 非対応)
- NBT がブロードキャストを利用するのに対し、LLMNR はマルチキャストを利用
- NetBIOS という規格自体が古くてセキュリティ強度に問題があるため、NBTはなるべく使わない方向に向かいたいがゆえのプロトコル
- ホップリミットが1しかない仕様のため、ルータ越えができない(同一ネットワーク内での名前解決のみ対応)
検証環境について
ここからは実際の動きを見ていく。改めて検証環境を以下に記す。
- 構成は「192.168.1.16」の Windows Server 2016 と 「192.168.1.10」の Windows 10 の2台構成
- それぞれ「SV01」と「PC01」というコンピュータ名を設定
ファイアウォールで ping を許可する
PC01 は「ゲストまたはパブリック ネットワーク」に接続されている。
既定では「ICMP エコー要求」が許可されていないので、SV01 から PC01 に ping を打ったとしても、PC01 のファイアウォールでブロックされ ping に応答しない。
ping に応答するようにファイアウォールを設定する。「詳細設定」から「受信の規則」を開き、「ファイルとプリンターの共有(エコー要求 – ICMPv4受信)」を許可する。
※ PC01 が接続しているのは「パブリック」となっているため、プロファイルが「プライベート,パブリック」になっているものを許可する
なお、ping や名前解決を含むすべての操作は「SV01 → PC01」の方向で行うため、SV01 のファイアウォールの設定は初期値のまま変更しない。
LLMNR による名前解決
ここからは実際の動きについて解説する。
まず、キャッシュで名前解決が行われないように DNS キャッシュ、NBT キャッシュを削除する。削除するコマンドはそれぞれ以下の通りだ。
DNS キャッシュの削除
NBT キャッシュの削除
nslookup で PC01 の名前解決ができないことを確認する(下図参照)。名前が解決できなかったことから、DNS を利用した名前解決ができないことがわかった。
次に「ping PC01」コマンドを入力するが、名前解決に失敗している。「ping 192.168.1.10」の場合は ping に応答があることから、純粋に名前解決に失敗しただけということがわかる。
SV01 と PC01 は同一ネットワーク内にいるため、LLMNR もしくは NBT による名前解決が行われるはずだ。
ここで名前解決に失敗したのは、LLMNR と NBT が PC01 のファイアウォールでブロックされていたからだ。
ファイアウォールで LLMNR を許可する
検証環境の説明では ping に応答するように ICMP エコー要求を許可するルールをファイアウォールに追加した。
それと同じように、環境によっては(例えば今回のようにパブリックネットワークに接続している場合) LLMNR がファイアウォールで許可されていない可能性がある。
LLMNR を許可するため、PC01 の「受信の規則」で「ネットワーク探索(LLMNR UDP 受信)」を許可する。
LLMNR による IPv6 名前解決
LLMNR を受信できるようにファイアウォールの設定を変更したところで、もう一度「ping PC01」を実行してみる。
すると下図のように、「PC01 [ IPv6 アドレス ]に ping を送信しています」と表示されたのちに ping がタイムアウトしている。つまり名前解決には成功しているが、ping は失敗している。
ping に失敗した理由は PC01「ファイルとプリンターの共有(エコー要求 – ICMPv6受信)」が許可されていないからだ。冒頭で ping に応答するように「ICMPv4受信」は許可したが「ICMPv6受信」は許可していない。
上記の実行結果から以下のことがわかった。
- LLMNR は少なくとも IPv6 の名前解決には成功した
- ping は IPv4 よりも優先度が高く設定されている IPv6 を利用して エコー要求を行った(IPv4 と IPv6 の優先度に関しては別記事に記載)
- IPv6 エコー要求に対する受信を PC01 で許可していなかったため、ping に失敗した
ping が返ってくるように PC01 の「ファイルとプリンターの共有(エコー要求 – ICMPv6受信)」を許可する。
そうすることで「ping PC01」に対する ping 応答が返ってくるようになる。
IPv6 を無効化すると LLMNR は動作しなくなる
IPv6 による ping は成功したが、主流は未だに IPv4 だ。
そこで、IPv4 で ping を実行するため、送信側である SV01 の IPv6 をアダプタのプロパティから無効化する。
その状態で「ping PC01」を実行すると、名前解決に失敗する。
確認のため、SV01 の IPv6 を再度有効化する。
IPv6 を有効化した結果、名前解決に成功するようになった。
これらの結果から、Windows における LLMNR は IPv6 を無効化すると名前解決に失敗することがわかった。
IPv4 を優先した場合の LLMNR の挙動
上記では IPv6 を無効化したが、運用としてこれはよくない。
詳しくは以下の記事を参照してほしいが、Microsoft の推奨は IPv6 の無効化ではなく IPv4 の優先度を上げる運用だ。
よって、IPv4 で ping を行いたい場合 IPv6 を有効化したまま IPv4 の優先度を上げる。
上記の記事では IPv4 の優先度を上げる方法をいくつか紹介しているが、本記事では単純に以下のレジストリを作成し、データを「0x20(IPv4 を優先)」にする。
この状態であれば IPv4 で ping は飛ぶはずなので、許可していた PC01 の「エコー要求 – ICMPv6受信」を無効化(拒否)する。
ping を実行すると、名前解決に成功し ping の応答も確認できた。
なお、この状態で IPv6 を無効化しても名前解決には失敗するようになる。
つまり、IPv4 が優先されていようと IPv6 が無効化された時点で LLMNR は名前解決を行わない。
LLMNR 実際のパケット
LLMNR で名前解決が行われた際の実際のパケットを見てみる。
下図は PC01 で取得したパケットだ。SV01 で IPv6 が有効になっている状態、つまり LLMNR による名前解決と ping に成功したとき、PC01 ではこのようなパケットのやり取りを行っていた。
これを見る限り、やはり LLMNR は IPv4、IPv6 の両方で名前解決を行っていることがわかる。
そして下図が SV01 で IPv6 を無効化した際のもの。
SV01 から LLMNR のパケットが一つも飛んできていない。LLMNR は IPv6 を無効化すると名前解決を一切行わないことがわかる。
なお、送信側を Windows Server 2008 に変更して試してもみたが、まったく同様の結果、同様のパケットの流れになった。
LLMNR キャッシュについて
ここで LLMNR のキャッシュについて紹介する。
正直な話、LLMNR のキャッシュを確認することはできなかった。
ただし、PC01 のファイアウォールで LLMNR を許可するポリシーを無効化した直後から ping の応答が返ってこなくなったことから、キャッシュは存在しない、もしくはキャッシュしていても利用しないことはわかった。
Reference
Correct that a LLMNR cache does not exist in Windows 7 / Server 2008 R2 ?
NBT による名前解決
次に NBT による名前解決を実際に行っていく。
ファイアウォールで NBT を許可する
NBT も LLMNR 同様ファイアウォールでブロックされている場合がある。PC01 のファイアウォールで「ネットワーク探索(NB名受信)」を許可する。
なお、先ほどの検証で許可していた LLMNR のポリシーは既定値(拒否)に戻しておく。
NBT による IPv4 名前解決
この状態で「ping PC01」を実行すると、名前解決に成功し ping に応答がある。
IPv6 を無効化した場合の NBT の挙動
LLMNR では IPv6 関連でトラブルがあり中々 ping の応答が返ってこなかったが、NBT はすぐに成功してしまった。
それは NBT がそもそも IPv6 の名前解決に対応していないからだが、一応 IPv6 を無効化する検証を行ってみる。
やはり、NBT は IPv6 を無効化しようが名前解決に成功してくれる。
NBT 実際のパケット
NBT で名前解決が成功した際のパケットを見てみる。これも PC01 でキャプチャしたものだ。
NBT の名前解決は非常にシンプル。No1 で SV01 から PC01 に query がブロードキャストされ、No2 で PC01 から SV01 に response が返されている。
なお、LLMNR はファイアウォールで許可されていないので query ばかり飛んでいる。
そして下図が IPv6 を無効化したときのものだ。LLMNR のパケットが一切飛んでいないのですっきりしている。もちろん、ping には成功している。
NBT キャッシュについて
LLMNR と違って NBT のキャッシュを確認する方法は簡単だ。以下のコマンドを実行することで NBT キャッシュの確認が行える。
NBT キャッシュの確認
NBT のキャッシュはデフォルトで600秒(10分)だ。600秒以内であれば NBT で名前解決が行えない状況でも コンピュータ名を使った通信を行うことができる。
別ネットワーク間の名前解決
別ネットワーク間の名前解決を DNS 以外で行いたい場合を考える。SV01 と PC01 に別ネットワークの IP を設定し、ルータを挟む。
この状態では「ping IPアドレス」には成功しても「ping ホスト名」は失敗する。
先述したが、LLMNR はホップリミットが1しかない仕様なのでルータを超えられない。NBT は名前解決にブロードキャストを使用するのでブロードキャストドメイン(ネットワーク)から外に出ることができない。
だが、NBT には別ネットワークのコンピュータの名前解決を行う手段が2つ用意されている。
「lmhosts」ファイルを使う方法と「WINS」サーバを使う方法だ。
別ネットワークへの ping が飛ばない場合
lmhosts と WINS の前に、そもそも「ping IPアドレス」に失敗する場合。その場合はファイアウォールの設定を見直す。
「エコー要求 – ICMPv4受信」のプロパティを見てみると、ローカルサブネットしか許可されていないことがわかる。
SV01 のネットワークアドレスを追加する。
そうすれば「ping IPアドレス」が通るはずだ。
「lmhosts」による名前解決
NBT の名前解決は 「lmhosts(Lan Manager hosts)」というファイルを作成することで静的に行うことができる。
Windows Server 2016 の場合 lmhosts は既定で存在しない。なので「C:\Windows\System32\drivers\etc」にある「lmhosts.sam」というサンプルファイルを複製して作成するとよい。
ただし lmhosts には拡張子が無いのでそのように作成する。
作成した lmhosts ファイルに以下のような書式で IP アドレスと NetBIOS 名(コンピュータ名とほぼ同義。実際は少し違う。詳細は別記事を参照)を記載する。
そうすることで別ネットワーク間のコンピュータ同士が名前により通信ができる。
lmhosts.sam を使用した場合
ちなみに、lmhosts.sam に IP アドレスと NetBIOS 名を記述したところで名前解決は行われない。
そもそも、「This is a sample LMHOSTS file」と書いてある。
一応、静的に登録してみる。
案の定失敗する。意味がないのでこんなことはしないように。
「WINS」による名前解決
WINS による名前解決は別記事を作成予定。
LLMNR と NBT による名前解決。覚えておいてほしいこと
LLMNR
- IPV6 を無効化すると LLMNR は機能しなくなる
- キャッシュが存在しない可能性あり(存在したとしてもキャッシュで名前解決はしない)
NBT
- IPv6を無効化しても NBT は機能する
- 名前解決の結果を600秒間キャッシュする