Android の「インターネットは利用できません」の検出

Android に詳しい方はご存知の通り、Android は http://connectivitycheck.gstatic.com/generate_204 に定期的に接続をしてインターネット接続できるかどうかを確認している。 ここへの接続が出来ない場合は「インターネットは利用できません」と表示される。

connectivitycheck.gstatic.com へ接続できない時の WiFi アクセスポイントの警告表示

なお、この警告は celler 回線(3G/4G 回線)でも表示は異なるが、警告される。

connectivitycheck.gstatic.com へ接続できない時の docomo 回線の警告表示

なお、上の図はいずれも connectivitycheck.gstatic.com への接続を遮断して得られた動作結果であり、 実際には他のドメインへの接続はできるといった挙動を確認している。

connectivitycheck.gstatic.com の偽装と挙動

http://connectivitycheck.gstatic.com/generate_204 へ接続すると常に "204 No Content" が帰ってくる。 ここで、接続不能であったり "404 Not Found" であったりしたときに、 「インターネットは利用できません」と判定がなされる。

そこで、connectivitycheck.gstatic.com を他の IP アドレスに解決させることで 代替することを考えた。 具体的には、

  • 192.168.1.2 アドレスで起動している PC 上の port 80 で HTTP server を起動させる。
    • http://192.168.1.2/generate_204 へのレスポンスは "204 No Content" とする。
    • 簡単のため "Host: connectivitycheck.gstatic.com" が要求ヘッダについていようがついていまいが、同一の動作をするものとする
  • Android 機において、connectivitycheck.gstatic.com のドメイン名を 192.168.1.2 に解決させる環境を作る。
  • Android 機において、WiFi アクセスポイントに接続させる。Android 機の IP アドレスは 192.168.1.1 とする。
確認環境のネットワーク。"genuine connectivitycheck.gstatic.com"には接続しには行かずに 192.168.1.2 に接続する

目的を実現するために簡素な HTTP server "Fake connectivitycheck.gstatic.com" を作成した。 これを linux マシン上で駆動させた(もちろん su 権限で実行し、また firewall で port 80 を許可した)。

そして Android 機を WiFi に接続させると下記の通り、 HTTP server 側のログが吐き出された。

[2016-08-14 07:23:00] DEBUG accept: 192.168.1.1:51856
[2016-08-14 07:23:00] DEBUG WEBrick::HTTPServlet::ProcHandler is invoked.
192.168.1.1 - - [14/Aug/2016:07:23:00 EDT] "GET /generate_204 HTTP/1.1" 204 0
- -> /generate_204
Dalvik/2.1.0 (Linux; U; Android 6.0.1; Nexus 5 Build/MMB29X)
[2016-08-14 07:23:00] DEBUG close: 192.168.1.1:51856
[2016-08-14 07:23:01] DEBUG accept: 192.168.1.1:56927
[2016-08-14 07:23:01] DEBUG WEBrick::HTTPServlet::ProcHandler is invoked.
192.168.1.1 - - [14/Aug/2016:07:23:01 EDT] "GET /generate_204 HTTP/1.1" 204 0
- -> /generate_204
Dalvik/2.1.0 (Linux; U; Android 6.0.1; Nexus 5 Build/MMB29X)
[2016-08-14 07:23:01] DEBUG close: 192.168.1.1:56927

最初の部分しか取り出していないため時間を空けずに幾度も接続しているようにみえるが、 しばらく経ったら間隔をあけて接続するようだ。 また、重要なこととしてこれによって「インターネットは利用できません」が表示されないことを実現できた。

connectivitycheck.gstatic.com の偽装効果

connectivitycheck.gstatic.com というGoogle のサーバへの接続処理は、 そもそも Android のコードに埋め込まれている。 よって世界中のオンラインとなっている Android 機から定期的に接続しているということだ。 それは冷静に考えると興味深いことである。 connectivitycheck.gstatic.com の接続を 本稿で述べたようにゴニョゴニョすることでこの Google のサーバへの接続処理を止めて かつ「インターネットは利用できません」判定も Google のサーバなしで実現することが出来た。

さらに connectivitycheck.gstatic.com のドメイン名を 127.0.0.1 に解決させてかつ android 上でサーバを駆動させれば、 「インターネットは利用できません」判定機能が実質無効化されることを引き換えに 無線アクセスを抑えることも考えられるが、これはやっていない。

Reference

その他、connectivitycheck.gstatic.com のドメイン名解決を操作するための /etc/hosts のフロントエンドとしてAdAwayを使用した。