从 CLI 和 PHP 代码修复 Curl TLS SSL 协议问题
在我们的一台服务器上,网络服务器未设置为支持 SSLv2 或 SSLv3。两者都在服务器端被禁用。它仅支持 TLSv1。我怎样才能让 curl 从命令行和我的 PHP 代码中工作?
在大多数情况下,curl 会自动选择正确的协议并连接到它。但是,您也可以指定用于 curl 命令的特定协议。在此示例中,您必须指示 CURL 使用 TLSv1,如本教程中所述。
在 Curl 命令行上指定协议
以下是 curl 在命令行上支持的各种协议选项:
- -0(或)-http1.0 用于 HTTP 1.0 (H)
- -1(或)–tlsv1 用于 TLSv1 (SSL)
- -2 (或) –sslv2 用于 SSLv2 (SSL)
- -3 (或) –sslv3 用于 SSLv3 (SSL)
在此示例中,此特定服务器在常规 HTTP 上运行。这里没有问题。
$ curl http://192.168.101.1
<html><body><h1>It works!</h1></body></html>
请参考:15 个实用的 Linux cURL 命令示例
但是,如果您使用 SSLv3,使用 -3 选项,它会返回“sslv3 alert handshake failure”错误消息。
$ curl -3 https://192.168.101.1
curl: (35) error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
如果您使用 SSLv2,使用 -2 选项,它会返回“未知 SSL 协议”错误消息。
$ curl -2 https://192.168.101.1
curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
在这种情况下,在这个特定的服务器上,它只支持 TLS。因此,请使用 -1 选项,如下所示。
$ curl -1 https://192.168.101.1
curl: (60) SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
在这种情况下,由于我们使用的是 IP 地址,它与安装在网络服务器上的 SSL 证书不匹配。因此,我们收到上述“SSL3_GET_SERVER_CERTIFICATE:certificate verify failed”错误消息。
Curl 默认执行 SSL 证书验证。如果您使用的是 CA 授权捆绑包,则默认捆绑包名称是 curl-ca-bundle.crt。您可以使用 –cacert 选项指定不同的捆绑包。
但是,在我们的例子中,我们想使用 TLSv1 协议,但没有 SSL 证书验证。为此,请使用 -k 选项(或 –insecure 选项),它不会执行 SSL 证书验证。
以下是 -k 选项的用法。
$ curl -k https://192.168.101.1
curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
如果您想了解有关 CURL 命令引发的错误的更多详细信息,请使用 -v 选项。正如你在下面看到的。即使我们没有传递协议选项,从命令输出中,我们也可以看到它正在尝试为此使用 SSLv2。
$ curl -k -v https://192.168.101.1
* About to connect() to 192.168.101.1 port 443
* Trying 192.168.101.1... connected
* Connected to 192.168.101.1 (192.168.101.1) port 443
* successfully set certificate verify locations:
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSLv2, Client hello (1):
Unknown SSL protocol error in connection to 192.168.101.1:443
* Closing connection #0
curl: (35) Unknown SSL protocol error in connection to 192.168.101.1:443
命令行解决方案
请参阅:wget vs curl:如何使用 wget 和 curl 下载文件
因此,在我们的例子中,由于 SSLv2 和 SSLv3 在服务器端被禁用,并且由于某种原因,如果 curl 没有自动设置正确的协议,当我们只想从命令行使用带有 curl 的 TLSv1 协议时,以下工作有效如下图所示。
$ curl -k -1 https://192.168.101.1
<html><body><h1>It works!</h1></body></html>
如果您想查看其具体功能的详细信息,请传递 -v 选项,如下所示。
$ curl -k -1 -v https://192.168.101.1
以上也可以使用以下替代选项来完成
$ curl --insecure --tlsv1 --verbose https://192.168.101.1
同样,在上面的命令中:
- -1(或)–tlsv1 用于 TLSv1 (SSL)
- -k (or) –insecure 允许连接到没有证书的 SSL 站点 (H)
- -v (or) –verbose 使操作更健谈(小写 v)
来自 PHP 的解决方案
从您的 PHP 代码中,如果您使用 cURL 函数,并且喜欢设置协议选项,您应该使用 curl_setopt 或 curl_setopt_array 函数。
如果您只想设置一个选项,请使用 curl_setopt。
curl_setopt($c, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
在上面:
- $c 是您从 curl_init() 函数获得的 curl 变量,当您从 PHP 程序创建新的 cURL 资源时。
- CURLOPT_SSLVERSION 是一个 curl 选项名称。
- CURL_SSLVERSION_TLSv1 是参数#2 中相应选项的 curl 值
您也可以使用数字代替“CURL_SSLVERSION_TLSv1”。在本例中,这等价于 1。
curl_setopt($c, CURLOPT_SSLVERSION, 1);
以下是您可以设置的可能的 CURLOPT_SSLVERSION 值。您可以使用描述性常量或下面显示的相应数字。
- CURL_SSLVERSION_DEFAULT (0)
- CURL_SSLVERSION_TLSv1 (1)
- CURL_SSLVERSION_SSLv2 (2)
- CURL_SSLVERSION_SSLv3 (3)
- CURL_SSLVERSION_TLSv1_0 (4)
- CURL_SSLVERSION_TLSv1_1 (5)
- CURL_SSLVERSION_TLSv1_2 (6)
如果要设置多个 CURL 选项,请使用 curl_setopt_array ,如下所示。在这里,除了设置 CURLOPT_SSLVERSION 之外,它还设置了一些其他的 curl 选项。
在这种情况下,第二个参数将是一个包含多个 CURL 选项的数组,如下所示。
curl_setopt_array($c, array
(
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_SSLVERSION => 1
));
- 点赞
- 收藏
- 关注作者
评论(0)