为什么PHP / OpenSSL拒绝此通配TLS证书?

时间:2019-02-06 08:49:36

标签: php openssl smtp phpmailer starttls

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

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

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

当我通过运行命令echo QUIT | .\openssl.exe s_client -starttls smtp -crlf -connect prefix.myredactedcompany.mailguard.com.au:2525按照PHPMailer故障排除指南对test 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中的注释说空的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验证之后?

1 个答案:

答案 0 :(得分: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之类的包从您的应用程序中对其进行管理。

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