Windowsネットワークについて調べてみた

アンドキュメンテッドMicrosoftネットワーク」を読んでから数週間でファイルサーバ(Samba)に接続できなくなってこの世の必然性みたいなものに関して思いを馳せていた。
ファイルサーバの状況等を確認すると

おそらく原因はSamba機をDHCP経由でIP取得するよう変更したせいでdhclientが余計なお節介をしてくれてるのかな?とまでは想像できたのですが、
そもそも本を流し読みしたせいで詳細まで把握できていなくて問題解決に時間がかかったのと、せっかく実際にトラブルに見舞われたのだからこの際復習しましょう、ということでメモ。

「アンドキュメンテッドMicrosoftネットワーク」について

MicrosoftWindows共有等の仕様について一部は公開しているが、
実装と違ったり、拡張されたりしてしまっている。
そのため、パケットキャプチャを交えてWindowsの実際の挙動を解説している本。
ただし古い本なのでWindows Vista以降の情報は載っていない。
が、これほど詳しく解説している本はないので、Windowsネットワークについて知りたい人はぜひ読んでみると良いと思う。

この記事で解説している事

  • NetBIOSのプロトコルについて
  • WINSサーバの役割について
  • 名前解決について

この記事で解説してない事

用語の整理

NetBEUI != NetBIOS

良く混同されているが、2つは違うレイヤの用語。
NetBIOSはインターフェースであり、
使用するプロトコル(NetBIOSの下のレイヤ)には、NetBEUI、IPX/SPX、TCP/IPがある。
今最も使われているのはもちろんTCP/IP
TCP/IPベースのNetBIOSをNetBIOS over TCP/IPと言い、よくNBTと略される。
昔はNetBIOSのプロトコルと言えばNetBEUIしかなかったため、
冒頭の2つが混同される原因となっている。

コンピュータ名 != ホスト名

コンピュータ名とはシステムのプロパティ画面で確認できるこれの事。
ちなみにこの画面はWindowsキー + Pause/Breakキーでも出せる。
さらに言うとコンピュータ名だけならコマンドプロンプトで「hostname」を実行すれば確認できる。

コンピュータ名はホスト名とは違っていて、むしろIPアドレスに似ている。
ホスト名は解決されIPアドレスとして通信されるが、コンピュータ名はIPアドレスと同じく相手を特定する一意なもの(だから他のPCと重複するのは×)。
つまり「TEST1」というコンピュータ名のままパケットに含まれ通信される。


…しかしこれはNetBEUI環境での話であり、現在主流のNBT環境では話が異なる。

NBT環境での名前解決

そもそもコンピュータ名で相手を特定するなら名前解決する必要あるの?と思うだろう。
前項で言ったように、コンピュータ名で相手を特定するのはNetBEUI環境での話であり、現在はIPベースのNBT環境では当然通信するにはIPアドレスで相手を特定しないといけない。

登録されているコンピュータ名とIPアドレスが、実際と違っていた場合どのような事が起きるか。
この場合NetBIOSレベルでは名前解決できないものの、TCP/IPレベルでは名前解決できるという事になる。
結果としてファイルサーバに接続できない。
ただ、Windows NT 4.0 SP6a / 2000 / XP以降だとCIFS(Common Internet File System)というプロトコルで通信が行われる。
この際「SMBSERVER」という特殊なコンピュータ名を用いてIP通信するので、もしかしたらコンピュータ名が間違っていても通信できる事もあるかも?
詳しくは「名前解決の順序」の項で書く。


これは私見だけど、Windows PCをあるセグメント*1に繋げたい場合、IPアドレスと同様、コンピュータ名が被ってないかの確認もした方がいい。
Windowsは起動時やコンピュータ名を変えた際に自身のコンピュータ名を他のWindows PCに登録させるパケットを送る。
この時コンピュータ名が重複していると(ARPキャッシュみたく無条件で古いエントリを上書きしたりはしないものの)他のWindows PCで「nbtstat -n」を実行すると「Conflict」と表示される状態になるようだ。*2
Windows PCが「Conflict」な状態になると通信とかできるんだろうか?
コンピュータ名が被ってもNBTは結局IPベースなので、通信不可能にはなったりはしないんじゃないだろうか。たぶん。
何しろ被らない方が良い事は確かで、そういえば前「localhost」って登録したWindows PCを社内ネットワークに繋げた途端大混乱が起きたとかいう噂話をネットで聞いた覚えがあって、大変楽しそうだった。



