使用 Fiddler 拦截 Boost.Asio HTTP/S 请求

Posted

技术标签:

【中文标题】使用 Fiddler 拦截 Boost.Asio HTTP/S 请求【英文标题】:Intercepting Boost.Asio HTTP/S request using Fiddler 【发布时间】:2012-08-21 03:57:31 【问题描述】:

我正在使用 Boost:Asio 执行 HTTP GET (使用http://www.boost.org/doc/libs/1_50_0/doc/html/boost_asio/example/http/client/async_client.cpp的例子)

我没有在提琴手上看到我的请求(仅在 WireShark 上) 怎么改?

【问题讨论】:

【参考方案1】:

Asio 在套接字级别工作,并且不使用 wininet - 因此 fiddler 无法捕获其流量。

我一直在寻找解决方案,为了让 fiddler 与 asio 一起工作,您需要将其用作代理。要在提琴手中启用代理,请使用工具 -> Telerik Fiddler 选项 -> 连接。

要将代理服务器与 asio 一起使用,您需要使用其 IP 地址 + 端口而不是目标服务器。然后在 GET 中,您需要提供完整的目标 uri - 不仅是路径。如需更好的解释,请参见此处:how to add proxy support to boost::asio?

【讨论】:

【参考方案2】:

我也遇到了类似的问题,所以我只是分享一下我的经验。据我所知,Asio 在套接字级别工作,并且没有像 @marcinj 指出的那样使用 wininet,Fiddler 在 wininet 上工作,但我们仍然可以通过使用 Fiddler 作为代理来做到这一点。

首先,解释一下为什么它在Boost:Asio 上不起作用,就像在 IE 上解析流量一样?

另见how to catch the socket programming's send and receive request in fiddler

Fiddler 将自己作为 HTTP 代理服务器插入堆栈。它依靠网络浏览器识别 PC 上配置了代理并通过该代理进行发送。您的代码未检测到要通过的代理发送 - 因此 Fiddler 将无法监控您的流量。

您有多种选择。

    由于您是自己的 Windows,只需从使用直接套接字切换到使用 WinInet HTTP API。它将为您进行自动代理检测,而无需您考虑。如果需要,它也会进行代理身份验证。

    或。使用 Wireshark 或 NetMon 而不是 Fiddler 来分析您的流量。

我推荐 #1,因为这意味着您的代码将在存在真正的代理服务器(通常在企业网络上找到)的情况下工作,而 Fiddler 将只使用它。

我想还有第三个选项,您可以自动检测浏览器代理设置,然后为代理创建一个套接字,使用 HTTP 代理协议等……但这不是最佳做法。

二、怎么办?

有一个很好的example 关于传递代理地址以创建基于Boost:asio 的客户端,例如Socket(java.net.Proxy) 或Configure a php/cURL Application to Use Fiddler,或者客户端应用程序不是您自己编写的,但如果您可以控制/配置您的客户端连接端点地址和端口,我们可以让 Fiddler 以任何方式拦截 HTTP(s) 流量(将 HTTP 请求重新路由为 HTTPS 请求或将 HTTPS 请求重新路由为 HTTPS 服务器的 HTTPS 请求)作为反向代理(需要一个论点)。

默认情况下,Fiddler 正在监听 8888。如果在浏览器中转到 http://localhost:8888/,它会显示如下默认页面:

<!doctype html>
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Fiddler Echo Service</title></head><body style="font-family: arial,sans-serif;"><h1>Fiddler Echo Service</h1><br /><pre>GET / HTTP/1.1
Host: localhost:8888
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36
DNT: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: _ga=GA9.1.123456789.1234567890

</pre>This page returned a <b>HTTP/200</b> response <br />Originating Process Information: <code>chrome:3628</code><br /><hr /><ul><li>To configure Fiddler as a reverse proxy instead of seeing this page, see <a href='http://fiddler2.com/r/?REVERSEPROXY'>Reverse Proxy Setup</a><li>You can download the <a href="FiddlerRoot.cer">FiddlerRoot certificate</a></ul></body></html>
    如果目标服务器是 HTTP 服务器或目标服务器是 HTTPS 服务器,并且客户端根据您配置的地址支持 HTTP,只需在 OnBeforeRequest 中添加以下代码(在规则 -> 自定义规则.. .Ctrl+R, FiddlerScript),另见Modifying a Request or Response。
//MessageBox.Show(oSession.fullUrl);
// string Session.fullUrl: Retrieves the complete URI, including protocol/scheme, in the form http://www.host.com/filepath?query.
//FiddlerObject.log("Session.fullUrl=" + oSession.fullUrl);
// string Session.url: Gets or sets the URL (without protocol) being requested from the server, in the form www.host.com/filepath?query."
//FiddlerObject.log("Session.url=" + oSession.url);
// string Session.PathAndQuery: Returns the path and query part of the URL. (For a CONNECT request, returns the host:port to be connected.)
//FiddlerObject.log("Session.PathAndQuery=" + oSession.PathAndQuery); // e.g. /filepath?query but host:port for a CONNECT request
// string Session.host: Gets/Sets the host to which this request is targeted. MAY include IPv6 literal brackets. MAY include a trailing port#.
// int Session.port: Returns the server port to which this request is targeted.
//FiddlerObject.log("Session.host=" + oSession.host + ", port=" + oSession.port);
// string Session.hostname: DNS Name of the host server (no port) targeted by this request. Will include IPv6-literal brackets for IPv6-literal addresses
//Gets/Sets the hostname to which this request is targeted; does NOT include any port# but will include IPv6-literal brackets for IPv6 literals.
FiddlerObject.log("Session: hostname=" + oSession.hostname +  ", oRequest.pipeClient.LocalPort=" + oSession.oRequest.pipeClient.LocalPort);


//bool Fiddler.Utilities.isLocalhostname(sHostnameWithoutPort))
// Determines if the specified Hostname is a either 'localhost' or an IPv4 or IPv6 loopback literal
// Returns true if True if the sHostname is 127.0.0.1, 'localhost', or ::1. Note that list is not complete.

// Run Fiddler on your machine, and then add this block of code and test it works on the your same machine:
// Use the `curl http://localhost:8888/get`command  or Using a browser, go to http://localhost:8888/get.
if (Utilities.isLocalhostname(oSession.hostname)) 
    // By default, Fiddler is listening on 8888. Inspect what ports are being listened using proexp or netstat
    // :: Lists the listening ports of a process with the specified image name including extension name(case-insensitive), fiddler.exe
    // for /f "skip=1 tokens=2,9 delims=," %a in ('tasklist /fo csv /fi "IMAGENAME eq fiddler.exe" 2^>NUL') do (netstat -ano | findstr "PID LISTENING" | findstr "PID %a")
    //oSession.host = "httpbin.org:443"; // oSession.oRequest.headers.UriScheme = "https";
    oSession.fullUrl = "https://httpbin.org" + oSession.PathAndQuery;

您可以将使用实际 url 的预期响应与通过 url localhost 连接将请求转发到实际 url 的 Fiddler 代理的上述响应进行比较,即 httpbin.org。

    如果目标服务器是 HTTPS 服务器,但客户端不支持 HTTP,则上述更改还不够。

使用命令curl -v https://localhost:8888/get(或浏览器),发现错误

* schannel: sent initial handshake data: sent 182 bytes
* schannel: SSL/TLS connection with localhost port 8888 (step 2/3)
* schannel: failed to receive handshake, need more data

查看Wireshark的流量,发现客户端发送第一个TLS请求(Client Hello)后,Fiddler没有进行任何HTTPS握手。

Fiddler 输出日志:

18:28:44:5960 HTTPSLint> 警告:ClientHello 记录的长度为 508 字节。某些服务器在 ClientHello 大于 255 字节时存在问题。 https://github.com/ssllabs/research/wiki/Long-Handshake-Intolerance

要解决它,我们需要在规则脚本之外做:

    将 Fiddler 配置为反向代理服务器,它将目标端口等于第二个参数!listen 命令的所有请求转发到目标服务器。单击工具 > Fiddler 选项 > 连接。确保选中“允许远程客户端连接”。它使 fiddler 能够响应 HTTPS 的 SSL/TLS 握手请求。此步骤是持久配置。

    在 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Fiddler2 中创建一个名为 ReverseProxyForPort 的新 DWORD。将 DWORD 设置为 Fiddler 将重新路由入站流量的本地端口(通常是标准 HTTP 服务器的端口 80)。

:: reg query HKEY_CURRENT_USER\SOFTWARE\Microsoft\Fiddler2 /v ReverseProxyForPort
reg add HKEY_CURRENT_USER\SOFTWARE\Microsoft\Fiddler2 /v ReverseProxyForPort /t REG_DWORD /d 58080 /f && REM /f Force overwriting the existing registry entry without prompt to 58080
:: Deletes the registry key
:: REG DELETE HKEY_CURRENT_USER\SOFTWARE\Microsoft\Fiddler2 /v ReverseProxyForPort  /f && REM /f Forces the deletion without prompt.
    重新启动 Fiddler 并启动代理服务器,通过在 Fiddler 左下角的 QuickExec 框中的 !listen *PORT [CERTHOSTNAME]* 脚本命令在指定端口上输入!listen 443 ServerHostName,其中 ServerHostName 是服务器的主机名;例如,对于https://Fuzzle/,您可以使用 fuzzle 作为服务器名称。

似乎没有必要在 Windows 注册表 (REGEDIT.exe) 的 HKEY_CURRENT_USER\SOFTWARE\Microsoft\Fiddler2 内创建一个名为 ReverseProxyForPort 的新 DWORD

QuickExec - Default commands

!listen *PORT [CERTHOSTNAME]*

在另一个端口上设置额外的侦听器,可选择由 HTTPS 证书保护

!listen 8889
!listen 4443 localhost
!listen 444 secure.example.com

另请参阅

Use Fiddler as a Reverse Proxy ***Reverse proxy Difference between proxy server and reverse proxy server?

从用户的角度来看,当向代理反向代理服务器发送请求时:

代理 - 需要两个参数: 1) 获取什么和 2) 使用哪个代理服务器中间 反向代理 - 需要一个参数: 1.) 得到什么 反向代理在用户不知情的情况下从另一台服务器获取内容并返回结果,就像它来自反向代理服务器一样 pspi 于 4 月 13 日 5:47 回答
Running Fiddler as a Reverse Proxy for HTTPS server fiddler redirect https to localhost

