【问题标题】:Intercepting Boost.Asio HTTP/S request using Fiddler使用 Fiddler 拦截 Boost.Asio HTTP/S 请求
【发布时间】: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 上) 怎么改?

【问题讨论】:

    标签: c++ boost-asio fiddler


    【解决方案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 将无法监控您的流量。

      您有多种选择。

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

      2. 或。使用 WiresharkNetMon 而不是 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>
      
      1. 如果目标服务器是 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。

      1. 如果目标服务器是 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

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

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

      2. 在 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.
      
      1. 重新启动 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
      

      另请参阅

      【讨论】:

        猜你喜欢
        • 2021-07-26
        • 2014-09-16
        • 1970-01-01
        • 1970-01-01
        • 2017-02-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-01
        相关资源
        最近更新 更多