如何在ssl:// transport的PHP流上下文中强制某个TLS版本?

Chr*_*iki 12 php ssl

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

我正在寻找类似的东西:

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

背景

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

phi*_*vin 15

PHP 5.6+用户

这是PHP 5.6 OpenSSL Changes页面中记录的新功能.

在撰写本文时,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',
        ],
    ]
);
Run Code Online (Sandbox Code Playgroud)

SOAP用户

PHP的SOAP客户端不使用curl,也不使用默认的上下文集stream_context_set_default.因此,创建的上下文需要在第二个参数中传递给SOAPClient构造函数,如下所示:

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

为什么那些密码?

openssl ciphers在服务器上运行该命令可以获得上述格式的受支持密码列表.Running openssl ciphers -v告诉你那些特定于TLSv1.2的那些.上面的列表是从OpenSSL报告的所有非TLSv1.2密码编译而来的.

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


Rob*_*han 5

如果有人想知道如何在发出 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);
Run Code Online (Sandbox Code Playgroud)

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

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

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

'ssl_method' => SOAP_SSL_METHOD_TLS,
Run Code Online (Sandbox Code Playgroud)

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

  • 我无法从 PHP 5.5 连接到不再接受 TLS1.1 的服务器。不幸的是,使用 crypto_method 不是一个选项,因为常量 STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT 是 PHP 5.6 的新内容。您关于删除“ssl_method”的编辑解决了这个问题。 (2认同)
  • @大卫,很高兴听到它!我花了很长时间才弄清楚到底发生了什么。你是对的那个常数。我遇到了同样的问题,也无法使用它,所以我不得不开始寻找替代方案。然后我登陆了流上下文。这有点奏效,然后我意识到我需要删除 ssl 方法的旧常量,因为它迫使它回到 TLS 1.1 并解决问题。 (2认同)