为通过 HTTPS 隧道的请求设置 CA 包

Sav*_*ior 5 python ssl https http-tunneling python-requests

我正在尝试通过 HTTPS 隧道发送 HTTPS 请求。也就是说,我的代理希望 CONNECT 使用 HTTPS。它还需要一个客户端证书。

我正在使用请求的代理功能

import requests

url = "https://some.external.com/endpoint"
with requests.Session() as session:
    response = session.get(
        url,
        proxies={"https": "https://proxy.host:4443"},
        # client certificates expected by proxy
        cert=(cert_path, key_path),
        verify="/home/savior/proxy-ca-bundle.pem",
    )
    with response:
        ...
Run Code Online (Sandbox Code Playgroud)

这有效,但有一些限制:

  1. 我只能为与代理的 TLS 连接设置客户端证书,而不能为外部端点设置。
  2. proxy-ca-bundle.pem只验证与代理的TLS连接的服务器证书。来自外部端点的服务器证书似乎被忽略了。

有什么办法可以requests用来解决这两个问题吗?我想为外部端点设置一组不同的 CA。

我也尝试使用http.clientHTTPSConnection.set_tunnel但是,据我所知,它的隧道是通过 HTTP 完成的,我需要 HTTPS。

Sav*_*ior 4

查看源代码,目前似乎不requests支持这种“TLS in TLS”,即。为代理请求提供两组客户端/CA 捆绑包。

我们可以使用PycURL它简单地包装了 libcurl

from io import BytesIO

import pycurl    

url = "https://some.external.com/endpoint"
buffer = BytesIO()

curl = pycurl.Curl()
curl.setopt(curl.URL, url)
curl.setopt(curl.WRITEDATA, buffer)
# proxy settings
curl.setopt(curl.HTTPPROXYTUNNEL, 1)
curl.setopt(curl.PROXY, "https://proxy.host")
curl.setopt(curl.PROXYPORT, 4443)
curl.setopt(curl.PROXY_SSLCERT, cert_path)
curl.setopt(curl.PROXY_SSLKEY, key_path)
curl.setopt(curl.PROXY_CAINFO, "/home/savior/proxy-ca-bundle.pem")
# endpoint verification
curl.setopt(curl.CAINFO, "/home/savior/external-ca-bundle.pem")

try:
    curl.perform()
except pycurl.error:
    pass # log or re-raise
else:
    status_code = curl.getinfo(curl.RESPONSE_CODE)
Run Code Online (Sandbox Code Playgroud)

PycURL 将使用这些PROXY_设置建立到代理的 TLS 连接,并向其发送 HTTP CONNECT 请求。然后,它将通过与外部端点的代理连接建立一个新的 TLS 会话,并使用该CAINFO捆绑包来验证这些服务器证书。