#navi_header|技術| "ProxyDroid"はHTTP(S), SOCKS4, SOCKS5に対応したプロキシ設定アプリです。 - ProxyDroid - Android マーケット -- https://market.android.com/details?id=org.proxydroid root化前提ですが、Android端末内のアプリ全てに対して強制的に外部HTTP(S)/SOCKS4,5プロキシを通すように設定できます。 本記事では、その裏舞台を簡単に紹介します。 * ProxyDroidに含まれているツール群 幸いなことにProxyDroidはソースコードが公開されています。ライセンスはGNU GPL v3です。 - proxydroid - Global Proxy App for Android System - Google Project Hosting -- http://code.google.com/p/proxydroid/ 早速hgでリポジトリをcloneして中身を確認してみると、"assets"ディレクトリの中に興味深いファイルが見つかりました。 assets/ cntlm iptables proxy.sh redsocks tproxy これらはインストール時に以下のディレクトリにコピーされます。 /data/data/org.proxydroid/ この辺の処理はorg.proxydroid.ProxyDroidのrecovery(), CopyAssets(), onCreate()辺りを参照してみてください。 では1つずつ見ていきます。 : redsocks :#block||> - redsocks - transparent socks redirector -- http://darkk.net.ru/redsocks/ HTTP(S), SOCKS4/5 の透過型Proxyです。 ||< : proxy.sh :#block||> ProxyDroidから起動されるシェルスクリプトで、引数に応じたredsocks用の設定ファイルを生成し、redsocksを起動します。 ||< : cntlm :#block||> - Cntlm: Fast NTLM Authentication Proxy in C -- http://cntlm.sourceforge.net/ これ・・・だと思います。多分。NTLM認証用のHTTPプロキシのようです。 ||< : tproxy :#block||> "tproxy"で検索すると似たようなのが結構出てくるので、ちょっとアタリがつけづらいのですが・・・多分これかな? - tproxy | Download tproxy software for free at SourceForge.net -- http://sourceforge.net/projects/tproxy/ ちょっとコマンドラインオプションが異なるようですが。 いずれにせよ、透過型プロキシの一種であることは確かなようです。 ||< : iptables : こちらはLinuxで使われるiptablesそのもののようです。 いずれもARM用にコンパイルされているようです。 * 動作原理 iptablesと透過型プロキシが同梱されている時点で気づいた人も居ると思いますが、ProxyDroidのやっていることは以下のとおりです。 + 外部のHTTPプロキシを指定した透過型プロキシを立ち上げて、 + 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()の中で #code|java|> 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の舞台裏のごく簡単な紹介でした。 #navi_footer|技術|