Как установить параметры контекста TLS в Ruby (например, OpenSSL::SSL::SSL_OP_NO_SSLv2)

При использовании OpenSSL в C мы устанавливаем параметры в контексте для удаления слабых и поврежденных протоколов, таких как 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 для 1.9.3 (и 2.0.0) даже не упоминают об этом.

Как установить параметры контекста TLS в Ruby?


Связано: настройка параметров SSLContext в ruby. Но нет способа прикрепить контекст к http когда http.use_ssl = true,

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.

Изменить: Похоже, нет способа, из коробки, чтобы установить параметры SSL для net http. Смотрите 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

Теперь просто установите аксессор ssl_options на экземпляр Net::HTTP. Пример использования:

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, на которую я смотрел, чтобы создать этот хак: https://github.com/ruby/ruby/blob/e9dce8d1b482200685996f64cc2c3bd6ba790110/lib/net/http.rb#L886

Другие вопросы по тегам