タグ別アーカイブ: 050plus-9911エラー調査

GP02,HW-01C,C01HW と Android で050 Plusを使う方法(ただし、未検証)

はじめに

前回まで、Androidから無線LAN(wifi)経由で050 Plusに接続しようとした場合9911エラーが発生することについて技術的な調査を行った。
その結果、AndroidのTLS接続と一部のルーターのDNSプロキシ機能の相性が悪いことが問題の原因であることが判明した。
技術的なことは前回までに説明したので割愛し、今回は、個人レベルで行える解決策についてまとめたいと思う。

これから示す手順の要点はAndroid端末のDNS設定に「8.8.8.8」(Google Public DNSのIPアドレス)を設定することである。
Rootを取っている方ならば、Set DNSなどのアプリを用いて端末のDNSの設定を書き換えることができる。また、静的IP設定でDNSの設定を行うこともできる。
だが、前者はrootを取る必要があり、後者は他の無線LANに接続するときに問題が発生する可能性があるため、あまりお勧めできない。(2011/10/28 追記有り)

ここでお勧めするのはルーターのDHCP設定を書き換えることで、端末に自動設定されるDNSを変更するという方法である。

インターネット上を徘徊していると、GP02、HW-01C、C01HWなどのポケットWifiを使用時に不具合を感じている方が多いようなので、この機種での設定方法を説明する。基本的にこれらの3つの機種は、同一の製造元のため、設定方法もだいたい同じである。なお、僕はこの機種を持っていないので、取扱説明書をもとに手順を示す。したがって、設定が正しく動作しない場合もあるので自己責任で設定を行っていただきたい。

このページで説明する設定手順の対象者

以下の条件をすべて満たす人は、このページで説明する設定を行うことで改善できる可能性がある。

  • iPhoneやiPod Touchでは050 Plusに接続できるのに、Androidでは接続出来ない
  • エラー番号が9911である

