【问题标题】:How to set TLS context options in Ruby (like OpenSSL::SSL::SSL_OP_NO_SSLv2)如何在 Ruby 中设置 TLS 上下文选项(如 OpenSSL::SSL::SSL_OP_NO_SSLv2)
【发布时间】:2014-04-28 07:34:54
【问题描述】:

在 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)

Ruby docs for 1.9.3(和 2.0.0)甚至懒得提它。

如何在 Ruby 中设置 TLS 上下文选项?


相关:setting SSLContext options in ruby。但是当http.use_ssl = true 时,无法将上下文附加到http

【问题讨论】:

    标签: ruby ssl openssl options


    【解决方案1】:

    在 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​​ 代码的相关部分:https://github.com/ruby/ruby/blob/e9dce8d1b482200685996f64cc2c3bd6ba790110/lib/net/http.rb#L886

    【讨论】:

    • 很好,谢谢格雷。 OS X 10.8 上的 Ruby 1.8.7 的相关问题。看起来SSLv2SSLv3 都可以;但是:uninitialized constant OpenSSL::SSL::OP_NO_COMPRESSIONuninitialized constant OpenSSL::SSL::OP_NO_COMP。是我的错吗?还是这更像是苹果的不安全感?
    • 这对我来说变得更糟了...http.options results int undefined method 'options=' for #&lt;Net::HTTP example.com:8443 open=false&gt;.
    • @jww 确保包含第一个代码块。这就是添加 ssl_options= 方法的原因。
    • 为了能够编译 Ruby 1.8.7,您需要预先对其进行修补:gist.github.com/hyoshida/11241844
    猜你喜欢
    • 2019-01-11
    • 1970-01-01
    • 2011-04-18
    • 2019-06-27
    • 2016-01-13
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    相关资源
    最近更新 更多