How to set TLS context options in Ruby (like OpenSSL::SSL::SSL_OP_NO_SSLv2)

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

Leave a Comment