設定方法

  1. まず、ポケットwifiの設定画面をブラウザで開く。(たぶん、http://192.168.1.1/ 。この時点で意味が分からない人は悪いことは言わないので、諦めて下さい)
  2. ユーザー名とパスワードを入れる。初期設定であれば、ユーザー名は「Admin」。パスワードはGP02, C01HWの場合、本体に貼られているラベルのWEP Keyの値。HW-01Cの場合は「0000」。
  3. 左側のメニューから「設定」をクリックする
  4. 「設定」画面が開いたら「ファイアウォール設定」をクリックする
  5. 「ファイアウォール設定」画面が開いたら、「DHCP設定」をクリックする
  6. 「DHCP設定」画面が開いたら、以下の通り設定値を変更する。
    • DNS設定: ダイナミック→スタティック
    • プライマリDNS: (空欄)→8.8.8.8
    • セカンダリDNS: (空欄)→192.168.1.1 (追記:もしかするとこれが原因でうまく動かないかもしれないので一応取り下げ)
  7. 「適用」ボタンをクリックする
  8. 確認画面が表示されるので、「OK」ボタンをクリックする
  9. ポケットWifiが再起動する
  10. 念のため、Android端末も再起動する

これで、正しく設定されていれば、Android端末に自動的に割り当てられるDNSサーバーは「8.8.8.8」と「192.168.1.1」になるはずだ。
8.8.8.8はGoogle Public DNS、192.168.1.1 はポケットWifiのDNSプロキシである。何故後者も設定するかというと、設定画面の表示に使用される可能性があるからだ。

この要領で設定すれば他のポケットWifiにも応用出来ることだろう。

この設定を行った後で、050 PlusをAndroidで起動してみると正常に050 Plusに接続出来るはずだ。

おわりに

なお、キャリアでパケットがブロックされる場合(日本通信やドコモのデータ端末回線?)は、この設定を行っても改善しない場合がある。
また、C01HW使用時は、softbankエリアからemobileエリア(サブエリア)にローミングが行われたときに接続が失われる可能性があり、ポケットwifiの仕様により長時間通信が行われない場合は自動的に切断されてしまう可能性もある。これらの理由により接続が中断された場合、050 Plusアプリは再接続性能が良くないので、再接続されない可能性がある。

他にも様々な問題があるが、この記事が少しでも役に立てば嬉しく思う。

追記(2011/10/10)
HW-01Cではこの設定では上手くいかないという報告があった。手元に同一機種がないので検証できないが、もし機種の問題であればほぼ同一機種のC01HWやD25HWでも同様に上手くいかない可能性がある。

追記(2011/10/28)
れおさんより以下の情報を頂きました。

一番素直な解決法として、Wifi Staticというアプりがあります。
アクセスポイント毎に静的IPの設定を覚えてくれるので、
複数のアクセスポイントを使う場合でも、ほぼ自動で切り替えてくれるので
これを使ってみています。

未検証ですが、たぶん上手く動作すると思いますので、DHCPのDNSの設定が存在しないルーターをご使用の方は「Wifi Static」というアプリをお試し下さい。

個人的には、もしルーター側のDHCPのDNS設定を変更することが可能なのであれば、アプリ導入等で端末の設定を変更するよりも、ルーター側の設定を変更することをお勧めします。(ただし、ルーターに繋がらなくなっても復旧出来る自信がある場合に限りますが)

追記(2011/12/05)
こちらのブログで、「Wifi Static」の設定方法が紹介されています。

追記(2012/01/28)
いつの間にか本家のほうで対策がとられたようです。
今回の問題の原因であったDNS逆引きも正常に行えるようになっており、問題は解決したと思われます。

050 plus がwifiで接続出来ない件について調査3(解決編) 原因はDNSだった


050 plus のポート関連について調査2(まだ未解決)
の続きです。

記事にコメントをいただいたyuさんの情報提供が切っ掛けで問題の原因を突き止め、うちの家のLANでは解決することができました。

いろいろと調べていたら、DNSの変更で接続できたと言う人もいたり、できなかった人がいたり。 舐めていました。。。

DNS…DNSだと……ははっ、ま、まさかね……

……結論からいうと、問題の原因はDNS周りでした。DNSをgoogle public dns (8.8.8.8)に設定することで解決できるみたいです。
色々と調査した割に意外と基本的な部分を見落としていました。

原因究明

android 050 plusの正常な通信(google public dnsを使用した場合)は以下のようになっている。

  1. start.050plus.comから接続情報を取得する
  2. レジストサーバー(kar-f2fcp.050plus.com:5061)に接続する
    1. TCPセッションを確立する
    2. 60.37.58.xxx(kar-f2fcp.050plus.comのDNS正引きIP)をDNSサーバー(8.8.8.8)でDNS逆引きする
    3. 即「No Such Name」エラーがDNSサーバーから返却される
    4. TLSセッションの確立を開始する
  3. (以下略)

一方、家のルーター(192.168.1.1)のDNSプロキシでは以下のようになる。

  1. start.050plus.comから接続情報を取得する
  2. レジストサーバー(kar-f2fcp.050plus.com:5061)に接続する
    1. TCPセッションを確立する
    2. 60.37.58.xxx(kar-f2fcp.050plus.comのDNS正引きIP)をDNSサーバー(8.8.8.8ルーター)でDNS逆引きする
    3. なぜかDNSの応答待ちが発生する
    4. TLSセッションの確立のタイムアウトにより、kar-f2fcp.050plus.comから切断される
    5. DNSクエリがタイムアウトエラーになる
    6. TLSセッションの確立を開始しようとするが既に接続が切れている→9911エラー

つまり、kar-f2fcp.050plus.comの正引き結果(60.37.58.xxx)を、TCP接続開始後に何故か逆引きしていることが根本的な原因というわけだ。しかも、60.37.58.xxxにはDNS逆引きレコードが設定されていない。ここでDNSサーバーの挙動が分かれる。Google Public DNSでは、即時「見つからないよ!」エラーを返すのに対して、うちのルーターであるIX2015や一部の家庭用ルーターは「探してるから待ってね!」的な状態が続く。

どうも、Androidのセキュアソケットは、TCP接続を確立した後に、IP逆引きを行い、その結果が返却されるのを待ってから、TLSセッション確立処理を開始(Client Helloを送信)するらしい。従って、DNSの応答がない場合はDNSがタイムアウトするのを待ってしまうようだ。その間に、TLSセッション確立処理がタイムアウトしてしまい、レジストサーバー(kar-f2fcp.050plus.com:5061)から切断されてしまう。これが9911エラーの正体だ。

解決策

根本的な解決策は、Androidの050 Plusアプリ側が無駄なDNSの逆引き問い合わせをしないようにすることだ。だが、これは050Plusの開発元にしか対応出来ないし、ライブラリの問題ならばお手上げだろう。仮にライブラリの設定次第でうまく動くならば簡単な修正に留まるが、この手の修正は、コーディング工数に比べテスト工数が無駄に増えるので嫌がられる気がする。大多数のユーザーが満足しているのだから、修正する必要無いよね? 的な。IT企業に勤めているとこの辺の感覚はよく分かる。

もう一つの解決策は、60.37.58.xxxを逆引きできるようにすること。これもNTTコミュニケーションズしかできないことだが、プログラムの修正を行わずに対応出来る。だが、対応にどれだけの時間がかかるか分からない。中には「全パターンで検証を行わないと気が済まない病」の人がいるはずなので、即時対応は期待しない方が良いだろう。

自分で出来る対策となると、こちらのDNS設定を変更することだ。
現時点で「見つからないよ」エラーになることは分かっているので、即時エラーを返してくれるDNSサーバーに設定することが好ましい。例えば先ほどの実験で用いたGoogle Public DNSだ。

IX2015では、DHCPでIP自動割り当て時にこのDNSサーバーを自動設定するように設定した。

ip dhcp profile homelan1
    assignable-range 192.168.1.200 192.168.1.240
    subnet-mask 255.255.255.0
    default-gateway 192.168.1.1
    dns-server 8.8.8.8
    exit

まぁGoogleにあまり情報を流したくないけれど、暫定的な措置なのでやむを得ないだろう。

IX2015以外の家庭用ルーターやポケットWifi(GP02とか)にも、「DHCP設定」というページが存在し、そこで自動的に割り当てるDNSサーバーを指定できるはずだ。GP02ではマニュアルの103ページにDHCPの設定方法が書かれている。ここでプライマリDNSに「8.8.8.8」を設定すれば良いはずだ。ちなみに僕はGP02を持っていないので実際に動くかどうかは知らない。設定後は、Android端末を再起動しよう。

最悪、ルーターのDHCPでDNSサーバーを指定できない場合は、端末のIPアドレスを手動で設定することになる。
HTCのAndroid機では、DNSのみを手動設定ということが設定画面から出来ないっぽいので、IPアドレス指定を固定にするしかない。
外でFON等、別の無線LANに接続できなくなる可能性があるため、あまりお勧めしない。とりあえず、設定→無線とネットワーク→Wifi設定でMenuキーを押し、静的IPを使用にチェックを入れ、IP設定を手動で入力し、DNSサーバー1を「8.8.8.8」に設定する。

これで問題なく接続出来るようになるはずだ。

一応、この件に関してNTTコミュニケーションズに報告しようと思う。
根本的な解決策を執ってくれることに心から期待したいものだ。

050 plus がwifiで接続出来ない件について調査2(まだ未解決)

050 plus のポート関連について調査(未解決)の続き。
結局問題は解決していない。公式サポートは「サポート対象外の機種では使えないからご了承を」的なテンプレ回答で、どうしよもうない。

とりあえず調べてみたことをまとめてみる。
結論としては、Androidのセキュアソケットライブラリの問題の可能性が非常に高いと思われる。となると、簡単には修正出来ない。望みは絶たれたような感じだ。

前提条件として、うちのルーターはNEC IX2015で、複数の固定IPアドレスが振られているIP Unnumbered接続だ。
そして、HTCのAndroid端末をNAPT下のローカルアドレスのネットワークに無線LANで接続している。
この状態で050 Plusを起動すると、ルーターのログを見る限り、kar-f2fcp.050plus.com:5061と192.168.1.208(端末のIP)NATのエントリは作成される。その後きっかり10秒後にNATエントリが削除されている。何回実験しても10秒後に削除される。つまり何かがタイムアウトしているようだ。

ルーターのログでは限界があるので、Android SDKのエミュレータ(Android2.3.3)に050plusをインストールし、wiresharkで流れるパケットをキャプチャする。その結果がこれだ。

050Plus接続失敗時のパケットキャプチャ

ここで192.168.1.113は、エミュレータの動作しているPCのローカルIPだ。
これを見ると、確かに「SYN」「SYN,ACK」「ACK」によりTCP接続が確立している。しかし、Androidからは10秒間なにも送信されず、接続確立から10秒後、先方から「FIN,ACK」が送信されてきている。恐らく、これは050plusのサーバーがTLSセッション確立のタイムアウトを通告してきているということなのだろう。この直後、AndroidがClient Helloを送信しているが、後の祭りである。

本来は「SYN」「SYN,ACK」「ACK」の後にクライアントがClient Helloを送信し、サーバーからServer Helloが送り返されTLSセッションの確立が行われる。それにもかかわらず、wifi接続中のAndroidは何故かClient Helloを送信しないのだ。

一応、NAPTやローカルIPが原因の可能性も考えて、HTCのAndroid端末にグローバルIPを設定してみた。当該IPはパケットフィルタの例外に設定し、050Plusに接続しようとした。しかし、接続エラー9911が発生し、接続出来なかった。したがって、IPやNAT、パケットフィルタの問題ではないっぽい。謎すぎる。

やはり、セキュアソケットライブラリの問題ではないかと思えてくる。
サポート対象の機種と、サポート対象外の機種の違いって実はここらへんにあるのかもしれない。
とはいうものの、SDKのエミュレータでもちゃんと動かないというのは謎だなあ。

追記
解決しました→050 plus のポート関連について調査3(解決編)

050 plus がwifiで接続出来ない件について調査(未解決)

家の無線LANで050 Plusの調子がどうも悪い。エラー9911が出て接続が出来ないのだ。しかし、3Gで接続完了後、wifiに切り替えると正常に接続出来ることが多い。したがって、初期情報のやりとりで何かのエラーが発生していると推測出来る。だが、結局原因を特定することはできなかった。

■現象
wifi接続時に「エラー接続に失敗しました(9911)」と表示され接続に失敗する

■発生条件

  • HTC製の端末
  • OS: Android 2.3.4
  • ADSL回線(固定IP)のwifi接続時
  • ルーターはNEC IX2015に無線LAN APをぶら下げている。
  • 発生は携帯端末の電源OFF状態からの起動直後の自動起動時が多い

■詳細情報
未登録状態での「テストコール」は正常。
アプリ再起動を行うと、正常に接続出来ることがある。
3G回線では問題なく接続でき、3G回線に接続後、wifi接続に戻すと正常に接続できることがある。
無線LANルーターのパケットフィルタのログにはパケットが破棄・棄却された記録はない。
同じADSL回線でWindows用の050 Plusは問題なく使用出来る。

(スタックトレースの一部)

E/050Service( 2948): d [main] : failed to send Ini-REGISTER
E/050Service( 2948): javax.net.ssl.SSLException: Connection closed by peer
E/050Service( 2948): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
E/050Service( 2948): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:474)
E/050Service( 2948): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328)
E/050Service( 2948):    at com.oki_access.b.ab.<init>(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.ab.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.c.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.bb.d(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.bb.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.bb.c(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.bb.f(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.bb.b(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.az.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.az.b(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.at.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.a.c.c.j.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.at.c(Unknown Source)
E/050Service( 2948):    at com.oki_access.a.c.c.j.c(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.at.b(Unknown Source)
E/050Service( 2948):    at com.oki_access.b.d.aa.H(Unknown Source)
E/050Service( 2948):    at com.oki_access.a.b.z.z(Unknown Source)
E/050Service( 2948):    at com.oki_access.a.b.z.b(Unknown Source)
E/050Service( 2948):    at com.oki_access.a.b.d.h(Unknown Source)
E/050Service( 2948):    at com.oki_access.a.c.aa.t(Unknown Source)
E/050Service( 2948):    at com.oki_access.a.c.c.d.r(Unknown Source)
E/050Service( 2948):    at com.oki_access.android.ims.core.service.ImsService.d(Unknown Source)
E/050Service( 2948):    at com.oki_access.android.ims.core.service.i.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.android.ims.a.b.a(Unknown Source)
E/050Service( 2948):    at com.oki_access.android.ims.a.c.onReceive(Unknown Source)
E/050Service( 2948):    at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:748)
E/050Service( 2948):    at android.os.Handler.handleCallback(Handler.java:587)
E/050Service( 2948):    at android.os.Handler.dispatchMessage(Handler.java:92)
E/050Service( 2948):    at android.os.Looper.loop(Looper.java:150)
E/050Service( 2948):    at android.app.ActivityThread.main(ActivityThread.java:4293)
E/050Service( 2948):    at java.lang.reflect.Method.invokeNative(Native Method)
E/050Service( 2948):    at java.lang.reflect.Method.invoke(Method.java:507)
E/050Service( 2948):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
E/050Service( 2948):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
E/050Service( 2948):    at dalvik.system.NativeStart.main(Native Method)

 

不思議なことにルーターのパケットフィルタがパケットを棄却しているわけではないようなのだ。

スタックトレースを読む限り、SSLセッションのハンドシェイクで失敗しているように見える。接続中に相手から接続を終了されてしまう。050 Plusが使用しているのは、ポート5060と5061で、このうちSSL(TLS)を使うのは、ポート5061のSIP-TLSである。また、ここを見るとhttpsで初期設定を取得しているようだ。

調査した結果、SIP-TLSはkar-f2fcp.050plus.comへ接続するようだが、PCからは問題なく接続できる。httpsが問題なく接続出来るのはいうまでもない。AndroidのSSLの実装にバグがあるのだろうか。謎である。

この件については、とりあえず公式サイトにお問い合わせフォームで報告しておいた。うーむ。

追記
解決しました→050 plus のポート関連について調査3(解決編)