cURL 不遵守 TLS v1

cURL not respecting TLS v1

我在连接到仅支持 TLS 的后端时遇到问题。配置如下:

在 OS X 中使用 cURL 7.43.0 时,连接工作正常,因为客户端尊重服务器的最高 TLS 版本:

curl -vvv -X GET -o /dev/null https://domain
* Rebuilt URL to: https://domain
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0*   Trying ip...
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to domain (ip) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: *.domain
* Server certificate: DigiCert SHA2 Secure Server CA
* Server certificate: DigiCert Global Root CA
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0> GET / HTTP/1.1
> Host: domain
> User-Agent: curl/7.43.0
> Accept: */*
> 
< HTTP/1.1 200 OK

但 Android 运气不好。由于不接受 SSLv3 连接,因此传递 --tlsv1 选项。仍然,客户端选择使用 SSLv3,因此无法结束握手:

curl -vvv --tlsv1 -X GET https://domain                                                                                                                                                             
* About to connect() to domain port 443 (#0)
*   Trying ip... connected
* Connected to domain (ip) port 443 (#0)
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs/
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
* Closing connection #0

未指定 TLS 1.0 的相同结果:curl -vvv -X GET https://domain

有什么方法可以告诉客户端使用 TLS 而不是 SSLv3?

编辑:检查已接受的答案,因为这是真正检查 cURL 在您的设备中执行的操作的好方法。问题本身是因为证书没有附加完整的链(中间+根证书)。这里有几个在线 SSL 健康检查器,可以帮助您进一步调试问题:

https://www.ssllabs.com/ssltest/

https://www.digicert.com/help/

  • SSLv3, TLS handshake, Client hello (1):

虽然这看起来像是使用了 SSLv3,但也许并没有使用。 OpenSSL 在 SSLv3 函数中实现了大部分 TLS1.x 协议,因为 TLS1.x 只是更好的 SSLv3,并且协议差别不大。

为了测试这个,我设置了一个简单的服务器,它回显 curl 端给出的密码和协议版本:

$ curl -vvv --tlsv1 -o /dev/null --insecure  https://127.0.0.1:12345
...
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Server key exchange (12):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using ECDHE-RSA-AES128-GCM-SHA256

但是在服务器端:

cipher=ECDHE-RSA-AES128-GCM-SHA256 version=TLSv1_2
GET / HTTP/1.1
User-Agent: curl/7.35.0
Host: 127.0.0.1:12345
Accept: */*

因此,即使调试输出显示 SSLv3,它实际上是 TLS1.2。