强制 cURL 在代理上使用 GET 来处理 HTTPs 请求

Posted

技术标签:

【中文标题】强制 cURL 在代理上使用 GET 来处理 HTTPs 请求【英文标题】:Force cURL to use GET on proxy for HTTPs requests 【发布时间】:2016-07-06 16:30:23 【问题描述】:

我正在尝试在我的本地计算机上使用转发代理服务器(Apache Traffic Server 或 Squid),作为我的 cURL 调用的本地 HTTP 缓存。

我已经使用以下方式设置了代理:

curl_setopt($ch, CURLOPT_PROXY, 'http://localhost:8080');

当我查询一个HTTP网站时,cURL执行一个标准的HTTPGET代理请求,可以正常缓存:

GET http://example.com/ HTTP/1.1

但是,在查询 HTTPS 网站时,cURL 会改为执行 CONNECT,有效地将代理用作 TCP 隧道,并阻止它缓存响应:

CONNECT example.com:80 HTTP/1.1

有没有办法强制 cURL 执行 GET 请求,即使对于 HTTPS 网站也是如此?

我可以理解使用 TCP 隧道通过 HTTP 代理通过 HTTP 请求进行 HTTP 请求以实现安全性的基本原理,但由于我的代理服务器位于 localhost 上,因此我不在乎使用不安全的 HTTP 连接到代理,并希望使用 cURL执行GET 请求:

GET https://example.com/ HTTP/1.1

我尝试使用:

curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, false);

但这并没有改变任何东西。

【问题讨论】:

没有好办法 AFAIK;您需要一个伪造的 SSL 证书和一个智能拦截(SOCKS?)代理 - 用它自己的替换目标网站的 ssl - 一个例子是 telerik.com/fiddler 上的 Fiddler 代理 您可以尝试通过命令行使用 curl 吗?如果您使用的是 SOCKS 代理:curl --socks5 127.0.0.1:8889 https://www.example.com/ -v 如果您使用的是 HTTP 代理:curl -x http://PROXY_HOST:PROXY_PORT https://www.example.com/ -v 您是否检查了curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 选项? ;) @MooYeolPrescottLee 将CURLOPT_SSL_VERIFYPEER 设置为false 只是阻止cURL 验证SSL 证书的有效性,这是无关的。 【参考方案1】:

我不相信这可以在客户端使用一些常见的配置设置来完成,因为它会否定 HTTPS 的全部目的(没有人可以窃听您的 HTTPS 流量)。

因此,您唯一的选择是将代理配置为基本上创建一个man-in-the-middle attack 来解密通过它的 HTTPS 流量。 Squid 代理应该使用他们的 "SSL bump" feature 来支持这一点。在this wiki 和更多setup docs here 上有一个很好的介绍。

squid 在这个机制中所做的是,它从客户端的 CONNECT 请求中获取远程服务器的地址,而不是仅仅创建一条通往服务器的盲道,它开始一个新的直接 HTTPS 请求 自行发送到服务器并保存回复。因此 Squid 可以访问所有流量并可以对其进行缓存或执行 Squid 可以对其执行的任何其他操作。

当向客户端发送回复时,它本身需要提供一个 HTTPS 证书(客户端期望 HTTPS 流量),因此在 Squid 中,对于所有代理域都有一个 automatically generate certificates 的功能。要配置它,您基本上必须创建一个本地证书颁发机构。请注意,这些自动生成的证书将是简单的自签名证书,因此在客户端,这将显示为不受信任的证书,您需要关闭对等验证 (CURLOPT_SSL_VERIFYPEER = false)。

我在 Apache 流量服务器中找不到任何类似的功能。他们似乎只支持反向代理模式下的SSL termination。

最后一点:请记住,这仍然是一种黑客攻击,解密 HTTPS 可能会带来法律或道德问题。未经客户同意,切勿这样做!

【讨论】:

感谢您的回答。解密 HTTPS 没有问题,因为除了复杂性和性能问题之外,这一切都是在同一台机器上作为本地流量发生的。我很惊讶 cURL 不允许覆盖这种行为(对于 localhost 上的代理),因为在技术方面,绝对没有什么能阻止我想要实现的目标。 ***.com/questions/14656/… 谢谢,抱歉 :)。据我所知,这确实是一种特殊的操作模式,必须在代理端支持,不能只是在客户端“打开”。【参考方案2】:

我认为这里的其他答案不了解您想要做什么。但有可能。

你想发出一个 https 请求并像这样完成它:

client <--http--> cache <--https--> remote server

因此,您通过本地网络上的 http 不安全地将 https 请求发送到本地缓存,然后让缓存在开放的互联网上以 https 的形式安全地获取它。

要做到这一点,您只需破解第一跳。您的客户端程序向缓存发出普通的 http 请求,但添加了一个标头,表示在下一跃点转换为 https,例如:

x-use-protocol: https

发明任何你喜欢的标题。为此,客户端和缓存都必须了解此标头才能进行转换。这不适合一般的网页浏览 - 或者您无法控制客户端的任何时候。但如果您同时编写客户端和缓存,这是一个很好的答案。

【讨论】:

你正确地理解了我的问题。不过,我不是在写缓存。我正在使用库存软件,目前是 Apache Traffic Server。真正的问题是 cURL 不允许在 https URL 上强制使用 GET 请求而不是 CONNECT 请求。

以上是关于强制 cURL 在代理上使用 GET 来处理 HTTPs 请求的主要内容,如果未能解决你的问题,请参考以下文章

使用代理的 http GET - Curl 命令有效,但 python“请求”库不

Linux curl 命令模拟 POST/GET 请求

Linux curl 命令模拟 POST/GET 请求

如何定义一个Swift协议来强制其采用者自己符合相关类型?

将PHP配置为使用代理服务器来实现curl的功能

基于GET的HTTP登录中的curl语法