Curl没有发送客户端证书

时间:2020-08-07 14:24:17

标签: ssl curl networking client-certificates

我正在尝试发送一个简单的curl请求:

curl -k -i --key ./key.pem --cert ./cert.pem https://target_ip/whatever/

我遇到的问题是它不发送任何证书。验证显然已通过,否则我会收到诸如密钥不匹配之类的错误,但是随后我在wireshark中看到未在客户端Hello周围的TCP连接中发送证书。像--verbose--cacert之类的开关也不起作用。

我能够通过邮递员成功发送相同的证书。

我尝试从各种来源(例如WSL2 ubuntu,云中的debian容器,VM,...)发送相同的curl请求。

有没有提示为什么不发送证书?

编辑我-curl -v的输出

*   Trying 52.xxx.xxx.xx:443...
* TCP_NODELAY set
* Connected to 52.xxx.xxx.xx (52.xxx.xxx.xx) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
*  subject: CN=NGINXIngressController
*  start date: Aug 10 18:08:13 2020 GMT
*  expire date: Aug 10 18:08:13 2021 GMT
*  issuer: CN=NGINXIngressController
*  SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /whatever/ HTTP/1.1
> Host: custom.localhost.dev
> User-Agent: curl/7.68.0
> Accept: */*
> Authorization: Bearer  eyJ0...
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
< Server: nginx/1.19.0
Server: nginx/1.19.0
< Date: Mon, 10 Aug 2020 22:23:24 GMT
Date: Mon, 10 Aug 2020 22:23:24 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 153
Content-Length: 153
< Connection: keep-alive
Connection: keep-alive

<
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx/1.19.0</center>
</body>
</html>
* Connection #0 to host 52.xxx.xxx.xx left intact

EDIT II-Wireshk捕获

匿名化pcap似乎太麻烦了,因此这里有一些提示。希望您能够看到所需的一切。我已经突出显示了我做的数据包(没有)看到正在发送的证书。请注意,我在Windows工作站上运行邮递员,而curl在WSL2中,因此源地址不同。其他卷曲的主机的行为确实一样。

卷曲

Curl

邮递员

Postman

EDIT III-客户问候

卷曲

Curl

邮递员

Postman

1 个答案:

答案 0 :(得分:5)

ClientHello显示出明显的区别:邮递员使用server_name扩展名(SNI)提供期望的主机名,而curl不提供。

这可能会触发Web服务器中配置的不同部分:邮递员触发对指定为server_name的特定虚拟主机的访问,而curl可能会运行到默认配置中。假设只有特定的虚拟主机启用客户端证书,这解释了为什么CertificateRequest是仅由服务器发送给邮递员而不发送给邮递员的。

尚不清楚此主机名是什么,但是根据长度,它不能是IP地址。因此,即使声称邮递员仅使用https://target_ip/(即没有给定的主机名)进行访问,邮递员也必须以某种方式知道服务器的预期主机名。 curl无法从该URL派生预期的主机名,因此无法设置server_name。要使curl知道要设置server_name的主机名,同时仍然能够访问特定IP,请使用--resolve选项:

curl --resolve hostname:443:target_ip https://hostname/