ssl - Curl 未发送客户端证书

标签 ssl curl networking client-certificates

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

curl -k -i --key ./key.pem --cert ./cert.pem https://target_ip/whatever/
我遇到的问题是它没有发送任何证书。验证显然通过了,否则我会遇到诸如 key 不匹配之类的错误,但随后我可以在 Wireshark 中看到证书没有在客户端 Hello 周围的 TCP 连接中发送。像 --verbose 这样的开关或 --cacert也不要做太多。
我能够通过 postman 成功发送相同的证书。
我尝试从各种来源发送相同的 curl 请求,例如我的 WSL2 ubuntu、云中的 debian 容器、VM ......
为什么它不发送证书的任何提示?
编辑 I - 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 - wireshark 捕获
匿名 pcap 似乎太麻烦了,所以这里只是一些快照。希望你能看到你需要的一切。我已经突出显示了我确实(没有)看到正在发送的证书的数据包。请注意,我在 Windows 工作站上运行 postman ,而 curl 在 WSL2 中,因此源地址不同。 curl 的其他主机确实表现相同。
卷发
Curl
postman
Postman
编辑 III - 客户您好
卷发
Curl
postman
Postman

最佳答案

ClientHello 显示出明显的区别: postman 使用 server_name扩展 (SNI) 以提供预期的主机名,而 curl 不提供。
这可能会触发 Web 服务器中配置的不同部分: postman 触发对指定为 server_name 的特定虚拟主机的访问。而 curl 可能会进入默认配置。假设只有特定的虚拟主机启用客户端证书,这就解释了为什么 CertificateRequest 仅由服务器发送给 postman 而不是 curl。
目前还不清楚这个主机名是什么,但根据长度,它不能是 IP 地址。因此 postman 必须知道服务器的预期主机名,即使声称访问是通过https://target_ip/ 完成的。仅,即没有给定的主机名。 curl 无法从此 URL 派生预期的主机名,因此无法设置 server_name .为了让 curl 知道要设置的主机名 server_name在仍然能够访问特定 IP 的同时使用 --resolve选项:

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

关于ssl - Curl 未发送客户端证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63303768/

相关文章:

android - 所有设备的 Android Trusted Credentials 中的凭据是否?

web-services - Camel cxf webservice - 获取响应的问题

ruby-on-rails - cURL无法连接到本地主机,但浏览器可以

php - 使用 CURL 下载时使用默认文件名 (content_disposition)

node.js - 我想要一个跨网络工作的事件发射器

ssl - 带有 jetty 9 和 ssl 的 spring boot

ssl - 如何在 monit 中检查具有有效 HTTPS 证书的 URL?

ssl - 在 curl -k 中请求工作,但不在 Postman 中禁用 SSL

c++ - Boost ASIO async_write_some 真的很慢

networking - Golang DNS 解析不起作用