The proxy situation on Android is [unutterably
woeful](http://code.google.com/p/android/issues/detail?id=1273). It beggars
belief, but until recently Android didn't have a global proxy setting at all.
Recent releases have repaired this, but in the meantime the app ecosystem has
grown used to life without this basic necessity, and many apps merrily ignore
it. The upshot is that the only way to make reliable interception work on
Android is to do it without using the proxy settings.
The Solution
============
In response to Android's proxy situation, a number of apps have been created to
duct-tape proxy support onto the OS. These tools work by running a rudimentary
local proxy on the device, and forwarding all traffic destined for HTTP/S ports
to it using iptables. Since the proxy is running locally, it can detect what
the final IP address of the redirected traffic would have been. The local proxy
then connects to a user-configured upstream, and forwards the requests with a
proxy CONNECT request to the destination IP.
Now, if the configured upstream proxy is mitmproxy, we have a slight problem.
Proxy requests from the Android device in this scheme will specify only the
destination IP address, __not__ the destination domain. But mitmproxy needs the
target domain to generate a valid interception certificate. The solution is
mitmproxy's [upstream certificate](@!urlTo("upstreamcerts.html")!@) option.
When this is active, mitmproxy makes a connection to the upstream server to
obtain the certificate Common Name and Subject Alternative Names.
Adding all this together, we can achieve reliable Android interception with
only a few minutes of setup.
Step-by-step
============
The instructions below show how to set up an Android device with
[ProxyDroid](https://play.google.com/store/apps/details?id=org.proxydroid)
(the local "duct-tape" proxy implementation) to achieve interception. We've
used an Asus Transformer Prime TF201 with Android 4.0.3 - your device may
differ, but the broad setup process will be the same.
Before continuing, make sure your device is rooted - this is required to
install ProxyDroid.
Run mitmproxy
-------------
Start a mitmproxy instance on your interception host, making sure that the
upstream certificate option is set (use the _--upstream-cert_ command-line
option, or enable it interactively using the _o_ shortcut).
mitmproxy --upstream-cert
Install the mitmproxy certificate
---------------------------------
The first step is to install mitmproxy's interception certificate on the
Android device. In your ~/.mitmproxy directory, there should be a file called
__mitmproxy-ca-cert.cer__ - we need to transfer this file to
__/sdcard/Downloads__ on the Android device. If this file doesn't exist for
you, your certs were generated with an older version of mitmproxy - just copy
the __mitmproxy-ca-cert.pem__ file to __mitmproxy-ca-cert.ca__ and proceed from
there.
In this case, we're using wget from the terminal to transfer the certificate
from a local HTTP server:
Once we have the certificate on the local disk, we need to import it into the
list of trusted CAs. Go to Settings -> Security -> Credential Storage,
and select "Install from storage":
The certificate in /sdcard/Downloads is automatically located and offered for
installation. Installing the cert will delete the download file from the local
disk:
Afterwards, you should see the certificate listed in the Trusted Credentials
store:
Install ProxyDroid
------------------
Now, install ProxyDroid from the Google Play store:
You will be prompted for super-user access, which you must allow. Next, enter
the ProxyDroid settings, and change the proxy settings to point to your
mitmproxy instance. When you're done, it should look something like this:
In this case, our mitmproxy instance is at the host __maru.otago.ac.nz__,
running on port __8080__.
And that's it - you should now have full SSL interception enabled for your
Android device. Happy hacking!