【发布时间】:2024-05-18 10:05:02
【问题描述】:
经过漫长的一天后,我终于找到了一个我认为是 SSL/TLS 密码协商问题的根源,该问题与不支持最新最好版本的服务器有关。
堆栈:
- Ubuntu 14.04 全面修补
- OpenSSL 1.0.1f 2014 年 1 月 6 日
- irb 0.9.6(09/06/30)
- ruby 2.2.2p95(2015-04-13 修订版 50295)[x86_64-linux](使用 rbenv)
60 秒后,下面的 sn-p 给我一个错误:
require 'net/http'
require 'openssl'
uri = URI.parse('https://some_old_server/my/path')
http = Net::HTTP.new('some_old_server', 443)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
response = http.request(Net::HTTP::Get.new(uri.request_uri))
Errno::ECONNRESET: Connection reset by peer - SSL_connect
如果我将它添加到代码中,它会起作用:
(...)
http.ciphers = ['AES128-SHA']
(...)
=> #<Net::HTTPOK 200 OK readbody=true>
这不是特定于 ruby 的问题,但理想情况下存在 ruby 解决方案。我无法将密码锁定为“AES128-SHA”,因为相同的代码可以处理许多可能支持也可能不支持此密码的网站。
有没有人遇到过这种情况并找到通用解决方案?
编辑:这似乎是由“TLS hang bug”引起的,并且是fixed in openssl 1.0.1g。
新问题:是否有可以在 ruby 端实现的解决方法?
更多信息。
运行 OpenSSL 1.0.1j 2014 年 10 月 15 日的 Gentoo 服务器没有这个问题。我尝试在 Ubuntu 14.04 服务器上安装 1.0.1j,重新编译 ruby(rbenv install 2.2.2),错误仍然存在。
我尝试过monkey patch ext/openssl,但没有成功。
使用上面链接中的整个密码列表不起作用。但是,使用一个小子集确实有效:
require 'net/http'
require 'openssl'
uri = URI.parse('https://some_old_server/my/path')
http = Net::HTTP.new('some_old_server', 443)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
http.ciphers = %w{
AES128-GCM-SHA256
AES256-GCM-SHA384
AES128-SHA256
AES256-SHA256
AES128-SHA
AES256-SHA
ECDHE-ECDSA-RC4-SHA
ECDHE-RSA-RC4-SHA
RC4-SHA
}.join(":")
response = http.request(Net::HTTP::Get.new(uri.request_uri))
Openssl 与 ruby 一致(应该如此)。在同一个系统上运行这些,复制了我在 ruby 中看到的问题:
openssl s_client -connect some_old_server:443
CONNECTED(00000003)
(...)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 295 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
---
传递密码:
openssl s_client -cipher AES128-SHA -connect some_old_server:443
CONNECTED(00000003)
(...)
---
No client certificate CA names sent
---
SSL handshake has read 2721 bytes and written 425 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : AES128-SHA
Session-ID: removed
Session-ID-ctx:
Master-Key: removed
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1454394952
Timeout : 300 (sec)
Verify return code: 20 (unable to get local issuer certificate)
---
我在某个地方读到了使用
http.ssl_options = OpenSSL::SSL::OP_ALL
但 ssl_options 在 ruby 2.2.2 上的 Net::HTTP 中不可用。
【问题讨论】:
-
谢谢,@jww - 我试过了,虽然代码有效,但连接仍然超时。
-
一点 tcpdump'ing 告诉我 1.0.1j 上的 SSL hello 有填充,而 1.0.1f 没有。实际上,在 1.0.1g 中添加了填充扩展以“处理损坏的服务器”。我会继续调查这条线。
-
此问题在 OpenSSL 常见问题解答中:openssl.org/docs/faq.html#USER17 - 其他 SO 条目:*.com/questions/11321403/…
-
另一种设置选项的方式:*.com/a/30008472/27693
标签: ruby openssl ubuntu-14.04 net-http