【发布时间】: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 PHP 到 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 中的 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 期间连接会失败。
我仍然有兴趣知道:
- 禁用
verify_peer_name有哪些安全隐患?我假设这会使 MITM 连接变得容易。 - 如何进一步诊断 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