Ubuntu 20.04和Debian 10中ClientHello之后SSL握手失败(适用于Ubuntu 18.04和Debian 9)

Ubuntu 20.04和Debian 10中ClientHello之后SSL握手失败(适用于Ubuntu 18.04和Debian 9),ssl,openssl,handshake,debian-buster,ubuntu-20.04,Ssl,Openssl,Handshake,Debian Buster,Ubuntu 20.04,我一直在尝试使用Oracle云电子邮件交付服务。配置后,它将提供SMTP凭据,您可以使用这些凭据从批准的发件人发送电子邮件 我被一些有趣的场景所困扰。 它在Ubuntu 18.04中工作,但在同一台机器上运行的docker容器(运行Debian 10)中失败 我在用openssl s_客户端测试握手 echo QUIT | openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.c

我一直在尝试使用Oracle云电子邮件交付服务。配置后,它将提供SMTP凭据,您可以使用这些凭据从批准的发件人发送电子邮件

我被一些有趣的场景所困扰。 它在Ubuntu 18.04中工作,但在同一台机器上运行的docker容器(运行Debian 10)中失败

我在用openssl s_客户端测试握手

echo QUIT | openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587
这个命令在Ubuntu 18.04中运行良好,但在运行Debian 10的docker容器中由于握手失败而失败

Docker容器的输出

root@06369bfe7c16:/var/www/html# echo QUIT | openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587
CONNECTED(00000003)
140491098481792:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure:../ssl/record/rec_layer_s3.c:1544:SSL alert number 40
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 199 bytes and written 367 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
root@06369bfe7c16:/var/www/html#
我尝试在这两个版本中检查openssl版本

18.04将于2018年9月11日发布openssl版本
openssl 1.1.1

Docker容器具有openssl版本
openssl 1.1.1d 2019年9月10日

可能与版本有关吗?

我试图通过Wireshark进行更多调试,以了解ClientHello消息是如何发送的-

来自Ubuntu18.04的ClientHello(成功返回)

来自Docker容器的ClientHello消息(导致握手失败SSL警报编号40)

这是来自Ubuntu 18.04的ServerHello消息

TLSv1.2 Record Layer: Handshake Protocol: Multiple Handshake Messages
    Content Type: Handshake (22)
    Version: TLS 1.2 (0x0303)
    Length: 4345
    Handshake Protocol: Server Hello
        Handshake Type: Server Hello (2)
        Length: 81
        Version: TLS 1.2 (0x0303)
        Random: 5ecea16938ffb32685dee0d46241ab4533820a178f3766e6…
        Session ID Length: 32
        Session ID: 5ecea169972b4c49269218eb6d64fbdeedb76539703d48e5…
        Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
        Compression Method: null (0)
        Extensions Length: 9
        Extension: renegotiation_info (len=1)
        Extension: extended_master_secret (len=0)
    Handshake Protocol: Certificate
    Handshake Protocol: Server Key Exchange
        Handshake Type: Server Key Exchange (12)
        Length: 329
        EC Diffie-Hellman Server Params
            Curve Type: named_curve (0x03)
            Named Curve: secp256r1 (0x0017)
            Pubkey Length: 65
            Pubkey: 048f81fb0fcd06c8f1d50620af144965cae3dd3804df3454…
            Signature Algorithm: rsa_pkcs1_sha256 (0x0401)
            Signature Length: 256
            Signature: 76bf06d1a887440d01be65938a92094510ae52e031463d58…
    Handshake Protocol: Server Hello Done
服务器似乎使用了加密套件TLS\u ECDHE\u RSA\u和\u AES\u 128\u GCM\u SHA256,而Docker容器ClientHello中恰好也存在这种加密套件

所以我在这件事上遗漏了什么。我是SSL调试新手

如果密码套件匹配,那么会有什么不同,从而导致服务器返回握手失败

请告诉我下一步可以调查什么

我已将线鲨捕获的图片上传到

有一个来自运行Debian-9(openssl 1.1.0l)的docker容器的捕获,它导致握手成功

更新:
我尝试在最新的Ubuntu 20.04虚拟机中使用openssl s_客户端,但由于握手失败而失败。

这是David Benjamin在github评论中描述的问题之一:

