Почему Ruby не может проверить сертификат SSL?
Это моя первая попытка использовать библиотеку xmlrpc:: Client для взаимодействия с удаленным API, и я продолжаю получать эту ошибку:
warning: peer certificate won't be verified in this SSL session
Поиск вокруг, я нашел множество людей, которые получили эту ошибку. Обычно это с самозаверяющими сертификатами, и они просто хотят, чтобы он ушел, поэтому они делают что-то грязное, как monkey patch, как XMLRPC::Client открывает его http-сеанс.
Я сначала предположил, что это был просто клиент не заботясь, будет ли сертификат был действителен или нет, поэтому я продолжил свой поиск и наткнулся этот перл. Он просто заставляет проверять все SSL-сертификаты и выдает жесткую ошибку, если она тоже не в состоянии. Это было именно то, что я хотел. Я включил его, снова запустил код и теперь я получаю это:
OpenSSL:SSL::SSLError:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B:
certificate verify failed
конечно! Сертификат-это плохо! Но я дважды проверяю, чтобы убедиться, что с помощью встроенного s_client openssl:
openssl s_client -connect sub.example.com:443
а что мне делать получить:
CONNECTED(00000003)
---
Certificate chain
<snip>
Verify return code: 0 (ok)
Итак, теперь мы переходим к моему вопросу. OpenSSL (версия командной строки) говорит, что сертификат хорош. OpenSSL (библиотека Ruby) не согласен. Все мои веб-браузеры говорят, что сертификат хорош.
несколько дополнительных деталей, которые могут быть полезны. Сертификат является подстановочным знаком, но действителен для домена. Openssl s_client был запущен на той же машине в секундах от кода Ruby. Это Ruby 1.8.7 p357, который установлен с RVM.
тут Ruby использует что-то другое, кроме пакета CA, предоставленного ОС хоста? Есть ли способ сказать Ruby использовать определенный пакет CA или системный?
2 ответов:
если вас интересует только то, как заставить Ruby вести себя так же, как OpenSSL
s_clientили ваш браузер делает, вы можете перейти к самому последнему разделу, я буду охватывать мелкий шрифт в том, что ниже.по умолчанию
OpenSSL::X509::Storeиспользуется для подключения не использует никаких доверенных сертификатов вообще. Основываясь на ваших знаниях о домене приложения, вы обычно загружаете экземплярX509::Storeс доверенными сертификатами, которые имеют отношение к вашему приложению. Есть несколько вариантов для этого:
- Store#add_file принимает путь к PEM / DER-кодированный сертификат
- Store#add_cert принимает экземпляр X509:: Certificate
- Store#add_path принимает путь к каталогу, где можно найти доверенные сертификаты
Подход "Браузер"
это в отличие от подхода браузеров, Java (cacerts) или Windows с собственным внутренним хранилищем доверенных сертификатов, брать. Там программное обеспечение предварительно оснащается набором доверенных сертификатов, который считается "хорошим" по мнению производителя программного обеспечения. Как правило, это не плохая идея, но если вы действительно посмотрите на эти наборы, то вскоре заметите, что существует слишком много сертификатов. Человек не может действительно сказать, является ли все из этих свидетельств следует доверять слепо или нет.
Рубиновый Подход
требования типичное приложение Ruby, с другой стороны, сильно отличается от браузера. Браузер должен быть в состоянии позволить вам перейти на любой "законный" веб-сайт, который поставляется с сертификатом TLS и обслуживается по протоколу https. Но в типичном приложении Ruby вам придется иметь дело только с несколькими службами, которые используют TLS или иначе требуют проверки сертификата.
и есть преимущество рубинового подхода-хотя он требует больше ручной работы, вы в конечном итоге получите индивидуальное решение, которое точно доверяет сертификатам, которым оно должно доверять в данном контексте приложения. Это утомительно, но безопасность намного выше, таким образом, потому что вы подвергаете гораздо меньше поверхность атаки. Возьмите недавние события: если вам никогда не приходилось включать DigiNotar или любой другой скомпрометированный корень в свой набор доверия, то такие нарушения не могут повлиять на вас.
недостатком этого, однако, как вы уже заметили, что по умолчанию, если вы не активно не добавить доверенные сертификаты, расширение OpenSSL не сможет проверить любой одноранговый сертификат вообще. Для того, чтобы заставить вещи работать, вы должны настроить конфигурацию вручную.
это неудобство привело к множеству сомнительных мер, чтобы обойти его, хуже всего то, чтобы глобально установить
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE. Пожалуйста, не делай этого. Мы даже шутили о добавлении кода, который позволяет вашему приложению аварийно завершать работу, если мы сталкиваемся с этим взломом:)если ручная настройка доверия кажется слишком сложной, теперь я предложу легкую альтернативу, которая заставляет расширение OpenSSL вести себя точно так же, как команды OpenSSL CLI, такие как
s_client.почему s_client может проверить сертификат
OpenSSL использует аналогичный подход к браузерам и Windows. Типичная установка поместит пакет доверенных сертификатов где-то на вашем жестком диске (что-то вроде
/etc/ssl/certs/ca-bundle.crt) и это будет служить набором доверенных сертификатов по умолчанию. Это гдеs_clientвыглядит, когда ему нужно проверить одноранговые сертификаты, и именно поэтому ваш эксперимент удался.заставляя Рубин действовать как s_client
если вы все еще хотите иметь такой же комфорт при проверке сертификатов с помощью Ruby, вы можете сказать ему использовать пакет доверенных сертификатов OpenSSL, если он доступен в вашей системе, позвонив
OpenSSL::X509::Store#set_default_paths. Дополнительную информацию можно найти здесь. Чтобы использовать это сXMLRPC::Client, просто убедитесь, чтоset_default_pathsполучает вызвали наX509::Storeон использует.
Если у вас есть файл ca-certificates, просто сделайте это:
http.ca_file = <YOUR CA-CERT FILE PATH> http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.verify_depth = 5
Comments