如何在PHP流上下文中强制使用某个TLS版本进行 ssl:// 传输?

2022-08-31 00:47:18

尝试访问 URL 时,如何在 PHP 流上下文中强制 TLSv1.0?https

我正在寻找类似这样的东西:

$context = stream_context_create(
  array(
    'ssl' => array(
      'protocol_version' => 'tls1',
    ),
  ));
file_get_contents('https://example.com/test', false, $context);

背景

实际上,我在使用PHP的SoapClient在Ubuntu 12.04中遇到了一个问题。不幸的是,我尝试连接的服务器仅支持 SSLv3.0/TLSv1.0,并且在默认的 TLSv1.1 协商上失败。因此,我想将传输协议显式设置为 TLSv1.0。ssl://


答案 1

PHP 5.6+ 用户

这是 PHP 5.6 OpenSSL 更改页面上记录的新功能。

在撰写本文时,PHP5.6 处于 Beta1 中,因此这并不是太有用。未来的人们 - 幸运的你!

未来就在我们身上。PHP 5.6 是一个东西,应该鼓励使用它。请注意,它弃用了一些相当广泛使用的东西,如mysql_*功能,因此在升级时应小心。

别人

@toubsen的答案是正确的 - 这不可能直接实现。详细阐述他建议的解决方法...当解决供应商的API服务器无法正确协商TLSv1.2到其支持的TLSv1.0的问题时,发送一小部分密码似乎允许协商正确完成。流上下文代码为:

$context = stream_context_create(
    [
        'ssl' => [
            'ciphers' => 'DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA:AES256-SHA:KRB5-DES-CBC3-MD5:KRB5-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:EDH-DSS-DES-CBC3-SHA:DES-CBC3-SHA:DES-CBC3-MD5:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA:AES128-SHA:RC2-CBC-MD5:KRB5-RC4-MD5:KRB5-RC4-SHA:RC4-SHA:RC4-MD5:RC4-MD5:KRB5-DES-CBC-MD5:KRB5-DES-CBC-SHA:EDH-RSA-DES-CBC-SHA:EDH-DSS-DES-CBC-SHA:DES-CBC-SHA:DES-CBC-MD5:EXP-KRB5-RC2-CBC-MD5:EXP-KRB5-DES-CBC-MD5:EXP-KRB5-RC2-CBC-SHA:EXP-KRB5-DES-CBC-SHA:EXP-EDH-RSA-DES-CBC-SHA:EXP-EDH-DSS-DES-CBC-SHA:EXP-DES-CBC-SHA:EXP-RC2-CBC-MD5:EXP-RC2-CBC-MD5:EXP-KRB5-RC4-MD5:EXP-KRB5-RC4-SHA:EXP-RC4-MD5:EXP-RC4-MD5',
        ],
    ]
);

SOAP 用户

PHP 的 SOAP 客户端不使用 curl,也似乎没有使用与 一起设置的默认上下文。因此,创建的上下文需要在第二个参数中传递给 SOAPClient 构造函数,如下所示:stream_context_set_default

$soap_client = new SOAPClient('http://webservices.site.com/wsdlfile.wsdl', array('stream_context' => $context));

为什么是这些密码?

在服务器上运行该命令将为您提供上述格式的受支持密码列表。“运行”会告诉您特定于 TLSv1.2 的那些内容。上面的列表是从OpenSSL报告的所有非TLSv1.2密码编译而来的。openssl ciphersopenssl ciphers -v

openssl ciphers -v | grep -v 'TLSv1.2' | cut -d ' ' -f 1 | tr "\n" ':'


答案 2

如果有人想知道在发出 SOAP 请求时如何“禁用”TLSv1.0...

$parameters = array(
    'trace' => true,
    'exceptions' => true,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'stream_context' => stream_context_create(array(
        'ssl' => array(
            'ciphers' => 'DEFAULT:!TLSv1.0:!SSLv3'
        ),
    )),
    'connection_timeout' => 15
);

$client = new SoapClient(YOUR_WSDL_URL_HERE, $parameters);

这里的关键部分是流上下文密码行。这表示使用默认密码,但不包括 TLSv1.0 密码(1.0 包也具有 TLSv1.1 密码)。的 :是密码包分隔符(包之间的分隔符)和 !这里是告诉它排除这个包(这是一个硬排除,所以如果它出现在列表的后面,它仍然会被排除)。软排除是 - 字符并添加到列表的末尾是+字符。要按顺序添加,只需添加它,前面没有任何东西。

密码信息在这里: https://www.openssl.org/docs/manmaster/man1/ciphers.html#CIPHER-LIST-FORMAT

编辑:无论出于何种原因,包括

'ssl_method' => SOAP_SSL_METHOD_TLS,

选项中的一部分确实让我头疼,并且在某些情况下无法连接。经过大量的故障排除和选项的尝试,我终于意识到删除此设置并让它自动设置它似乎已经解决了这个问题。


推荐