home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Android/ProxyDroidとHTTP(S),SOCKSプロキシ

技術/Android/ProxyDroidとHTTP(S),SOCKSプロキシ

技術 / Android / ProxyDroidとHTTP(S),SOCKSプロキシ
id: 1020 所有者: msakamoto-sf    作成日: 2011-09-19 14:16:22
カテゴリ: Android 

"ProxyDroid"はHTTP(S), SOCKS4, SOCKS5に対応したプロキシ設定アプリです。

root化前提ですが、Android端末内のアプリ全てに対して強制的に外部HTTP(S)/SOCKS4,5プロキシを通すように設定できます。
本記事では、その裏舞台を簡単に紹介します。

ProxyDroidに含まれているツール群

幸いなことにProxyDroidはソースコードが公開されています。ライセンスはGNU GPL v3です。

早速hgでリポジトリをcloneして中身を確認してみると、"assets"ディレクトリの中に興味深いファイルが見つかりました。

assets/
    cntlm
    iptables
    proxy.sh
    redsocks
    tproxy

これらはインストール時に以下のディレクトリにコピーされます。

/data/data/org.proxydroid/

この辺の処理はorg.proxydroid.ProxyDroidのrecovery(), CopyAssets(), onCreate()辺りを参照してみてください。

では1つずつ見ていきます。

redsocks

HTTP(S), SOCKS4/5 の透過型Proxyです。

proxy.sh

ProxyDroidから起動されるシェルスクリプトで、引数に応じたredsocks用の設定ファイルを生成し、redsocksを起動します。

cntlm

これ・・・だと思います。多分。NTLM認証用のHTTPプロキシのようです。

tproxy

"tproxy"で検索すると似たようなのが結構出てくるので、ちょっとアタリがつけづらいのですが・・・多分これかな?

ちょっとコマンドラインオプションが異なるようですが。
いずれにせよ、透過型プロキシの一種であることは確かなようです。

iptables
こちらはLinuxで使われるiptablesそのもののようです。

いずれもARM用にコンパイルされているようです。

動作原理

iptablesと透過型プロキシが同梱されている時点で気づいた人も居ると思いますが、ProxyDroidのやっていることは以下のとおりです。

  1. 外部のHTTPプロキシを指定した透過型プロキシを立ち上げて、
  2. iptablesで対象となる80, 443などのポートあてのパケットを全て↑で立ち上げた透過型プロキシに流すよう設定。

図にするとこんな感じです:

Androidアプリ <-> Kernel <-> 透過型プロキシ <-> 外部プロキシ <-> インターネット

iptablesのコマンド実行や、上で紹介したツールの実行は org.proxydroid.ProxyDroidService クラスの enableProxy() メソッドで処理されています。実行されるコマンドラインについてはちゃんとログ出力されてますので、LogCatなどで確かめてみてください。

root化が必要な理由

iptablesでroot権限が必要で、例えば org.proxydroid.ProxyDroidService クラスの runRootCommand(String command) メソッドでは以下のように処理しています。

process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes(command + "\n");
os.writeBytes("exit\n");
os.flush();
process.waitFor();

注意点

ProxyDroidがiptablesで強制的に透過型プロキシにルーティングしているのは、80番や443番など標準的なポート番号を使用している場合に限ります。従って標準以外の独自ポート番号を使用しているHTTP通信の場合は、直接インターネットに出て行ってしまい、外部Proxyを通せない可能性が高いです。
もしそのようなアプリにも透過型プロキシを適用させたいのであれば、ProxyDroidのソースを取得しで独自にビルドすればOKです。
試してないので断言できないのですが、多分 enableProxy() の中でiptablesの設定コマンドを実行してますので、適当にコピペしてポート番号を書き換えればOKだと思います。
あと、バージョン2.0.4ではローカルIPへの通信がProxyに流れない現象が見られました。enableProxy()の中で

if (intranetAddr == null || intranetAddr.equals("")) {
    // Reference:
    // http://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
    if (localIp != null) {
        String[] prefix = localIp.split("\\.");
        if (prefix.length == 4) {
            String intranet = localIp;
            if (localIp.startsWith("192.168."))
                intranet = "192.168.0.0/16";
            else if (localIp.startsWith("10."))
                intranet = "10.0.0.0/8";
            else if (localIp.startsWith("172.")) {
                int prefix2 = Integer.valueOf(prefix[1]);
                if (prefix2 <= 31 && prefix2 >= 16) {
                    intranet = "172.16.0.0/12";
                }
            }
            rules = rules.replace("-p tcp", "-p tcp " + "! -d "
                    + intranet);
        }
    }
} else {
    rules = rules.replace("-p tcp", "-p tcp " + "! -d "
            + intranetAddr);
}

この辺の処理だと思います。一応画面上にもintranetAddrを指定する箇所があります。
色々弄ってみたのですが、結局上のifブロクをelseも含めてまるごとコメントアウトして、ローカルIPについても強制的にProxyを通すように修正してビルドしたのを使ってます。


当面の間、Android 2.x系ではHTTPプロキシ設定は公式にはサポートされない状況が続くと思います。
もしもroot化が可能であれば、ProxyDroidを使うことで無料で外部HTTP(S), SOCKS4, 5のプロキシを設定可能です。
しかもオープンソースですので、独自に改造してiptablesや透過型プロキシの設定を修正できます。

以上、ProxyDroidの舞台裏のごく簡単な紹介でした。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2011-09-19 14:16:47
md5:96d9c7f81b2deb1fdf38cfe93f1c1c5c
sha1:66bd8bc7369668ff424fd7d5e69423ad7a354c37
コメント
コメントを投稿するにはログインして下さい。