付録2 MSN Messengerのファイル転送障害

2003/1/22作成


MSN Messengerのファイル転送機能はあんまり評判がよくありません。
なぜかというと、NAT環境では使えないのです。
パケットキャプチャしてみてびっくり。プロトコルさぼりすぎ。
ちなみに、MSN Messengerに関するドキュメントは見つけることができなかったのでここに書いてあるのはキャプチャしたパケットから想像したものです。
著しく事実と違っても保証しかねますのでご了承ください。
もし、事実とちがっていることを見つけた方は指摘してもらえるとうれしいです。



1.MSN Messengerが使うポート

MSN Messengerは主に以下のポート番号を使います。
ポート番号 宛先 メモ
1863 MSNのサーバ 通常のチャットはこっちを使う
6891〜6900 ファイルを渡す相手 ファイル転送は直接行う
ファイル転送をする際には一旦1863を使ってアナウンスして、それからファイルを送信し始めます。

2.1863ポートの動き

通常のメッセージのやりとりは書いてもあんまりおもしろくないのでいきなりファイル転送の時の動きを説明します。
1863ポートによって送られるパケットって実はHTTPにすごく似ています。
MSG ****@****.**.** 293 ・・・・(1)
MIME-Version: 1.0  ・・・・(2)
Content-Type: text/x-msmsgsinvite; charset=UTF-8  ・・・・(3)

Application-Name:  ・・・・(4)
Application-GUID: {ABCDEFGH-0123-4567-BBBB-FFFFFFFFFFFF}  ・・・・(5)
Invitation-Command: INVITE  ・・・・(6)
Invitation-Cookie: 12345  ・・・・(7)
Application-File: hogehoge.dat  ・・・・(8)
Application-FileSize: 1024  ・・・・(9)
まず(1)、メッセージタグがあり、そこには送信元が書いてあります。MSNではメールアドレスが識別子になっていますね。
こっちからの送信データにはこのアドレスがかかれていないのでおそらくMSNのサーバでくっついてくる情報だと思います。
その後の293という数字はステータスコードか何かだと思います。

つづいて(2)と(3)。おなじみのHTTPのMIMEバージョンとコンテンツのタイプですね。
何となくこの2行は80番ポートのプロクシを通したときのためなような気がします。

(4)はアプリケーションの名前ってことになっています。ここには実データとしてはバイナリ形式になっているため読めませんでした。
(5)のGUID。ドキュメントがないのでなんだかよくわかりません。一つ気づいたのは、最後のFFFFFFFFFFFFのところにはなにやらMACアドレスっぽい数字が入っていました。GUIDっていうくらいなのでなんかのIDだと思います。
(6)はコマンドです。INVITEなので取りに来いと行っているんでしょう。
(7)はクッキーです。こいつがセッションIDみたいになっています。
肝心の(8)と(9)です。(8)には送りたいファイル名がかかれています。(9)はそのファイルのサイズ。
ひとまずこの情報が送信元から届きます。
すると・・
MSG 138 U 181 ・・・・(1)
MIME-Version: 1.0  ・・・・(2)
Content-Type: text/x-msmsgsinvite; charset=UTF-8 ・・・・(3)

Invitation-Command: ACCEPT ・・・・(4)
Invitation-Cookie: 12345 ・・・・(5)
Launch-Application: FALSE ・・・・(6)
Request-Data: IP-Address: ・・・・(7)
こんなメッセージが受信側から送られます。
(1)はステータスコードか何かでしょう。たぶんこの後MSNのサーバでここが置き換わるんだと思います。
(2)と(3)はいいですね。
(4)はさっきのINVITEコマンドに対してACCEPTを出しています。受信OKだよと言う意味でしょう。
(5)は送信元が出したクッキーと同じですね。これでセッションを管理しているんだと思います。
(6)は上の(4)で指定したアプリケーションを立ち上げようとしたのですが、失敗している様子だと思います。よくわかりません。
(7)ではACCEPTのためのIPアドレスを要求しています。
要するに準備OKなのでホストの情報をくれという意味の通信です。
そうして送信元から送られてきたのがこちらです。
MSG ****@****.**.** 239 ・・・・(1)
MIME-Version: 1.0 ・・・・(2)
Content-Type: text/x-msmsgsinvite; charset=UTF-8 ・・・・(3)

