5

我正在尝试使用 php curl 连接到站点,但收到错误“没有通用加密算法”。进一步调查,我认为这与NSS有关?我发现从命令行,我可以重现错误(所以问题肯定在 curl 而不是 php 包装器),但是如果我设置 --ciphers ecdhe_ecdsa_aes_128_sha 那么它可以工作:

[ec2-user@ip-10-181-165-22 current]$ curl -I https://sslspdy.com
curl: (35) Cannot communicate securely with peer: no common encryption algorithm(s).

[ec2-user@ip-10-181-165-22 current]$ curl -I --ciphers ecdhe_ecdsa_aes_128_sha https://sslspdy.com
HTTP/1.1 200 OK
Server: nginx centminmod
Content-Type: text/html; charset=utf-8
Connection: close
Vary: Accept-Encoding
Strict-Transport-Security: max-age=31536000; includeSubdomains
Date: Sat, 07 Feb 1970 22:34:32 GMT
X-Page-Speed: ngx_pagespeed
Cache-Control: max-age=0, no-cache

所以我的问题是,

  1. 为什么会这样?我无法在网上找到关于 ssl 密码如何在 curl 中工作的解释;似乎每一页都是假设读者已经是该领域的专家 - 不幸的是,像“你可能正在使用 NSS,所以尝试将 PKCS 切换为 FIPS”这样的句子对我来说是完全无法理解的,并且谷歌搜索只会解释各个组成部分(通常参考 20 年前的标准),而不是它们之间的关系。

  2. 有什么办法可以让 curl 告诉我它正在尝试哪些密码以及服务器将接受哪些密码?我试过在ssllabs上查找服务器,但似乎是说服务器接受所有密码,但显然不接受。

  3. 我需要将哪些选项传递给 curl_setopt 以便我的 php 脚本能够连接到该服务器?

  4. 如果我将密码设置为此,会破坏其他网站吗?我可以做些什么使 curl 能够连接到所有安全站点,还是我必须手动迭代不同的密码来尝试每个密码以找出哪个有效?

4

4 回答 4

4
  1. Why is this happening? I have not been able to find an explanation online as to how the ssl ciphers work in curl

It depends on a few things. The client and server libraries, the client and server configurations, etc. You'd need to provide more details.


  1. Is there any way I can make curl tell me which ciphers

Use the right tool for the job. In this case, its an updated sslscan.


  1. What options do I need to pass to curl_setopt so that my php script is able to connect to this server?

CURLOPT_SSL_CIPHER_LIST.


  1. If I set the cipher to this, will that break other sites?

Maybe. It depends on that particular site's configuration.

Ideally, you pick 12 or 16 cipher suites you approve of, and then you use them instead of one. The 12 or 16 covers most sites you encounter on the internet.

Here's the list I usually use. Its from Which Cipher Suites to enable for SSL Socket?:

  • TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
  • TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
  • TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
  • TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
  • TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
  • TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
  • TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA
  • TLS_DHE_DSS_WITH_AES_128_CBC_SHA
  • TLS_RSA_WITH_AES_256_CBC_SHA256
  • TLS_RSA_WITH_AES_256_CBC_SHA
  • TLS_RSA_WITH_AES_128_CBC_SHA256
  • TLS_RSA_WITH_AES_128_CBC_SHA

I would like to ditch the TLS_RSA_* cipher suites because they are key transport, but I need them for those older IIS servers I encounter.

As you can see from the scan results below, this list intersects with the server's list.


Note that you don't specify, say TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384. Rather, in OpenSSL, you specify the OpenSSL's name ECDHE-ECDSA-AES256-SHA384 for the suite. You can find the OpenSSL names at the documentation for openssl ciphers.

With OpenSSL, you can also use the string "HIGH:!aNULL:!MD5:!RC4:!PSK:!SRP". That will get you about 40 or 50 that are reasonably good choices.

You can run the OpenSSL ciphers command to see what the list is:

$ openssl ciphers -v 'HIGH:!aNULL:!MD5:!RC4:!PSK:!SRP'
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA384
ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
...

You can use an updated version of sslscan to determine what cipher suites are available:

$ sslscan --no-failed sslspdy.com
...
Testing SSL server sslspdy.com on port 443

  Supported Server Cipher(s):
    Accepted  TLSv1  256 bits  ECDHE-ECDSA-AES256-SHA
    Accepted  TLSv1  128 bits  ECDHE-ECDSA-AES128-SHA
    Accepted  TLSv1.1  256 bits  ECDHE-ECDSA-AES256-SHA
    Accepted  TLSv1.1  128 bits  ECDHE-ECDSA-AES128-SHA
    Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-GCM-SHA384
    Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-SHA384
    Accepted  TLSv1.2  256 bits  ECDHE-ECDSA-AES256-SHA
    Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-GCM-SHA256
    Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-SHA256
    Accepted  TLSv1.2  128 bits  ECDHE-ECDSA-AES128-SHA

  Prefered Server Cipher(s):
    TLSv1  128 bits  ECDHE-ECDSA-AES128-SHA
    TLSv1.1  128 bits  ECDHE-ECDSA-AES128-SHA
    TLSv1.2  128 bits  ECDHE-ECDSA-AES128-GCM-SHA256
于 2015-06-05T11:36:23.080 回答
3

我无法在网上找到关于 ssl 密码如何在 curl 中工作的解释;...

这不是特定于 curl 的。使用 SSL/TLS,客户端提供它愿意使用的密码,服务器从这些密码中挑选它也支持的密码。默认情况下,客户端不会提供他们可以提供的所有密码,尤其是那些被认为很弱的密码。

有什么办法可以让 curl 告诉我它正在尝试哪些密码以及服务器将接受哪些密码?

使用wireshark,您可以查看客户端提供了哪些密码。您还可以对照 https://www.ssllabs.com/ssltest/viewMyClient.html检查您的客户端,其中显示了提供的密码。或者创建一个测试服务器openssl s_server -cipher ALL -www并将客户端连接到它,它将显示客户端和服务器共享的密码。

我需要将哪些选项传递给 curl_setopt...

CURLOPT_SSL_CIPHER_LISTECDHE-ECDSA-AES128-SHA可能适用于您的情况。但这个值实际上取决于你的 curl 是如何编译的。Curl 支持不同的 SSL/TLS 后端,例如 OpenSSL、NSS、SecureTransport、SChannel、GnuTLS,具体语法取决于后端。此示例设置对 OpenSSL 后端有效。

如果我将密码设置为此,会破坏其他网站吗?...

如果您将自己全局限制在此集合中,那么可以。对于全局设置,您最好也添加其他设置,即HIGH:ECDHE-ECDSA-AES128-SHA:!aNULL. 再次出现错误,确切的语法取决于 SSL/TLS 后端。

于 2015-06-05T11:30:59.800 回答
2

curl_setopt与_CURLOPT_SSL_CIPHER_LIST

于 2015-06-05T11:20:38.773 回答
1

您只需要在 PHP 中添加 curl 选项

curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'DEFAULT:!DH');

在外壳上

curl -I --ciphers 'DEFAULT:!DH' https://sslspdy.com
于 2020-10-16T11:17:49.903 回答