我无法让API <21的android设备连接到我的nginx服务器。这里的所有结果均来自API 19仿真设备。
我尝试按照其他地方的建议使用VolleyToolboxExtension
和NoSSLv3Factory
,但仍然遇到如下类似的严重错误,只是后来不是sslv3而是tlsv1。
我目前的方法是让旧的android版本通过SSLv3连接。但这仍然会产生如下错误。
注意:我知道SSLv3已损坏,但是我使用的是其他证书,并且没有发送任何与安全性相关的信息。整个想法是进行调查,以便我可以决定是否要放弃对旧版Android SDK的支持。
error during request: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb8a45890: Failure in SSL library, usually a protocol error
error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:741 0x8d959990:0x00000000)
我使用以下代码进行连接:
final String url;
if ( Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP ){
url = "https://abc.badssl.example.com";
} else {
url = "https://abc.example.com";
}
final JSONObject jsonBody;
try {
jsonBody = new JSONObject("{\"api\":" + Build.VERSION.SDK_INT + "}");
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, url,
jsonBody,
response -> {
try {
Log.d(TAG, "Response is: " + response.getInt("api"));
} catch (JSONException e) {
Log.wtf(TAG, e);
}
wasRunning = true;
loading.postValue(false);
}, e -> {
Log.e(TAG, "error during request: " + e.getMessage());
error.postValue(true);
});
jsonObjectRequest.setShouldCache(false);
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 5, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.getCache().clear();
queue.add(jsonObjectRequest);
} catch (JSONException e) {
Log.wtf(TAG, e);
}
这是我使用不同证书的abc.badssl.example.com的nginx配置:
listen 443 ssl;
server_name abc.badssl.example.com;
ssl on;
ssl_protocols SSLv3;
ssl_dhparam /etc/nginx/ssl/dhparams.pem;
#worker shared ssl cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_ciphers 'ECDHE-ECDSA-AES256-SHA:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:!DHE-RSA-AES256-GCM-SHA384:!DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:!DHE-RSA-AES256-SHA256:!DHE-RSA-AES128-SHA256:!DHE-RSA-AES256-SHA:!DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4:!DHE-RSA-DES-CBC-SHA:!DHE-RSA-CAMELLIA256-SHA:!DHE-RSA-CAMELLIA128-SHA:!DHE-DSS-CBC-SHA:!DHE-RSA-DES-CBC3-SHA';
fastcgi_param HTTPS on;
我认为我弄错了nginx参数,但我似乎找不到99%的内容是关于禁用SSLv3或与当前版本的凌空(死链接)无关。
答案 0 :(得分:0)
好,所以解决方案变得有些不同。
首先:出于明显的原因,在当前版本的OpenSSL中,在debian和ubuntu上禁用了SSLv3。有趣的是,这不会引发任何错误或类似错误,nginx configuraton协议将被忽略?即使配置中仅使用SSLv3,我仍然可以通过TLS1.X连接到服务器。 nmap报告相同。
在Android <21(如其他答案中所述)上,存在TLS,但SSLv3是首选甚至是强制的。
在较旧的设备上获得有效的HTTPsUrlConnection的最简单解决方案是使用NetCipher。
build.gradle:
implementation "info.guardianproject.netcipher:netcipher:2.0.0-alpha1"
然后使用Netcipher创建HTTP连接。
您还可以通过使用自定义HttpStack将其与凌空一起使用。请注意,来自Netcipher的 StrongBuilders不是用于建立简单的https连接!,它们仅用于通过Tor网络进行连接。因此,不要以为您可以使用它们来避免使用HttpStack。
使用原始HttpsUrlConnection的不带凌空的请求处理程序:
final String url = "https://asd.example.com";
runner = new Thread(() -> {
final JSONObject jsonBody;
try {
HttpsURLConnection con = NetCipher.getHttpsURLConnection(new URL(url));
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.setRequestProperty("Accept", "application/json");
con.setDoOutput(true);
con.setDoInput(true);
jsonBody = new JSONObject("{\"api\":" + Build.VERSION.SDK_INT + "}");
OutputStream wr = con.getOutputStream();
wr.write(jsonBody.toString().getBytes("UTF-8"));
wr.flush();
wr.close();
InputStream in = new BufferedInputStream(con.getInputStream());
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
JSONObject jsonObject = new JSONObject(result.toString("UTF-8"));
in.close();
con.disconnect();
Log.d(TAG,"received json: "+jsonObject.toString());
loading.postValue(false);
} catch (
Exception e) {
Log.wtf(TAG, e);
}
});
runner.start();