如何在Ruby中设置TLS上下文选项(例如OpenSSL :: SSL :: SSL_OP_NO_SSLv2) [英] How to set TLS context options in Ruby (like OpenSSL::SSL::SSL_OP_NO_SSLv2)

查看:534
本文介绍了如何在Ruby中设置TLS上下文选项(例如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代码的相关部分:#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

However, I'm having trouble setting them in 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

Results in:

$ ./TestCert.rb
./TestCert.rb:12:in `<main>': uninitialized constant OpenSSL::SSL::SSL_OP_SSL2 (NameError)

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 http when http.use_ssl = true.

解决方案

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: 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.

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:

(Net::HTTP::SSL_IVNAMES << :@ssl_options).uniq!
(Net::HTTP::SSL_ATTRIBUTES << :options).uniq!

Net::HTTP.class_eval do
  attr_accessor :ssl_options
end

Now just set the ssl_options accessor on the instance of Net::HTTP. Example usage:

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

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