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

查看:32
本文介绍了如何在 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 = 真http.verify_mode = OpenSSL::SSL::VERIFY_PEERhttp.options = OpenSSL::SSL::SSL_OP_NO_SSLv2 |OpenSSL::SSL::OP_NO_SSLv3 |OpenSSL::SSL::SSL_OP_NO_COMPRESSION结尾

结果:

$ ./TestCert.rb./TestCert.rb:12:in `<main>': 未初始化的常量 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 做attr_accessor :ssl_options结尾

现在只需在 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_COMPRESSIONhttp = Net::HTTP.new(uri.host, uri.port)request = Net::HTTP::Get.new(uri.request_uri)如果 uri.scheme == "https"http.use_ssl = 真http.verify_mode = OpenSSL::SSL::VERIFY_PEERhttp.ssl_options = options_mask结尾响应 = http.request 请求# 去测试ssl_context = http.instance_variable_get(:@ssl_context)ssl_context.options == options_mask # =>真的

我正在使用 ruby​​ 2.1.2 进行测试,因此您在其他 ruby​​ 版本上的表现可能会有所不同.如果它不适用于您的首选版本,请告诉我.

对于那些感兴趣的人,我查看了创建此 hack 的 ruby​​ 代码的相关部分:https://github.com/ruby/ruby/blob/e9dce8d1b482200685996f64cc2c3bd6ba790110/lib/net/http.rb#L886

When using OpenSSL in C, we set options on the context to remove weak and wounded protocols like SSLv2 and SSLv3. From ssl.h, here is a bitmask of some of the options that are useful:

#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天全站免登陆