gpt4 book ai didi

python - SSL 客户端证书不是由 python 'requests' 库或 s_client 发送的,但在网络浏览器中工作正常

转载 作者:太空宇宙 更新时间:2023-11-04 03:42:35 25 4
gpt4 key购买 nike

我正在尝试用 Python 编写客户端脚本来访问 Web 应用程序并使用 SSL 客户端证书进行身份验证。尽管只要加载了客户端证书,我就可以从 Firefox 和 Chrome 访问该应用程序,但每当我通过 Python 的“请求”发送请求时,我都会收到以下响应:

400 No required SSL certificate was sent
nginx/1.4.6 (Ubuntu)

我也试过 Python httplib、s_client 和 curl,得到了同样的错误信息。我对所有测试使用相同的客户端证书,以 pkcs12 格式用于 Web 浏览器,并提取到命令行工具的证书和 key PEM 文件中。我的 python 代码如下所示:

import requests

CERT = r'/path/to/cert.crt' #Client certificate
KEY = r'/path/to/key.key' #Client private key
CACERT = r'/path/to/ca.crt' #Server certificate chain

session = requests.Session()
session.cert = (CERT, KEY)
resp = session.get('https://my.webapp.com/',
verify=CACERT)

print resp.content
session.close()

s_client 提供了有关正在发生的事情的更多信息。这是输出的缩写版本:

$ openssl s_client -cert cert.crt -key key.key -CAfile ca.crt -connect <host>:<port>
CONNECTED(00000003)
depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
verify return:1
depth=1 /C=US/O=GeoTrust, Inc./CN=RapidSSL CA
verify return:1
depth=0 /serialNumber=tgBIwyM-p18O/aDyvyWNKHDnOezzDJag/OU=GT89519184/OU=See www.rapidssl.com/resources/cps (c)13/OU=Domain Control Validated - RapidSSL(R)/CN=*.rexdb.us
verify return:1
---
Certificate chain
...
---
Server certificate
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
subject=...
---
No client certificate CA names sent
---
SSL handshake has read 3519 bytes and written 328 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES128-SHA
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES128-SHA
Session-ID: ...
Session-ID-ctx:
Master-Key: ...
Key-Arg : None
Start Time: 1409269239
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
GET / HTTP/1.1
Host: my.webapp.com

HTTP/1.1 400 Bad Request
Server: nginx/1.4.6 (Ubuntu)
Date: Thu, 28 Aug 2014 23:41:04 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: close
...
<head><title>400 No required SSL certificate was sent</title></head>
...
closed

我有理由相信这不是服务器的问题,因为身份验证在浏览器中工作。但是,s_client 输出显示“未发送客户端证书 CA 名称”,这听起来像是服务器问题(例如,客户端证书未发送到服务器,因为服务器未请求它)。这是 nginx 配置的相关部分:

ssl                  on;
ssl_certificate_key /path/to/server/key.pem;
ssl_certificate /path/to/server/certificate.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-ECDSA-RC4-SHA:AES128:AES256:RC4-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!PSK;
ssl_prefer_server_ciphers on;
ssl_session_timeout 5m;

ssl_client_certificate /path/to/client/ca/certificate.crt;
ssl_verify_depth 10;
ssl_verify_client on;

应用程序通过 nginx 使用 uwsgi。 vm上有多台虚拟主机,只有这台使用证书认证。

我能找到的唯一其他可能相关的区别是,在 Firefox 中,连接是保持事件的,而在 s_client 中,它是关闭的。我试过在 header 中设置 Connection: keep-alive,结果相同。

最佳答案

There are multiple virtual hosts on the vm, and only this one uses certificate authentication.

我假设这意味着您在同一个 IP 地址后面有多个证书,并且客户端必须使用 SNI(服务器名称指示)向服务器发送 SSL 握手中预期的主机名。 openssl s_client 默认不使用 SNI,我不知道 python 是否使用 - 这可能取决于您使用的 python 版本。

因为客户端只在服务器告诉它这样做时才发送证书,所以可能是因为缺少 SNI,您会遇到错误的配置部分,这是带有另一个证书的默认部分,不需要客户端证书。

我建议再次尝试使用 openssl s_client,但使用命令行选项 -servername(未在手册页中记录,但如果使用 调用则会显示 - h) 显式设置预期的服务器名称。如果这可行,您也需要找到一种在 python 中使用 SNI 的方法。如果这不起作用,请转储数据包并使用 wireshark 确保服务器确实需要客户端发送证书,而客户端确实不发送证书。

关于python - SSL 客户端证书不是由 python 'requests' 库或 s_client 发送的,但在网络浏览器中工作正常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25560041/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com