【问题标题】:Ruby 1.8.7 and Net::HTTP: Making an SSL GET request with client cert?Ruby 1.8.7 和 Net::HTTP:使用客户端证书发出 SSL GET 请求?
【发布时间】:2012-02-17 22:44:51
【问题描述】:

我正在尝试使用Net::HTTP 获取资源通过 SSL。以下是相关代码片段:

req = Net::HTTP::Get.new(ContentURI.path)
https = Net::HTTP.new(ContentURI.host, ContentURI.port)
https.use_ssl = true
https.cert = OpenSSL::X509::Certificate.new(@cert_raw)
https.key = OpenSSL::PKey::RSA.new(@cert_key_raw)
https.verify_mode = OpenSSL::SSL::VERIFY_PEER
https.ca_file = File.join(TestDataPath, 'cacert.pem')
resp = https.start { |cx| cx.request(req) }

或使用备用的最后一行:

resp = https.get(ContentURI.path)

我已经验证了各个位(证书、密钥、CA 证书、)都是正确的。

问题是cx.request(req)抛出异常:

OpenSSL::SSL::SSLError: SSL_connect SYSCALL returned=5 errno=0 state=SSLv3 read server session ticket A

服务器上的 Apache SSL 错误日志包含以下内容:

[Tue Jan 24 11:47:26 2012] [debug] ssl_engine_kernel.c(1876): OpenSSL: Loop: SSLv3 read finished A
[Tue Jan 24 11:47:26 2012] [debug] ssl_engine_kernel.c(1905): OpenSSL: Exit: error in SSLv3 write session ticket A
[Tue Jan 24 11:47:26 2012] [debug] ssl_engine_kernel.c(1905): OpenSSL: Exit: error in SSLv3 write session ticket A
[Tue Jan 24 11:47:26 2012] [info] [client 10.11.88.53] SSL handshake interrupted by system [Hint: Stop button pressed in browser?!]
[Tue Jan 24 11:47:26 2012] [info] [client 10.11.88.53] Connection closed to child 0 with abortive shutdown (server _SERVERNAME_:443

证书、密钥和 CA 证书文件通过其他工具与此 SSL 主机配合使用;我只是在使用Net::HTTP[S] 以编程方式重现该成功时遇到了麻烦。

感谢任何能找出我做错了什么的人!

【问题讨论】:

    标签: ruby ssl certificate client-certificates net-http


    【解决方案1】:

    我会说这是您的 Apache 设置问题,而不是 Ruby 本身的问题。

    看看这个:

    $ curl https://palladium.wejn.cz/sslcerttest/
    curl: (56) SSL read: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure, errno 0
    $ curl https://palladium.wejn.cz/sslcerttest/ -E client.pem
    <pre>Yop.</pre>
    

    然后:

    #!/usr/bin/ruby
    require 'net/http'
    require 'net/https'
    require 'openssl'
    require 'uri'
    
    ContentURI = URI.parse("https://palladium.wejn.cz/sslcerttest/")
    @cert_raw = File.read('client.pem')
    @cert_key_raw = @cert_raw
    TestDataPath = '.'
    
    req = Net::HTTP::Get.new(ContentURI.path)
    https = Net::HTTP.new(ContentURI.host, ContentURI.port)
    https.use_ssl = true
    https.cert = OpenSSL::X509::Certificate.new(@cert_raw)
    https.key = OpenSSL::PKey::RSA.new(@cert_key_raw)
    https.verify_mode = OpenSSL::SSL::VERIFY_PEER
    https.ca_file = File.join(TestDataPath, 'cacert.pem')
    resp = https.start { |cx| cx.request(req) }
    p resp
    p resp.body
    

    结果:

    $ ruby a.rb
    #<Net::HTTPOK 200 OK readbody=true>
    "<pre>Yop.</pre>\n"
    
    $ dpkg -l ruby1.8 | tail -n1 | awk '{print $3}'
    1.8.7.302-2squeeze1
    
    $ ruby -v
    ruby 1.8.7 (2010-08-16 patchlevel 302) [x86_64-linux]
    

    当然,有问题的 apache 配置是:

    <Directory /var/www/sslcerttest/>
        SSLVerifyClient require
        SSLVerifyDepth 5
        SSLCACertificateFile /var/www/sslcerttest/cacert.pem
        SSLCACertificatePath /var/www/sslcerttest/
        SSLOptions +FakeBasicAuth
        SSLRequireSSL
        SSLRequire %{SSL_CLIENT_S_DN_O} eq "Wejn s.r.o." and %{SSL_CLIENT_S_DN_OU} eq "Server Certificate"
    </Directory>
    

    在跟踪此问题时,发布其他详细信息(用于测试的 apache 配置)可能会有所帮助...

    【讨论】:

    • 查看openssl源码,错误信息与缺少会话票证有关(恢复ssl会话需要客户端提供的数据);不知道为什么会在这种情况下发生这种情况......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 1970-01-01
    • 2013-07-08
    • 2022-07-01
    相关资源
    最近更新 更多