ブラウズリスト

Windowsは起動時やコンピュータ名を変えた際に自身のコンピュータ名を他のWindows PCに登録させるパケットを送る。」と書いたが、このコンピュータ名の一覧はブラウズリストと呼ばれる。
ARPキャッシュ(MACアドレスIPアドレス)のコンピュータ名バージョン(コンピュータ名⇔IPアドレス)と考えるといいかもしれない。
ブラウズリストは「nbtstat -c」で確認できる。
ブラウズリストは「nbtstat -R」でクリアできる…が、コマンドプロンプトを管理者権限で実行しないと「NBT リモート キャッシュ テーブルを削除できませんでした。」と表示され、削除できない。
UACが導入されるXP以前の記事をよく確認せず実行し、エラーも見ないとハマる。技術者ならそんな事はしないとは思うけど。
管理者権限で実行すると「NBT リモート キャッシュ ネーム テーブルを正常に削除し、事前に読み込みました。」と表示され、無事削除される。

NBT環境でのサブネットを越えた通信

NBTはIPベースなので当然サブネットを越えた通信ができる。
が、ブロードキャストで名前解決を行うため、通常サブネット越えができない。
名前解決を行うためには、LMHOSTSファイルにファイルサーバのIPアドレスを記載するか、WINSサーバ(コンピュータ名に対するDNSサーバのようなもの)に問い合わせる必要がある。

名前解決の対象 ファイル サーバ
コンピュータ名 LMHOSTSファイル*3 WINSサーバ
ホスト名 HOSTSファイル*4 DNSサーバ

WINSサーバが設定されている場合の名前解決の挙動の違い

Windowsのコンピュータ名の名前解決の挙動はWINSサーバが設定されている場合とされていない場合で大きく異なる。

WINSサーバが設定されていない場合

ブロードキャストで名前解決を行う。
特にWINSサーバを設定していなければ通常この挙動となる。

WINSサーバが設定されている場合

ユニキャストでWINSサーバに問い合わせて名前解決を行う。
一定間隔ごとにブロードキャストで名前解決を行わないため、トラフィックの削減にもなる。
WINSサーバはSambaで構築できるらしいけど、詳しくはググってください(丸投げ)。

名前解決の順序

Windowsの名前解決は複雑怪奇で、本書にも

このあたりの動作についてはコマンドの実相と名前解決機能の実装との切り分けが困難なため、どこまでが名前解決機能の実装なのかについては、筆者も把握しきれていない面があります。

と書かれていて、大変絶望感がある。


ドットが含まれていればホスト名として判断され、DNSを使うみたいな話もあるらしいが、

しかし筆者が、Windows NT Server 4.0 SP4 と Windows 2000 Server SP2 のマシンで、NET VIEW \\computername コマンドを用いて実際に確認したところ、15文字以下の名前はピリオドの有無に関わらず、通常のNetBIOS名として名前解決が行われました。

とも書かれていて、仕様と実装が違ったりする。
そもそもこの様に仕様と実装が違う事が多々あるため、
本書ではパケットキャプチャのスクリーンショットを付けているらしい。
Sambaは頑張ってるんだろうなぁとか思ったりする。


またノードタイプというのもあり、
このタイプによりWINSサーバやブロードキャストでの参照の順序や有無が違ったりするので、
詳しくは本書を買ったり、本書の様にパケットキャプチャ等を用いて
実際の挙動を探ったりするしかなさそう。

感想

なんだかMicrosoftの技術ってパッと見シンプルなように見えるけど詳細を見ると所々に後方互換性のための変な仕様に引きずられていて人生ですなぁという感じがする。
名前解決の順序にしても、WINSサーバがいなければブロードキャストで通信、WINSサーバがいればユニキャストで通信って仕様はある意味シンプルなように聞こえるけど、NetBEUIとの互換性の為に複雑怪奇な仕様になってしまっていて、技術的負債感をすごく感じる。

*1:この記事では「ネットワーク」だとややこしいので「セグメント」という用語を使う事にする

*2:起動したWindows PCの方ではログイン後にエラーダイアログとか表示されるんだろうか。良く分からない。あとコンピュータ名とは関係ないけど、IP取得のタイミングってログイン後で合ってるんだろうか?ちなみにコンピュータ名をシステムのプロパティ画面で変えた時は「重複してますよ」ってダイアログメッセージが表示される。

*3:%WINDIR%\drivers\etc\lmhosts

*4:%WINDIR%\drivers\etc\hosts