Ruby 带有 ca 认证的 https 在与 curl 一起工作时不起作用
Ruby https with ca certification does not work while it worked with curl
在 ruby 中,我尝试使用自动签名证书与我在本地设置的 nginx 服务器建立 ssl 连接。我的代码是:
require "net/http"
require "net/https"
require "openssl"
require "uri"
require "pp"
request = Net::HTTP::Get.new("/")
response = Net::HTTP.start(
"localhost",
443,
{
:use_ssl => true,
:key => OpenSSL::PKey::RSA.new(File.read("/home/gg/crt/client.key")),
:cert => OpenSSL::X509::Certificate.new(File.read("/home/gg/crt/client.crt")),
:ca_file => "/home/gg/crt/ca.pem",
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:verify_depth => 5,
}
) do |http|
http.request(request)
end
puts response.inspect
puts response.body
当我运行它它return
/home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `connect': SSL_connect returned=1 errno=0 state=error: certificate verify failed (OpenSSL::SSL::SSLError)
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `block in connect'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/timeout.rb:74:in `timeout'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `connect'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:852:in `start'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:583:in `start'
from testso.rb:8:in `<main>'
但是如果我 运行 使用 curl 得到正确的结果:
curl https://localhost --key crt/client.key --cert crt/client.crt --cacert crt/ca.pem
我做错了什么?
我觉得自己很笨,但想通了问题。
生成不同的证书时,我将一些字段留空。
openssl 似乎将此证书检测为 "looking" 自动签名。
因此如果我们使用 OpenSSL::SSL::VERIFY_PEER 连接失败
因此,要确保使用 CA 正确生成证书,您可以执行以下操作:
openssl verify -CAfile ca.crt server.crt
(与 client.crt 相同的命令)
如果我们得到
error 18 at 0 depth lookup:self signed certificate
OK
证书被检测为自动签名但失败
如果我们得到
Signature ok
它应该有效
为了可能帮助其他人,这里有一个 Ruby 2.0 的工作解决方案,用于 HTTP GET。
require "net/http"
uri = URI.parse('https://your_url.com')
http = Net::HTTP.new(uri.host, uri.port)
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ssl_version]=nil
http.use_ssl = true
http.ca_path='/etc/pki/tls/certs/'
http.ca_file='/etc/pki/tls/certs/YOUR_CERT_CHAIN_FILE'
http.cert = OpenSSL::X509::Certificate.new(File.read("YOUR_CERT)_FILE"))
http.key = OpenSSL::PKey::RSA.new(File.read("YOUR_KEY_FILE"))
#SSLv3 is cracked, and often not allowed
http.ssl_version = :TLSv1_2
#### This is IMPORTANT
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#Crete the GET request
request = Net::HTTP::Get.new(uri.request_uri)
#Add Headers, if needed
request.add_field 'X_REMOTE_USER', 'USER_NAME'
request.add_field 'Accept', '*'
#Get Response
response = http.request(request)
#Review Response
puts response.body
在 ruby 中,我尝试使用自动签名证书与我在本地设置的 nginx 服务器建立 ssl 连接。我的代码是:
require "net/http"
require "net/https"
require "openssl"
require "uri"
require "pp"
request = Net::HTTP::Get.new("/")
response = Net::HTTP.start(
"localhost",
443,
{
:use_ssl => true,
:key => OpenSSL::PKey::RSA.new(File.read("/home/gg/crt/client.key")),
:cert => OpenSSL::X509::Certificate.new(File.read("/home/gg/crt/client.crt")),
:ca_file => "/home/gg/crt/ca.pem",
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
:verify_depth => 5,
}
) do |http|
http.request(request)
end
puts response.inspect
puts response.body
当我运行它它return
/home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `connect': SSL_connect returned=1 errno=0 state=error: certificate verify failed (OpenSSL::SSL::SSLError)
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `block in connect'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/timeout.rb:74:in `timeout'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:923:in `connect'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:852:in `start'
from /home/gg/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/net/http.rb:583:in `start'
from testso.rb:8:in `<main>'
但是如果我 运行 使用 curl 得到正确的结果:
curl https://localhost --key crt/client.key --cert crt/client.crt --cacert crt/ca.pem
我做错了什么?
我觉得自己很笨,但想通了问题。
生成不同的证书时,我将一些字段留空。 openssl 似乎将此证书检测为 "looking" 自动签名。
因此如果我们使用 OpenSSL::SSL::VERIFY_PEER 连接失败
因此,要确保使用 CA 正确生成证书,您可以执行以下操作:
openssl verify -CAfile ca.crt server.crt
(与 client.crt 相同的命令)
如果我们得到
error 18 at 0 depth lookup:self signed certificate
OK
证书被检测为自动签名但失败
如果我们得到
Signature ok
它应该有效
为了可能帮助其他人,这里有一个 Ruby 2.0 的工作解决方案,用于 HTTP GET。
require "net/http"
uri = URI.parse('https://your_url.com')
http = Net::HTTP.new(uri.host, uri.port)
OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:ssl_version]=nil
http.use_ssl = true
http.ca_path='/etc/pki/tls/certs/'
http.ca_file='/etc/pki/tls/certs/YOUR_CERT_CHAIN_FILE'
http.cert = OpenSSL::X509::Certificate.new(File.read("YOUR_CERT)_FILE"))
http.key = OpenSSL::PKey::RSA.new(File.read("YOUR_KEY_FILE"))
#SSLv3 is cracked, and often not allowed
http.ssl_version = :TLSv1_2
#### This is IMPORTANT
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#Crete the GET request
request = Net::HTTP::Get.new(uri.request_uri)
#Add Headers, if needed
request.add_field 'X_REMOTE_USER', 'USER_NAME'
request.add_field 'Accept', '*'
#Get Response
response = http.request(request)
#Review Response
puts response.body