我们如何在 Guzzle 中指定 TLS/SSL 选项?

Posted

技术标签:

【中文标题】我们如何在 Guzzle 中指定 TLS/SSL 选项?【英文标题】:How do we specify TLS/SSL options in Guzzle? 【发布时间】:2016-01-13 01:40:05 【问题描述】:

我们开始在 php 中使用 Guzzle,其代码调用各种不同的 API,其中一些不支持 TLSv1.2,其中一些需要 TLSv1.2。

强制 Guzzle 使用可用的最新协议的最佳方法是什么,除非我们知道它不会被识别?

【问题讨论】:

【参考方案1】:

简单易行。

$client = new Client();
$guzzle = new GuzzleClient('https://www.yourweb.com', array(
    'curl.options' => array(
        CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2
    )
));
$client->setClient($guzzle);
...

在 Guzzle 3.0+ 中(根据@limos 的评论更新):

'curl' => array(
    CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2
)

可能的CURLOPT_SSLVERSION选项可以在官方cURL页面找到:http://curl.haxx.se/libcurl/c/CURLOPT_SSLVERSION.html

--- 更新(基于 cmets)---

选择正确的 SSL 协议版本不仅涉及 CURLOPT_SSLVERSION 设置,还涉及更多 cURL 设置。期望和重要的结果称为“最大前向保密”。 这不仅适用于 cURL!

您不能使用多个CURLOPT_SSLVERSION 参数(至少,我在 Guzzle 文档中没有找到这样的选项)。当您定义 CURLOPT_SSLVERSION 时,cURL 将尝试使用该 SSL 版本 - 从 cURL 文档(上面提供的关于 CURLOPT_SSLVERSION 的链接) - “传递一个 long as 参数来控制要尝试的 SSL/TLS 版本使用。”

您可以定义多个安全密码,但只能定义一个 SSL 版本参数。我不会使用早于 TLS 1.1 的任何东西。任何早期的 SSL 版本都容易受到攻击。版本 TLS 1.1 也很容易受到攻击,但如果你走这条路,你可能会在 1.2 中遇到客户端兼容性问题。唯一安全的(目前,直到他们发现一些漏洞)是 TLS 1.2。

如果安全性是重中之重,请使用最高可用的 TLS 版本 (TLS1.2)。当存在服务提供商安全责任时,客户端兼容性不是您的问题。

如果安全很重要,这里有其他 cURL 选项可供查看:

CURLOPT_SSL_VERIFYHOST CURLOPT_SSL_VERIFYPEER CURLOPT_CAINFO(cURL 在他们的网站上提供 CA CERTs) CURLOPT_SSL_CIPHER_LIST

设置正确的CURLOPT_SSL_VERIFYHOSTCURLOPT_SSL_VERIFYPEER 将防止MITM 攻击。

CURLOPT_CAINFO - 修复错误:35 - 连接中的未知 SSL 协议错误。提高最大前向保密性。

这里有一个包含 cURL 密码 (CURLOPT_SSL_CIPHER_LIST) 的列表供您研究,这将提高最大前向保密性:

'DHE-RSA-AES256-SHA',
'DHE-DSS-AES256-SHA',
'AES256-SHA',
'ADH-AES256-SHA',
'KRB5-DES-CBC3-SHA',
'EDH-RSA-DES-CBC3-SHA',
'EDH-DSS-DES-CBC3-SHA',
'DHE-RSA-AES128-SHA',
'DHE-DSS-AES128-SHA',
'ADH-AES128-SHA',
'AES128-SHA',
'KRB5-DES-CBC-SHA',
'EDH-RSA-DES-CBC-SHA',
'EDH-DSS-DES-CBC-SHA:DES-CBC-SHA',
'EXP-KRB5-DES-CBC-SHA',
'EXP-EDH-RSA-DES-CBC-SHA',
'EXP-EDH-DSS-DES-CBC-SHA',
'EXP-DES-CBC-SHA'

根据 Qualys SSL Labs 强列表 (2014) 检查了这些密码,并删除了弱密码。随意添加/删除任何密码。

如果您仍想追求多个CURLOPT_SSLVERSION 选项,我会编写一个脚本来执行此操作(我认为这不是一个好的做法或必要的)。但是,如果您出于任何原因决定使用该功能,请编写一些代码尝试使用最强的 SSL 加密,然后在连接失败时回退到下一个版本。

    在您做出决定之前,请先查看 Qualys SSL 实验室关于安全性的 projects。 查看this SSL Labs' article,了解完美的前向保密和最佳实践。 使用SSL Labs' web tool 测试您的客户端(Web 浏览器)是否存在任何漏洞。这将使您了解在您的服务器和应用上应该查看哪些内容以及需要改进和保护哪些内容。 使用 Qualys 的 SSL 实验室 SSL tool 测试您的网站/网络服务。

漏洞和攻击:Longjam、FREAK、POODLE,应有尽有!谁知道还有哪些其他攻击或漏洞未被发现?是的!它们都会影响您对 SSL/TLS 连接的选择。

您无法控制客户端(除非您开发它),但您可以控制服务器和服务器-客户端协商。

无论您构建什么应用程序,您都应该查看最佳实践,根据您的需求和具体情况,您应该决定以下选项:

    安全性 兼容性 可维护性 复杂性

如果安全性如此重要,请至少使用 TLS1.1。 还要看密码列表,我不会忽略那部分。

您的应用周围还有一个不错的OWASP guide for creating a secure layer。

OWASP 和 Qualys SSL Labs 是很好的入门资源。我什至会对 cURL 和 OpenSSL 进行一些研究,以熟悉弱点、可能的安全选项和最佳实践。

有一些安全点,我没有提到,也没有,但我们无法涵盖所有​​内容。这只是冰山一角。 此处未提及的内容供您研究。

祝你好运!

如果可以的话,我会随时回答任何问题。

【讨论】:

好的,所以我们可以让它自动协商(默认)或者只设置一个协议版本来接受?我希望有一种方法可以给它一组协议版本并让它选择最新的。 正确,您不能使用多个 CURLOPT_SSLVERSION 参数(至少,我在 Guzzle 文档中没有找到这样的选项)。当您定义 CURLOPT_SSLVERSION 时,cURL 将尝试使用该 SSL 版本。从 cURL 文档(提供的链接)“传递一个 long as 参数来控制尝试使用哪个版本的 SSL/TLS。”您可以定义多个安全密码,但只能定义一个 ssl 版本参数。我不会使用早于 TLS 1.1 的任何东西。任何早期的 SSL 版本都容易受到攻击。 v1.1 也存在漏洞,但我们会在 1.2 中遇到客户端兼容性问题 我决定更新我的答案,因为您的问题没有简单的答案。 只是添加 - 在 Guzzle 3.0 中,关键是“curl”而不是“curl.options”。此外,常量应该不带引号 @limos 不错。感谢您指出了这一点!我做了更新。 :)【参考方案2】:

在 Guzzle 5.3 中,我必须使用以下语法:

$guzzle = new \GuzzleHttp\Client([
    'defaults' => [
        'config' => [
            'curl' => [
                CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1_2
            ]
        ]
    ]
]);

【讨论】:

以上是关于我们如何在 Guzzle 中指定 TLS/SSL 选项?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Security 中指定 Open ID Realm?

如何从急切加载中指定我们想要的列

如何在 XIB 中指定左、右或标题视图按钮

如何删除PDF文档中指定的一页文件?

如何在 CMake 中指定链接类型?

如何在 SQL Server 的交叉应用联接中指定列名