static function OnBeforeRequest(oSession:Fiddler.Session) 中使用的以下代码:

if (oSession.HostnameIs("YYYY.azurewebsites.net")) oSession.host = "127.0.0.1:19703";
Running Fiddler as HTTP to HTTPS reverse proxy

Fiddler 将入站请求从 HTTP 转换为 HTTPS 的最简单方法是在 OnBeforeRequest 中添加一些内容,例如:

if (oSession.HostnameIs("myhost") && (oSession.oRequest.pipeClient.LocalPort == 80)) 
  oSession.fullUrl = "https://" + oSession.url;

当然,这假定 Fiddler 被配置为在端口 80 上运行,这是 HTTP 的默认端口。您可以在您喜欢的任何端口上运行它(例如,如果端口 80 已在使用中),但您需要更改客户端请求的 URL 中的端口,如果您可以这样做,您可能能够更改客户端以使用 HTTPS URL 开头。

Setting WinINet Proxy Configurations in WinHTTP MS - How to configure client proxy server settings by using a registry file Configure Fiddler to Decrypt HTTPS Traffic

【讨论】:

以上是关于使用 Fiddler 拦截 Boost.Asio HTTP/S 请求的主要内容,如果未能解决你的问题,请参考以下文章

使用 boost::asio::async_wait_until 和 boost::asio::streambuf

std::boost::asio::post / dispatch 使用哪个 io_context?

将 Boost.Log 与 Boost.Asio 服务一起使用

使用 boost::asio 丢弃数据

传递给 boost::asio::async_read_some 的回调从未在 boost::asio::read_some 返回数据的使用中调用

使用 boost::asio::spawn 生成的 asio 处理程序中的 boost::property_tree::read_xml 段错误