经过漫长的一天,我设法找到了我认为与不支持最新和最好版本的服务器的SSL / TLS密码协商问题的底部。
堆栈:
60秒后,下面的代码段给出了一个错误:
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的问题,但理想情况下有一个红宝石解决方案。我无法将密码锁定为“AES128-SHA”,因为相同的代码会处理许多可能支持或不支持此密码的网站。
有没有人遇到这个并找到了通用的解决方案?
编辑:这似乎是由“TLS hang bug”造成的,而且是fixed in openssl 1.0.1g。
新问题:是否有可以在红宝石方面实施的解决方法?
更多信息。
运行OpenSSL 1.0.1j的Gentoo服务器2014年10月15日没有此问题。我尝试在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
但是在ruby 2.2.2上的Net :: HTTP中没有ssl_options。
答案 0 :(得分:0)
After spending more time on this than I'd care to admit, my solution was to upgrade from Ubuntu 14.04 to 15.10 which comes with OpenSSL 1.0.2d 9 Jul 2015
.
While the TLS negotiation still hangs using the openssl CLI, in Ruby it does not:
require 'net/http'
require 'openssl'
require 'pp'
uri = URI.parse('https://broken_server/my/path')
http = Net::HTTP.new('broken_server', 443)
http.instance_eval {
@ssl_context = OpenSSL::SSL::SSLContext.new
@ssl_context.set_params({:options=>OpenSSL::SSL::OP_ALL})
}
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
pp response = http.request(Net::HTTP::Get.new(uri.request_uri))
SSL context code above courtesy of @vinhboy.
The CLI equivalent of the above is turned-on with the -bugs
option:
openssl s_client -bugs -connect broken_server:443