【问题标题】:Ruby net/imap getting OpenSSL::SSL::SSLError - self-signed certificate?Ruby net/imap 获取 OpenSSL::SSL::SSLError - 自签名证书?
【发布时间】:2019-05-09 18:34:40
【问题描述】:

在尝试开发一个使用 IMAP 访问 Gmail 的工具时,即使是这个简单的启动代码,我也遇到了困难:

require 'net/imap'
imap = Net::IMAP.new('imap.gmail.com', ssl: true)

运行,失败如下(注意:为了便于展示,略作编辑)

Traceback (most recent call last):
        5: from test-imap:2:in `<main>'
        4: from test-imap:2:in `new'
        3: from /.../.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/net/imap.rb:1092:in `initialize'
        2: from /.../.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/net/imap.rb:1533:in `start_tls_session'
        1: from /.../.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/net/protocol.rb:44:in `ssl_socket_connect'
/.../.rvm/rubies/ruby-2.6.0/lib/ruby/2.6.0/net/protocol.rb:44:in
  `connect_nonblock': SSL_connect returned=1 errno=0 state=error:
  certificate verify failed (self signed certificate) (OpenSSL::SSL::SSLError)

四处搜索,我发现了一些类似的问题,例如imap-backup issue #57ruby/openssl issue #238在撰写本文时仍然开放在分享下面的答案后关闭)和rbenv/ruby-build issue #380...但没有任何内容。

将以上资源中的信息拼凑在一起,我想出了这个命令来尝试:

openssl s_client -connect imap.gmail.com:993 \
  -CAfile $(ruby -ropenssl -e 'puts OpenSSL::X509::DEFAULT_CERT_FILE') \
  < /dev/null > /dev/null

哪些报告:

depth=2 /OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
verify return:1
depth=1 /C=US/O=Google Trust Services/CN=Google Internet Authority G3
verify return:1
depth=0 /C=US/ST=California/L=Mountain View/O=Google LLC/CN=imap.gmail.com
verify return:1
DONE

因此,SSL 证书似乎确实以这种方式验证为 OK(正如人们所期望的那样)。

我确实找到了some instructions,因为它在禁用主机检查的情况下使用带有 SSL 的 net/imap,这是可行的……但我真的不想这样做。

我还找到了non-IMAP gmail interface,但我的意图是一个也可以与其他 IMAP 提供程序一起使用的工具,所以我特别打算在这里坚持使用 IMAP。所以:

我怎样才能让net/imap 使用 SSL 成功连接,并且仍然验证证书(假设它实际上是有效的)?

【问题讨论】:

    标签: ruby ssl imap gmail-imap


    【解决方案1】:

    理想:升级到 Ruby 2.6.3 或更高版本

    升级到 Ruby 版本 2.6.3 或更高版本应该可以解决问题,因为为 related issue #15594 提供修复的 ruby pull #2077 已合并到 2.6.3 change list 中。在 2.6.3 中,问题中的原始测试 sn-p 现在可以工作了。

    如果无法升级:

    也就是说,如果由于某种原因升级不切实际,commit that fixed imap-backup issue #57 提供了一种解决方法类型的解决方案。而不是以下内容:

    imap = Net::IMAP.new('imap.gmail.com', ssl: true)
    

    试试这个:

    imap = Net::IMAP.new('imap.gmail.com', ssl: {ssl_version: :TLSv1_2})
    

    即使在 Ruby 2.6.0 中,这似乎也能正常工作。

    【讨论】:

      【解决方案2】:

      在 Ruby 2.4 中,我不得不使用这个补丁:

      require 'net/imap'
      
      class Net::IMAP
        module UseSNI
          def start_tls_session(*)
            @sock.instance_variable_set(:@hostname, @host)
            super
          end
        end
      
        prepend UseSNI
      end
      
      class OpenSSL::SSL::SSLSocket
        module UseSNI
          def connect(*)
            self.hostname = io.instance_variable_get(:@hostname)
            super
          end
        end
      
        prepend UseSNI
      end
      

      【讨论】:

        猜你喜欢
        • 2012-09-26
        • 1970-01-01
        • 2016-08-26
        • 2012-03-06
        • 1970-01-01
        • 2013-01-06
        • 2021-11-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多