Я пытаюсь создать SSLSocket
поверх другого SSLSocket
в приложении для Android. Более низкое соединение - это SSL-защищенная связь с Secure Web Proxy (прокси HTTP через SSL), верхнее соединение для HTTP через SSL ( HTTPS).
Для этого я использую функцию SSLSocketFactory createSocket()
, которая позволяет передать существующий Socket, для которого можно запустить SSL-соединение, например:
private Socket doSSLHandshake(Socket socket, String host, int port) throws IOException {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager(){
public X509Certificate[] getAcceptedIssuers(){ return null; }
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
SSLSocket sslSocket = (SSLSocket) sslContext.getSocketFactory().createSocket(socket, host, port, true);
sslSocket.setEnabledProtocols(sslSocket.getSupportedProtocols());
sslSocket.setEnableSessionCreation(true);
sslSocket.startHandshake();
return sslSocket;
} catch (KeyManagementException | NoSuchAlgorithmException e) {
throw new IOException("Could not do handshake: " + e);
}
}
Этот код работает нормально, когда базовый сокет является обычным Tcp Socket, но когда я использую в качестве базового сокета SSLSocket, который был создан с использованием вышеприведенного кода раньше, рукопожатие выходит из строя со следующим исключением:
javax.net.ssl.SSLHandshakeException: Handshake failed
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:429)
at com.myapp.MyThreadClass.doSSLHandshake(MyThreadClass.java:148)
at com.myapp.MyThreadClass.run(MyThreadClass.java:254)
Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x7374d56e80: Failure in SSL library, usually a protocol error
error:100000e3:SSL routines:OPENSSL_internal:UNKNOWN_ALERT_TYPE (external/boringssl/src/ssl/s3_pkt.c:618 0x738418ce7e:0x00000000)
at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
... 2 more
Я тестирую на Android 7.1.1. Приложение настроено на уровень 23 SDK.
- Что я могу делать неправильно?
- Как я могу продолжить отладку проблемы?
- Есть ли у кого-нибудь рабочий пример SSLSocket, который перебирает другой SSLSocket на недавней версии Android?
Любая помощь очень ценится!
Обновить. Тот же самый код работает в JRE 1.8 на Mac, но не на Android.
Обновление 2. Концептуально это шаги, через которые проходит соединение:
- В приложении Android сделайте подключение к серверу Secure Proxy (Socket)
- Выполнение SSL/TLS-связи с прокси-сервером (SSLSocket через Socket)
- Через SSLSocket отправьте сообщение CONNECT на прокси-сервер
- Прокси подключается к серверу назначения (https) и только копирует байты с этого момента
- Сопоставление SSL/TLS с сервером назначения (https) (SSLSocket через SSLSocket через Socket)
- Отправьте сообщение GET на целевой сервер и прочитайте ответ
Проблема возникает на шаге 5 при выполнении рукопожатия на SSLSocket который проходит через SSLSocket (который проходит через Socket).
Обновление 3: теперь я открыл репозиторий GitHub с образцом проекта и tcpdumps: https://github.com/FD-/SSLviaSSL
Примечание: я нашел и прочитал вопрос с очень похожим заголовком, но он не содержал много полезной помощи, к сожалению.