基本上,它是一个有缺陷的服务器。即使它完全能够使用SHA-2散列对签名进行签名,但如果SHA-1不在客户端支持的签名算法散列列表中,它也会失败

为了测试这一点,我首先尝试了以下方法:

$ openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587 -no_tls1_3 -trace -sigalgs "RSA+SHA256"
我收到了你收到的握手失败警报。然后我重试了相同的命令,但添加了一个额外的基于SHA1的sigalg:

$ openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587 -no_tls1_3 -trace -sigalgs "RSA+SHA256:RSA+SHA1"
第二次连接成功


您将在跟踪中注意到,基于docker的OpenSSL版本没有发送任何基于SHA1的签名算法。要解决此问题,您需要另外配置这些证书。

实际问题是此服务器的证书链具有SHA-1根证书,并且客户端声明它不支持证书链中SHA-1证书的验证。阅读TLS 1.2规范(),服务器的行为在合理的解释下是正确的:

   The client uses the "signature_algorithms" extension to indicate to
   the server which signature/hash algorithm pairs may be used in   
   digital signatures.
TLS 1.3规范对这种情况有更多说明():

对于本文本,解释取决于“使用”一词。如果它的意思是“在证书链中使用”,那么服务器的行为是正确的,TLS 1.3规范是自相矛盾的。如果它的意思是“用于验证证书链”,那么服务器的行为是错误的(根据TLS 1.3规则),并且TLS 1.3规范是一致的。我假设后者是更好的解释


因此,服务器遵循TLS 1.2规则,但尚未更新为遵循TLS 1.3规则。作为一个在服务器上工作的工程师,我认为这是一个错误,因为TLS 1.3取代TLS 1.2,但是因为它是两个标准版本之间的行为改变,所以它不是一个特别严重的bug。这很有帮助。那么这应该在服务器端修复吗?最新的OpenSSL版本没有在ClientHello请求中发送基于SHA1的签名算法的原因是什么?或者这些都被弃用了?是的。这是服务器端的问题——尽管(如我所说)可以通过发送基于SHA1的SIGALG在客户端解决。广泛不鼓励使用SHA1(例如,参见)。实际上,从OpenSSL项目获得的最新OpenSSL版本仍然发送基于SHA1的SIGALG。但是,某些平台的OpenSSL下游打包程序正在将默认配置设置为不发送它们。您引用的规范非常清楚,本地根证书(即信任锚)的签名算法并不重要,因为签名无论如何都不会被检查:“自签名的证书或预期为信任锚的证书不会作为链的一部分进行验证,因此可以使用任何算法进行签名。“。因此,根证书是否用SHA-1签名并不重要。Steffen,请重新阅读我写的内容。我说过TLS 1.2规则服务器在合理的解释下是有效的,我引用了TLS 1.3规则的合理解释,你也用粗体引用了,我相信这是一个服务器错误。但是TLS版本之间的规则发生了变化。鉴于根证书的签名首先没有经过验证,因此检查此签名的签名算法没有任何意义。服务器实现可能只是简单地检查发送到客户端的所有证书上的签名算法,这是基于这样的假设:根证书首先不会由服务器发送,因为这样做没有意义(即,这也是服务器端的错误配置)。
$ openssl s_client -starttls smtp -crlf -connect smtp.email.ap-mumbai-1.oci.oraclecloud.com:587 -no_tls1_3 -trace -sigalgs "RSA+SHA256:RSA+SHA1"
   The client uses the "signature_algorithms" extension to indicate to
   the server which signature/hash algorithm pairs may be used in   
   digital signatures.
   All certificates provided by the server MUST be signed by a signature
   algorithm advertised by the client if it is able to provide such a
   chain (see Section 4.2.3).  Certificates that are self-signed or
   certificates that are expected to be trust anchors are not validated
   as part of the chain and therefore MAY be signed with any algorithm.

   If the server cannot produce a certificate chain that is signed only
   via the indicated supported algorithms, then it SHOULD continue the
   handshake by sending the client a certificate chain of its choice
   that may include algorithms that are not known to be supported by the
   client.  This fallback chain SHOULD NOT use the deprecated SHA-1 hash
   algorithm in general, but MAY do so if the client's advertisement
   permits it, and MUST NOT do so otherwise.