Invitation-Command: ACCEPT ・・・・(4)
Invitation-Cookie: 12345 ・・・・(5)
IP-Address: 192.168.0.1 ・・・・(6)
Port: 6891 ・・・・(7)
AuthCookie: 21513 ・・・・(8)
Launch-Application: FALSE ・・・・(9)
Request-Data: IP-Address: ・・・・(10)
(1)、(2)、(3)は説明済みなので省略
(4)は一つ前のコマンドに対するACCEPTでしょう。
(5)はさっきから出ているクッキーのセッションIDです。
問題は(6)です。
(6)でIPアドレスを相手に通知するのですが、NATを使っている場合、まさに自分の生アドレスを入れているので問題が起こってしまいます。
ここにちゃんとグローバルアドレスが入っていれば問題ないのですけどね。
このあと、正常な状態では(6)のIPアドレスの(7)に向けてデータを送りつけます。
手順だけを見るとftpのPASVモードに似ています。
ということでおさらいすると、一連の流れはこんな感じです。
1.送信側が送信したいと受信する相手に伝える(tcp/1863)
2.受信OKだったら受信側が相手に準備完了の合図を送り、取りに行く場所を聞く(tcp/1863)
3.受信相手に自分のIPアドレスと待ち受けポート番号を通知する(tcp/1863)
4.送信側によって通知されたIPアドレスとポート番号を使って受信側がセッションを開始する(tcp/6891〜6900)
5.受信側によって開始されたセッションを使って送信側が受信側にデータを送る(tcp/6891〜6900)

3.対処

まず、直接マシンをインターネットにつないでグローバルアドレスが割り振られている場合は問題ありません。パーソナルファイアウォールを入れている人はポート開けるのだけ注意すればOKです。
それからMSN Messengerの状態監視エンジンを搭載しているNAT箱も問題ありません。
こういうNAT箱はデータグラム中のIPアドレスとポート番号を監視してMSN Messengerが使う一連のNAT情報やらNAT変換ルールをまとめて設定してくれます。最近こういうNAT箱(ブロードバンドルータ)増えてます。Planexあたりから出てるみたいです。
あと、ブリッジタイプとかステルスタイプとか呼ばれているファイアウォールを使っている人もOKだと思います。
こういう環境が無い場合、どうすればいいかを検討してみましょう。
基本的にはxdmcpのところで書いた方法が使えますが、別の側面からも見てみたいと思います。
MSN Messengerの仕様
元はといえばMSN Messengerの仕様がいけてないのがダメなのです。
転送元のIPアドレスを自己申告制ではなく、MSN Messengerのサーバにパケットが届いた時に、パケットのSrcアドレスを入れて受信側に渡してあげれば送信側の静的IPマスカレードの設定だけすればOKなのです。
ソフトウェアの仕様
相手に通知するIPアドレスを手動で設定するようなオプションが付けばとりあえずの対処にはなります。
あとは静的マスカレードを忘れずに。
VPN
xdmcpで書いたようにVPNを使う方法はどうでしょう?
ただし、MSNのサーバとの通信をしなければいけないので、ファイル転送のポートだけがIPカプセル化するように工夫することになると思います。
面倒な上にうまく動くかわからないのであまりおすすめできません。
相手のアドレスをこっちでNAT
これもxdmcpに書いた方法ですが、自分のNAT箱に相手のプライベートIPアドレスをグローバルアドレスに変換してあげればとりあえず相手のルータまでは届きます。
あとは相手にポートを開けてもらって静的マスカレードでパケットをリダイレクトでOKなはずです。
とはいうものの、WindowsXPのメッセンジャーはその辺が対策済みだそうです。
偽メッセンジャーとかも対応されていたりされていなかったりしているようです。
もう少し待てばこのコンテンツも意味がなくなるかもしれません。

参考文献

偽メッセンジャー  http://homepage3.nifty.com/yamaneko/index.html
MSDNドキュメント(英語) .Net Messenger Service Application Programming Interfaces
YAMAHA RTルータシリーズ ネットワークゲームのためのヒント http://www.rtpro.yamaha.co.jp/RT/docs/game/index.html
同、FTPのPORTとPASVの説明 http://www.rtpro.yamaha.co.jp/RT/FAQ/IP-Filter/public-ftp-server.html

謝辞

データ収集に協力してくれた悠翔くんありがとう。

もどる