Android emulator http-proxy SSL handshake failure
Asked Answered
P

1

15

I have a local HTTP proxy set up for debugging .json request and response data from my Android application. I deploy it to a Nexus One emulator image running Android 4.2.2 with the command line option -http-proxy http://localhost:8888. I'm using a stock ADT Build: v21.1.0-569685. I can validate that the HTTP proxy can handle HTTPS connections with the following code snippet I run using groovy:

import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;

FileInputStream fis =
    new FileInputStream( "./.mitmproxy/mitmproxy-ca-cert.pem" );
BufferedInputStream bis = new BufferedInputStream( fis );
CertificateFactory cf = CertificateFactory.getInstance( "X.509" );
KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
ks.load( null,"".toCharArray() );
while ( bis.available() > 0 )
{
    Certificate cert = cf.generateCertificate( bis );
    ks.setCertificateEntry( "mitmproxy", cert );
    System.out.println( cert.toString() );
}
TrustManagerFactory tmf =
    TrustManagerFactory.getInstance(
        TrustManagerFactory.getDefaultAlgorithm() );
tmf.init( ks );
SSLContext ctx = SSLContext.getInstance( "TLS" );
ctx.init( null, tmf.getTrustManagers(), null );
SSLSocketFactory sslFactory = ctx.getSocketFactory();
try
{
    String url = "https://www.openssl.org/";
    Proxy proxy =
        new Proxy(
            Proxy.Type.HTTP,
            new InetSocketAddress( "127.0.0.1", 8888 ) );
    HttpsURLConnection conn =
        ( HttpsURLConnection ) new URL( url ).openConnection( proxy );
    conn.setSSLSocketFactory( sslFactory );
    String s =
        new Scanner(
            conn.getInputStream(),
            "UTF-8" ).useDelimiter( "\\A" ).next();
    System.out.println( s );
}
catch ( Exception e )
{
    e.printStackTrace();
}

This snippet fetches the HTTPS resource just fine, logs the request and response unencrypted, and works beautifully. The proxy also works when accessing HTTPS resources from a browser configured to use it as its proxy, so I'm pretty sure the problem is not with the proxy. Based on the certificate, you can tell I'm using the mitmproxy, but this code also works with the OWASP ZAP proxy. But with either proxy, after installing the appropriate CA root certificate on the Android image, HTTPS requests from the image fail with the following events being logged to the mitmproxy event log:

127.0.0.1:56210: connect
127.0.0.1:56210: 400: SSL handshake error: (-1, 'Unexpected EOF')
127.0.0.1:56210: disconnect
  -> handled 0 requests

On the Android side, the following exception is thrown:

05-23 16:13:30.109: E/HttpUrlConnectionClient(827): Network error
05-23 16:13:30.109: E/HttpUrlConnectionClient(827): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x2a180890: Failure in SSL library, usually a protocol error
05-23 16:13:30.109: E/HttpUrlConnectionClient(827): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x45dc2ba8:0x00000000)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:420)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:219)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:480)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:444)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:294)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:244)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:286)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:181)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.integralblue.httpresponsecache.compat.libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:273)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.ehi.national.mobile.network.HttpUrlConnectionClient.send(HttpUrlConnectionClient.java:178)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.ehi.national.mobile.network.AppClient.send(AppClient.java:212)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.ehi.national.mobile.network.MsiClient.send(MsiClient.java:87)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.ehi.national.mobile.services.SimpleService.runService(SimpleService.java:134)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.ehi.national.mobile.task.InitTask.doInBackground(InitTask.java:84)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at com.ehi.national.mobile.task.InitTask.doInBackground(InitTask.java:1)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at android.os.AsyncTask$2.call(AsyncTask.java:287)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at java.util.concurrent.FutureTask.run(FutureTask.java:234)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at java.lang.Thread.run(Thread.java:856)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x2a180890: Failure in SSL library, usually a protocol error
05-23 16:13:30.109: E/HttpUrlConnectionClient(827): error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol (external/openssl/ssl/s23_clnt.c:766 0x45dc2ba8:0x00000000)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:378)
05-23 16:13:30.109: E/HttpUrlConnectionClient(827):     ... 20 more

Other HTTP requests get logged and recorded as expected. What am I missing in the SSL setup for the Android image to complete the SSL handshake with the HTTP proxy successfully?

Pentahedron answered 23/5, 2013 at 17:41 Comment(1)
Did you ever find the answer? I'm having the same problem on Android 2.3.3. I installed the cert in the emulator image by this method but keep getting the 400 error.Filigreed
P
0

Android Developers gives two methods for supplying proxy; the one you used and an environment variable method. Maybe try the env var and see if it works?

From the Android Developers page:

If the -http-proxy command is not supplied, the emulator looks up the http_proxy environment variable

I found the details on the Android Developers page.

Purloin answered 2/2, 2016 at 15:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.