読者です 読者をやめる 読者になる 読者になる

カイワレの大冒険 Third

技術的なことや他愛もないことをたまに書いてます

Flashとフォワードプロキシ

トラブルシューティング トラブルシューティング-Flash

寒すぎて風呂が常に恋しくなる@masudaKです。 FLASHで作られたサービスに長く携わっていることもあり、ちょっとハマったので、残しておきます。 やりたいことは、FLASHで作られたゲームをフォワードプロキシ経由で表示させること。

要は、こんな感じ。

自分のPC - フォワードプロキシ - リアルサーバ(apache, socket)

単にWebサーバにつなぎに行くだけなら難しくありません。

Squid立てて、以下の様な感じの記述をしておけば、最低限動くでしょう。

acl Safe_ports port 80          # http
http_access deny !Safe_ports

あとはACLの設定すればいけるかと。

しなしながら、FLASH Playerを経由したRTMP通信をプロキシ経由にさせようとすると、以下の様な方法ではうまくいきません。

acl Safe_ports port 80          # http
acl Safe_ports port 843         # crossdomain
acl Safe_ports port 1935        # rtmp
http_access deny !Safe_ports

これではダメなのです。では、どうダメなのか。

Config

まず、Safe_portsだけではだめ。

acl SSL_ports port 1935

のようにSSL_portsとしても扱ってあげる。要はSafe_portsとSSL_ports両方が必要になります。

通信

加えて、ブラウザでプロキシの設定をしても、SWFはプロキシを介してくれません。 これは仕様らしく、wiresharkとかでパケットみないと分からないかも。

要は直接サーバとソケット通信しようとしてしまうのです。 そのため、プロキシを介すように魔改造をしなければならない。

そこで見つけた以下の記事。 要はRFC準拠した形でソケット通信する部分のクラス(flash.net.Socket class)を書き換えればいけるでしょうと。

これが提案されているクラス。

んで、これを反映したswfを使って (デベロッパーの方ありがとうございます> <)、通信させると、プロキシは通ってくれる。

クロスドメイン

しかしながら、デベロッパーツールとかで見ると、以下の様なエラーが見られる。

Delegate::onError, [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]
RootModel::showError, 通信エラーが発生しました。

セキュリティエラーが発生してしまいました。なぜなのか。

どうもローカルに落としたSWFは、別ドメインとしてのプロキシサーバにアクセスしにいきます。 ただし、プロキシサーバはそれに答えられない。 そのため、crossdomainの部分でセキュリティ上エラーを吐いてしまいます。

なので、crossdomain.xmlを返せるようにします。

Apacheでさくっとやるなら、

# wget http://www.beamartyr.net/projects/mod_adobe_crossdomainpolicy.c
# ./apxs -c -i mod_adobe_crossdomainpolicy.c

// modules/mod_adobe_crossdomainpolicy.so ができあがるので、conf/extra/httpd-crossdomain.confを作る
# vim conf/extra/httpd-crossdomain.conf

// 以下を記入
LoadModule adobe_crossdomainpolicy_module modules/mod_adobe_crossdomainpolicy.so
Listen 843
<VirtualHost 0.0.0.0:843>
  AdobePolicyFileServerEnabled On
  AdobePolicyFile [crossdomain.xmlの絶対パス書く]
</VirtualHost>

// crossdomain.xmlにはこんな感じで書いておく
<cross-domain-policy><allow-access-from domain='*.test.com' to-ports='*'/></cross-domain-policy>

あとはapache再起動して、以下で確認。crossdomain.xmlの中身が返ってきたら、OK。

perl -e 'printf "<policy-file-request/>%c",0' | nc 127.0.0.1 843

ここまでできたらSqiud再起動して、FLASHがプロキシ経由できるか見てみましょう。

終わりに

なんか色々ハマるところが多かったので、苦戦しました。 ソケット通信部分のクラスを改造したりしなきゃなので、あまりスマートな解決とは言えないかもしれません。

他にもっといい方法があるかもしれませんが、とりあえず。 間違い等あれば@masudaKまでお願いします。