【问题标题】:Ruby TCP server with OpenSSL and Letsencrypt certificate带有 OpenSSL 和 Letsencrypt 证书的 Ruby TCP 服务器
【发布时间】:2020-01-15 16:35:12
【问题描述】:

我想使用 Letsencrypt 生成的证书设置一个带有 SSL 层的最小 Ruby TCP 服务器。

我安装软件包(系统是 Ubuntu 18,64 位):

    sudo apt install ruby certbot

我像这样生成证书:

    certonly -d example.com

然后运行以下代码:

    require "socket"
    require "openssl"
    require "base64"

    port = 443
    cert_path = "/etc/letsencrypt/live/example.com/fullchain.pem"
    key_path = "/etc/letsencrypt/live/example.com/privkey.pem"
    chain_path = "/etc/letsencrypt/live/example.com/chain.pem"

    context = OpenSSL::SSL::SSLContext.new
    context.cert = OpenSSL::X509::Certificate.new( File.read( cert_path ))
    context.key = OpenSSL::PKey::RSA.new( File.read( key_path ))
    context.extra_chain_cert = OpenSSL::X509::Certificate.new( File.read( chain_path ))
    tcp_server = TCPServer.new( port )
    ssl_server = OpenSSL::SSL::SSLServer.new( tcp_server, context )

    loop {

        client = ssl_server.accept

        data = client.gets
        response = "I got #{data.dump}"

        puts response
        client.puts response
        client.close

    }

然后像这样使用 curl 发送一个 POST 请求:

    curl --data "param1=value1&param2=value2" https://example.com

然后我收到以下错误消息:

Traceback (most recent call last):
5: from api.rb:35:in `<main>'
4: from api.rb:35:in `loop'
3: from api.rb:37:in `block in <main>'
2: from /var/lib/gems/2.5.0/gems/openssl-2.1.2/lib/openssl/ssl.rb:483:in `accept'
1: from /var/lib/gems/2.5.0/gems/openssl-2.1.2/lib/openssl/ssl.rb:483:in `new'
/var/lib/gems/2.5.0/gems/openssl-2.1.2/lib/openssl/ssl.rb:483:in `initialize': undefined method `each' for #<OpenSSL::X509::Certificate:0x0000556df03c22c0> (NoMethodError)

你们能帮我找出问题所在吗?我已经为此苦苦挣扎了一段时间。官方示例在这里也不起作用:

https://docs.ruby-lang.org/en/2.1.0/OpenSSL.html#module-OpenSSL-label-SSL+and+TLS+Connections

我在一个 SO 线程中读到,对于 Letsencrpyt 证书,我应该包含 .extra_chain_cert 属性。问题还是一样。

谢谢。

【问题讨论】:

    标签: ruby openssl


    【解决方案1】:

    根据documentationextra_chain_cert 属性应该是一个数组,但您只是将其设置为单个证书。 openssl gem 正在崩溃,因为它希望该属性是一个数组,并在其上调用 each 方法来迭代数组的元素。

    您可以尝试将您的证书放入一个单元素数组中,方法是将其括在方括号中([])。

    context.extra_chain_cert = [OpenSSL::X509::Certificate.new(File.read(chain_path))]
    

    我刚刚在这里使用我自己的 Lets Encrypt 证书对其进行了测试,它对我有用。我使用了 444 端口,当我将浏览器指向 https://example.com:444 时,Ruby 程序说:

    I got "GET / HTTP/1.1\r\n"
    

    【讨论】:

    • 请注意,一般而言,可能需要任意数量的中间证书来形成从您的证书返回到受信任根的完整信任链。我的回答只有在只有一个证书的情况下才有效,因此如果 Lets Encrypt 开始使用更长的链,将来可能需要修复它。
    猜你喜欢
    • 1970-01-01
    • 2018-11-21
    • 2012-09-26
    • 2018-11-29
    • 2014-09-05
    • 2019-07-19
    • 2017-01-16
    • 2015-10-14
    • 1970-01-01
    相关资源
    最近更新 更多