OKHttp Android没有通过http2 alpn连接到nginx
Posted
技术标签:
【中文标题】OKHttp Android没有通过http2 alpn连接到nginx【英文标题】:OKHttp Android not connecting to nginx via http2 alpn 【发布时间】:2016-08-12 03:47:48 【问题描述】:我有一个使用以下库的 android 应用程序 (4.4.4+):
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'
compile 'com.squareup.okio:okio:1.7.0'
我有 nginx(版本 1.9.14) 用 OpenSSL 编译(版本 1.0.2g 源码编译) 在 centOS 7 上使用 nginx -V 确认了 openSSL 的使用。 为反向代理启用 nginx http2 的配置:
server
listen 443 ssl http2;
ssl on;
server_name mobile.site.com;
ssl_certificate /etc/pki/tls/certs/start_cert.pem;
ssl_certificate_key /etc/pki/tls/certs/start_cert.key;
proxy_cache one;
underscores_in_headers on;
access_log /var/log/nginx/ssl.log ssl_custom;
location /
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_pass https://10.10.1.31:443;
在服务器上运行命令:
echo | openssl s_client -alpn h2 -connect
返回:
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3718 bytes and written 442 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
ALPN protocol: h2
从任何现代浏览器浏览 API URL 都会导致 HTTP/2 连接显示在 SSL 日志和 HTTP/2 chrome 插件中。假设在 nginx / OpenSSL 中正确配置了 HTTP/2。
Android OKHttp 客户端拒绝 HTTP/2:
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.build();
okHttpClient = new OkHttpClient.Builder()
.followSslRedirects(true)
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
.connectionSpecs(Collections.singletonList(spec))
.sslSocketFactory(new TLSSocketFactory((SSLSocketFactory) TLSSocketFactory.getDefault()))
.retryOnConnectionFailure(true)
.connectTimeout(25, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(30, 120, TimeUnit.SECONDS))
.addInterceptor(new AddCookiesInterceptor())
.addInterceptor(new ReceivedCookiesInterceptor())
.build();
我编写了一个自定义 TLS 套接字工厂,以在
TLSv1.2 确实可以在 4.4.4+ 上使用此自定义套接字工厂,但我也尝试在 5.0+ 上运行,无论是否使用自定义套接字工厂,都没有 HTTP/2 运气。
HTTP/2 在 kit-kat、棒棒糖和棉花糖上失败,但在“N”开发者预览版(又名纽约芝士蛋糕)上工作。不会抛出任何错误,只会以 HTTP/1.1 连接。我很难找到任何与 OKhttp 和 HTTP/2 相关的文章,大多数帮助问题/帖子只是说使用 ALPN,但没有资源来详细说明用法。 OkHTTP 文档并不清楚 HTTP/2 的使用和部署实践,但主页上说它支持它。任何帮助或专家指导将不胜感激,即使只是朝着正确的方向轻推也会是一个巨大的帮助。如果我错过了任何可能在此过程中提供帮助的内容,请告诉我,提前致谢!
更新 1:我发现了一个与此相关的 SO 问题,答案非常模糊:[SO 链接]How to use http/2 with Okhttp on Android devices? 有一条评论建议使用码头,但仅限于桌面使用,不是安卓使用。
更新 2:本文显示 ALPN 已在 Android 4.4 中启用:https://github.com/http2/http2-spec/wiki/ALPN-Status
更新 3:能够使用 +5.0 连接 HTTP/2,但不能使用 4.4.4。我不需要低于 4.4.4,因为内部目标设备是 http/2 的关注点,它们运行 4.4.4。我能够更新应用程序以使用 Google Play Services 安全协议作为 OKHttp 套接字连接,但我们使用的 4.4.4 设备未启用 Google,因此我无法在这些设备上使用 PlayServices 安全套接字。
【问题讨论】:
对用于寻找模式的密码进行了更多研究:4.4.4: TLSv1.2 ECDHE-RSA-AES128-SHA - 5.1。 1:TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256-6.0:TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256-7.0: TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256 - Chrome/FireFox:TLSv1.2 ECDHE-RSA-AES128-GCM-SHA256。只有 Chrome/FireFox 和“7.0(N)”使用 HTTP/2 连接。 这方面有什么更新吗?您是否能够在 4.4.4 上获得 http2 或者您是否会选择其他替代方案? 我现在开始做其他事情,但我想很快再访问这里。我明天可能会看看,看看我可以用任何更新的库做什么。 OkHttpClient.Builder“sslSocketFactory”中似乎有一个新的(扩展的)方法。原始方法(已弃用)仅需要 sslSocketFactory,但新方法需要 sslSocketFactory 和 X509TrustFactory。这里可能有一些东西,但如果这有任何影响,我将不得不调查下一个构建周期。我有限的理解是,Android( 【参考方案1】:根据 swankjesse,
接下来的步骤: 不要在 Android 4.4 及更早版本上使用 ALPN;它在那里坏了。 为之前稳定的 Android 版本恢复 NPN。
Don't use broken ALPN on Android 4.4
【讨论】:
真正的问题是关于如何让 HTTP2 在以上是关于OKHttp Android没有通过http2 alpn连接到nginx的主要内容,如果未能解决你的问题,请参考以下文章