【问题标题】:Why is PHP/OpenSSL rejecting this wildcard TLS certificate?为什么 PHP/OpenSSL 拒绝此通配符 TLS 证书?
【发布时间】:2019-06-30 04:07:33
【问题描述】:

我正在尝试使用 PHPMailer 通过 TLS 上的 SMTP 发送电子邮件。

我发现当 PHPMailer 尝试连接 SMTP 服务器并调用 STARTTLS 时,连接立即失败——除非我在打开 SMTP 连接时设置了PHP SSL context variableverify_peer_name => false

我要连接的 SMTP 服务器是 prefix.myredactedcompany.mailguard.com.au:2525。查看 SMTP 日志,我看到当我要求连接到 prefix.myredactedcompany.mailguard.com.au:2525 时,我实际上连接到了 someotherhost.mailguard.com.au。我认为这是负载平衡器或其他集群设置的结果。

当我按照 PHPMailer 故障排除指南通过运行命令 test the OpenSSL connection outside of PHPtest the OpenSSL connection outside of PHP 时,我得到以下结果:

CONNECTED(000001E0)
---
Certificate chain
 0 s:/C=AU/postalCode=3006/ST=VIC/L=SOUTHBANK/street=198 NORMANBY RD/O=MailGuard Pty Ltd/OU=Netops/OU=PremiumSSL Wildcard/CN=*.mailguard.com.au
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIF0jCCBLqgAwIBAgIQI1raes2jQvcAbHxOBIAtqTANBgkqhkiG9w0BAQsFADCB
... snip ...
pYwh4eDZtcm4tZQfc71R1KhA9ci5A0G9ewPLmZUYoDlguNdlNlVf07aus54EV6XI
1wHfJ/xs
-----END CERTIFICATE-----
subject=/C=AU/postalCode=3006/ST=VIC/L=SOUTHBANK/street=198 NORMANBY RD/O=MailGuard Pty Ltd/OU=Netops/OU=PremiumSSL Wildcard/CN=*.mailguard.com.au
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5395 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: redacted
    Session-ID-ctx: 
    Master-Key: redacted
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - 18 ad e7 c2 c9 46 ab 96-5f 58 03 81 fc 48 3c 18   .....F.._X...H<.
    ... snip ...
    0090 - 41 47 9b f2 60 c4 41 5f-0d fc ea 2b 40 0c 25 3b   AG..`.A_...+@.%;

    Start Time: 1549441609
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---

PHPMailer 故障排除指南在这种情况下说

verify error:num=20:unable to get local issuer certificate 不是问题。

在我看来,这对于mailguard.com.au 的所有子域来说都是一个有效的通配符证书。为什么 PHPMailer/OpenSSL 会拒绝它,除非我关闭对等名称验证?是不是因为实际的 SMTP 主机名与我建立出站连接时使用的 DNS 名不匹配?

如果我关闭对等名称验证,这会给我带来哪些安全风险?

版本:

  • PHP 7.1.7
  • PHPMailer 6.0.6
  • OpenSSL 1.0.2l
  • 通过 XAMPP 7.1.7 在 Windows 上运行(如果重要)

一位评论者询问直接连接到池中的一台主机时,openssl 连接结果如何。非常相似:

CONNECTED(000001F8)
---
Certificate chain
 0 s:/C=AU/postalCode=3006/ST=VIC/L=SOUTHBANK/street=198 NORMANBY RD/O=MailGuard Pty Ltd/OU=Netops/OU=PremiumSSL Wildcard/CN=*.mailguard.com.au
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIF0jCCBLqgAwIBAgIQI1raes2jQvcAbHxOBIAtqTANBgkqhkiG9w0BAQsFADCB
...snip...
pYwh4eDZtcm4tZQfc71R1KhA9ci5A0G9ewPLmZUYoDlguNdlNlVf07aus54EV6XI
1wHfJ/xs
-----END CERTIFICATE-----
subject=/C=AU/postalCode=3006/ST=VIC/L=SOUTHBANK/street=198 NORMANBY RD/O=MailGuard Pty Ltd/OU=Netops/OU=PremiumSSL Wildcard/CN=*.mailguard.com.au
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Organization Validation Secure Server CA
---
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 5399 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES256-GCM-SHA384
    Session-ID: redacted
    Session-ID-ctx: 
    Master-Key: redacted
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - 6d bd 68 e7 44 29 72 ea-99 00 c8 84 a6 cc 45 76   m.h.D)r.......Ev
    ... snip ...
    0090 - 28 73 65 a4 a1 24 fd c6-18 ad fb 13 26 ec 6f b9   (se..$......&.o.

    Start Time: 1549519771
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---

好的,php.ini 中的 cmets 说空的 openssl.cafile 设置将导致 PHP 使用操作系统管理的证书存储。这在 Windows 上似乎不正确,因为 OpenSSL 没有对 Windows 证书存储的内置支持。因此,我按照PHP - SSL certificate error: unable to get local issuer certificate 中的说明设置了本地根 CA 捆绑包。这似乎现在起作用了。当我运行上面给出的 OpenSSL 测试命令并附加 -CAfile C:\xampp\extras\cacert.pem 时,最终结果现在是 Verify return code: 0 (ok) 而不是 Verify return code: 20 (unable to get local issuer certificate)

我已经重新启动了 Apache 并检查了 phpinfo() 中 openssl.cafile 的值是否正常。但是 PHPMailer 仍然不会成功 STARTTLS。症状与以前相同 - 如果我将 SSL 上下文变量 verify_peer_name 设置为 false,则 PHPMailer 成功连接。如果我将 verify_peer_name 保持打开状态,则在 STARTTLS 期间连接会失败。

我仍然有兴趣知道:

  1. 禁用verify_peer_name 有哪些安全隐患?我假设这会使 MITM 连接变得容易。
  2. 如何进一步诊断 STARTTLS 失败的确切原因,尤其是在证书通过 OpenSSL 验证的情况下?

【问题讨论】:

  • “我实际上已连接到someotherhost.mailguard.com.au - 如果您直接使用该主机名运行该 openssl check 命令会得到什么结果?
  • 可能是因为通配符只匹配一个级别,即prefix.myredactedcompany.mailguard.com.au不匹配*.mailguard.com.au。或者,它可能归结为 PHP 正在使用的 CA 证书包。
  • 你可能会发现testssl.sh 的输出更容易理解,如果你能让它在 Windows 上运行的话。
  • @O4FS 我打开了一个到主主机名的 telnet 会话,记下了我连接到的主机名,然后对该主机运行 OpenSSL 诊断命令。我已将结果附加到问题的底部。它看起来与我基本相同。
  • 根据phpinfo(),openssl.cafile和openssl.capath配置设置都是空的。 php.ini cmets 说“PHP 将尝试在 [openssl.cafile's] 缺席的情况下使用操作系统管理的证书存储”,但在 Windows 上可能不是这样?各种网页显示 OpenSSL 无法读取 Windows 证书存储区。

标签: php openssl smtp phpmailer starttls


【解决方案1】:

这可能是因为通配符只匹配一个级别,即prefix.myredactedcompany.mailguard.com.au 不匹配*.mailguard.com.au。使用报告的名称(连接时看到)应该有助于解决这个问题。

或者,它可能归结为 PHP 正在使用的 CA 证书包,这意味着服务器正常,但您无法正确验证其证书 - 这通常很难诊断,因为它可能很难判断在哪里您的链验证失败。例如,如果您的连锁店是:

host cert -> intermediate cert -> root (CA) cert

其中任何一个验证失败都会导致验证失败,但可能不清楚哪个是错误的。

您可能需要获取最新 CA 证书包的副本并告诉 PHP 使用它(如 the PHPMailer troubleshooting guide 中所述),或者使用像 Certainty 这样的包从您的应用程序中管理它。

也可能是您的中间证书的顺序错误。

【讨论】:

  • 谢谢。我们遇到的两个问题是:1)我们被告知要连接的主机名具有比 SMTP 服务器上配置的通配符证书更多级别的子域;和 2) stock XAMPP 7.1.7 实际上并没有将 OpenSSL 配置为使用 XAMPP 中包含的 CA 包。现在我不需要禁用verify_peer_name
猜你喜欢
  • 2014-12-17
  • 2019-07-23
  • 1970-01-01
  • 2019-07-06
  • 2018-12-13
  • 2014-07-04
  • 1970-01-01
  • 2021-01-03
  • 1970-01-01
相关资源
最近更新 更多