NetBIOS over ssh

 安全にWindows上でネットワーク越しに共有を読もうという、実用的なんだけどお馬鹿な試みに関する話です。
 sshの使い方とかは省略。環境はWindows XP Professionalしか試してません。たぶんWindows 2000でも平気だと思いますが。ちなみに、TCP port 445に関してはポート445(ダイレクト・ホスティングSMBサービス)に注意辺りを参照のこと。

問題点

 まず、単純にLAN上に非Windowsマシンがあれば、普通にsshのport forwardでport 139とか445でlistenすれば、そのマシンに繋ぐだけでできます。VMwareでもたぶん平気です。
 問題は、Windowsマシン単体で実現する方法です。
 最大の問題は、WindowsにささっているNICは、必ずport 137〜139,445が起動時に先にbindされてしまっているためあとからbindできないことです。(どうも正確にはbindできるくせに無効という感じ)ネットワークの設定で「Microsoftネットワーク用ファイルとプリンタ共有」を外しても解決されません。
 さらに、explorerではUNC表記(「\\マシン名\共有名」のような書き方のことです)でport指定ができない上に、smb://な表記も受けつけません。
 つまり、ローカルマシンの上で、port 139または445にbindするのが必須ということになります。でも、それはできない、と。

方法

 とりあえず、なんとかしてbindしないといけないので、NetBIOSをNICから外します。具体的にはレジストリをいじります。
 ついでに、port foprward用のダミーのNICを用意して、ローカルでのNetBIOS共有に影響がでないようにします。port forwardでしかbindできなくなっちゃうのは困るので。

用意するもの

putty/plink
オリジナル
PuTTY: A Free Win32 Telnet/SSH Client
hdk氏による日本語対応パッチ版
PuTTY で ISO 2022 による日本語入力・表示を可能にするパッチ

stone
Simple Repeater `stone'

Microsoft Loopback Adapter Driver
OSがあれば普通にinstallできるとおもいます。
NetBIOSを絶対つかわないというNICがあれば不要です。
その場合、以下では自分で読み替えてください。

実作業

 まず、Microsoft Loopback Adapter Driverをinstall。
 固定でIPアドレスを振ります。default gatewayとかDNSは不要。

 次に、どうにかしてMicrosoft Loopback Adapter DriverのデバイスID?を確認します。「{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}」みたいな奴です。
 「HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\」の下を「Microsoft Loopback Adapter」で検索すると「NetCfgInstanceId」というパラメータがあるところが見つかると思うので、その中身を確認すればわかります。
 もしインストールしていれば、etherealとかwindump -Dとかsnort -Wとかでもわかります。:)

 「HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBIOS\Linkage」と「HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NetBT\Linkage」の両方の「Bind」、「Export」、「Route」の中から、判明したIDを消します。
 一応、事前にレジストリ情報をexportしておくことをお勧めします。
 壊れても知りません。:)

 その後、たぶんrebootしないと駄目だと思います。

 これで、Microsoft Loopback Adapter Driverのport 139や445が空いている状態になっているはずなので、「stone localhost:140 ダミーNICに振ったIP:139」とかします。振ったIPアドレスのport 139はlocalhostのport 140に転送されるようになります。

 「plink -C -T -L 140:繋ぎたいサーバー:139 アカウント@sshするサーバー」もやります。cmd.exeが二つあがってることになりますが、まあこの辺は適当に。
 これで、localhostのport 140が、sshで繋いだサーバーから繋がる「繋ぎたいサーバー」のport 139に転送されます。

 explorerから「\\ダミーNICに振ったIP」とかいれると、stoneからplinkを経由して、繋ぎたいサーバーのSMB共有がみえるはずです。

 あー、めんどくせー。:)

残る問題など

 plinkがstoneのようにlocalhost以外のインターフェースにbindできるようになると、stoneはいらなくなるはずです。→できるようにしました。任意のインターフェースにbind可能なplinkを参照してください。
 あとMicrosoft Loopback Adapter Driverが10Mとかでるのが気になります…。速度は全く計測していませんが、本当に10MしかでないならBフレッツだとボトルネックになりそうな気がします。っていうか、10Mもでるのかな…。昔、えらく遅かった記憶が。

 ちなみに、対策せずにplinkでport 139や445にbindしようとするとできてしまいます。telnet 127.0.0.1 139するとたしかに有効になっているのが確認できます。接続先portをport 80とかにすると一発でわかります。
 が。explorerで\\127.0.0.1に繋ぐと、なぜかローカルの共有を見ます。ちゃんとしろー。おそらくexplorerがlocalhost(127.0.0.1)を特例扱いしてるのでしょう。これがうまくいけばMicrosoft Loopback Adapter Driverなんていらないのに…。
 なお、Zebedeeでよければたぶん受け側(サーバー)もWindowsでいけるし、clientは最初から個別インターフェースへのbind機能を持っています。(OpenSSHも持ってるわけだけど)ただし、僕はZebedeeは試してません。まあ、ZebedeeがFirewall越えられるかとかそういう問題になるわけで…。

任意のインターフェースにbind可能なplink

 というわけで任意のインターフェースにbind可能なplinkを作りました。
 Release 0.53ベースです。かなり適当なのでbugってたらすみません。覚悟の上でどうぞ。
 optionが二つ増えています。
 一つは、port forward時に任意のインターフェースにbindできるようにするオプションです。(-local_bind_address アドレス)
 もう一つは本家PuTTYのGUI版にある、他のホストからローカルのforward用ポートへの接続を許可する(Local ports accept connections from other hosts)オプションです。なぜかplinkでは指定できないのでoptionをでっち上げました。(-acceptall)
 
パッチバイナリーです。バイナリーはplinkだけです。どうせ英語しか出ないので英語版へのpatchですが、hdk氏のパッチを当てたあとでも当たると思います。コンパイルはmingwでやりました。(なのでpatchを当てるとmingw用のmakefileも増えます)
 コンパイル時には、-DLOCALBINDと-DACCEPTALLを付けてください。
 ちなみに、plinkではなくputtyの-local_bind_addressは、GUIをいじるのがめんどうなので対応してません。
 これで、stoneなしでいきなりport 139をbindできます。
 「plink -v -T -C -local_bind_address ダミーNICに振ったIP -acceptall -L 139:向こうのNetworkのSMBサーバー:139 アカウント@sshサーバー」こんな感じです。
 なお、plinkはそのままだとbindされているアドレス以外からのconnectionを弾くので、-acceptallは必須です。


このページへのリンクに関しては当然自由に行っていただいて構いません。
但し、コンテンツの著作権はLefに帰属します。
Copyright (C) 1999-2002 Lef. All rights reserved.