如何在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 `': uninitialized constant OpenSSL::SSL::SSL_OP_SSL2 (NameError) 

1.9.3 (和2.0.0)的Ruby文档甚至懒得提及它。

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


相关: 在ruby中设置SSLContext选项 。 但是当http.use_ssl = true时, 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上的里程可能会有所不同。 如果它对您的首选版本不起作用,请告诉我。

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