如何在Ruby中设置TLS上下文选项(例如OpenSSL :: SSL :: SSL_OP_NO_SSLv2) [英] How to set TLS context options in Ruby (like OpenSSL::SSL::SSL_OP_NO_SSLv2)
问题描述
在C语言中使用OpenSSL时,我们在上下文中设置选项以删除弱而受伤害的协议,例如SSLv2和SSLv3.从ssl.h
开始,下面是一些有用的选项的位掩码:
#define SSL_OP_NO_SSLv2 0x01000000L
#define SSL_OP_NO_SSLv3 0x02000000L
#define SSL_OP_NO_TLSv1 0x04000000L
#define SSL_OP_NO_TLSv1_2 0x08000000L
#define SSL_OP_NO_TLSv1_1 0x10000000L
但是,我无法在Ruby中设置它们:
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.options = OpenSSL::SSL::SSL_OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
OpenSSL::SSL::SSL_OP_NO_COMPRESSION
end
结果:
$ ./TestCert.rb
./TestCert.rb:12:in `<main>': uninitialized constant OpenSSL::SSL::SSL_OP_SSL2 (NameError)
1.9.3版的Ruby文档(和2.0.0)甚至不用提它.
如何在Ruby中设置TLS上下文选项?
相关:在ruby中设置SSLContext选项.但是当http.use_ssl = true
时,无法将上下文附加到http
.
在Ruby OpenSSL库中,选项常量不带有'SSL_'前缀.您可以通过在irb/console中运行以下内容来查看选项常量列表:OpenSSL::SSL.constants.grep(/OP_/)
.以下是定义它们的相关ruby C源: https ://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L2225 .
修改: 似乎没有一种方法可以直接为net http设置SSL选项. 参见 https://bugs.ruby-lang.org/issues/9450 .>
但是暂时您可以使用这个小技巧:
(Net::HTTP::SSL_IVNAMES << :@ssl_options).uniq!
(Net::HTTP::SSL_ATTRIBUTES << :options).uniq!
Net::HTTP.class_eval do
attr_accessor :ssl_options
end
现在只需在Net :: HTTP实例上设置ssl_options访问器.用法示例:
uri = URI('https://google.com:443')
options_mask = OpenSSL::SSL::OP_NO_SSLv2 + OpenSSL::SSL::OP_NO_SSLv3 +
OpenSSL::SSL::OP_NO_COMPRESSION
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ssl_options = options_mask
end
response = http.request request
# To Test
ssl_context = http.instance_variable_get(:@ssl_context)
ssl_context.options == options_mask # => true
我正在使用ruby 2.1.2进行测试,因此您在其他版本的ruby上的里程可能会有所不同.让我知道它是否不适用于您的首选版本.
对于那些感兴趣的人,我查看了创建此hack的Ruby代码的相关部分: However, I'm having trouble setting them in Ruby: Results in: The Ruby docs for 1.9.3 (and 2.0.0) don't even bother to mention it. How does one set the TLS context options in Ruby? Related: setting SSLContext options in ruby. But there's no way to attach the context to an In the Ruby OpenSSL library the option constants aren't prefixed with 'SSL_'. You can see a list of the option constants by running something like this in irb/console: Edit:
There doesn't appear to be a way, out of the box, to set the SSL options for net http.
See https://bugs.ruby-lang.org/issues/9450. However for the time being you can use this little hack: Now just set the ssl_options accessor on the instance of Net::HTTP. Example usage: I was testing with ruby 2.1.2 so your mileage on other versions of ruby may vary. Let me know if it doesn't work on your preferred version. For those interested, the relevant part of the ruby code I looked at to create this hack: https://github.com/ruby/ruby/blob/e9dce8d1b482200685996f64cc2c3bd6ba790110/lib/net/http.rb#L886 这篇关于如何在Ruby中设置TLS上下文选项(例如OpenSSL :: SSL :: SSL_OP_NO_SSLv2)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!#define SSL_OP_NO_SSLv2 0x01000000L
#define SSL_OP_NO_SSLv3 0x02000000L
#define SSL_OP_NO_TLSv1 0x04000000L
#define SSL_OP_NO_TLSv1_2 0x08000000L
#define SSL_OP_NO_TLSv1_1 0x10000000L
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.options = OpenSSL::SSL::SSL_OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
OpenSSL::SSL::SSL_OP_NO_COMPRESSION
end
$ ./TestCert.rb
./TestCert.rb:12:in `<main>': uninitialized constant OpenSSL::SSL::SSL_OP_SSL2 (NameError)
http
when http.use_ssl = true
.OpenSSL::SSL.constants.grep(/OP_/)
. Here is the relevant ruby C source where they are defined: https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L2225.(Net::HTTP::SSL_IVNAMES << :@ssl_options).uniq!
(Net::HTTP::SSL_ATTRIBUTES << :options).uniq!
Net::HTTP.class_eval do
attr_accessor :ssl_options
end
uri = URI('https://google.com:443')
options_mask = OpenSSL::SSL::OP_NO_SSLv2 + OpenSSL::SSL::OP_NO_SSLv3 +
OpenSSL::SSL::OP_NO_COMPRESSION
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ssl_options = options_mask
end
response = http.request request
# To Test
ssl_context = http.instance_variable_get(:@ssl_context)
ssl_context.options == options_mask # => true