【问题标题】:HTTPS proxy with support for chunked-encoded requests支持分块编码请求的 HTTPS 代理
【发布时间】:2014-04-29 13:58:35
【问题描述】:

我正在开发一个简单的 HTTPS 代理(用 Python 编写),它接收 POST/GET 请求/响应,应用一些转换,最后将结果转发给接收者。 我需要以“流”方式处理分块编码的请求/响应,这意味着一旦收到一个块,代理就会对其进行转换并将其转发给接收者。

在决定支持分块编码请求之前,我一直在使用 mitmproxy http://mitmproxy.org/,它运行良好。不幸的是,我注意到它会等到收到整个正文后才让我处理响应/请求。

如何实现支持分块编码请求/响应的代理?你们有没有人做过这样的事情?

谢谢

编辑:关于我的用例的更多信息

我需要处理 POST 请求和 GET 响应。

POST 请求中,我收到一个 JSON 对象,我必须加密它的一些值。

GET 响应中,我收到一个 JSON 对象,我必须解密它的一些值。

到目前为止,以下代码已经完美运行:

 def handle_request(self, r):
    if(r.method=='POST'):
       // encryption of r.get_form_urlencoded()

 def handle_response(self, r):
    if(r.request.method=='GET'):
       // decryption of r.content

我怎样才能对单个块做同样的事情?

编辑:更新

在评估了不同的解决方案后,我决定选择 Squid(代理)+ICAP(内容适配)。

我已经成功配置了 Squid,并且性能非常好。不幸的是,我找不到合适的 ICAP 服务器(如果可能的话,在 Python 中)进行内容调整(修改)。我认为这个https://github.com/netom/pyicap 可以完成这项工作,但看起来它不会读取 myPOST 请求的正文。

你们知道我可以与 Squid 一起使用的 Python ICAP 服务器吗?

谢谢

【问题讨论】:

    标签: apache proxy squid


    【解决方案1】:

    下面的答案已经过时了。您现在可以将 --stream 传递给 mitmproxy,其行为在 mitmproxy documentation 中进行了说明。

    mitmproxy 开发人员在这里。这绝对是我们想要的 mitmproxy 的一个功能,但它并不是那么微不足道,而且可能不会很快推出。如果你真的想自己实现,我可以推荐两件事:

    1. 如果您有一个非常具体的用例,您可以使用libmproxy.protocol.http.HTTPRequest.from_stream 来解析标头并自己进行正文处理。
    2. 如果您不想修改请求/响应正文,您可能会发现修改 mitmproxy 本身就足够了。简而言之,您需要读取没有内容的请求/响应(参见 1.),根据需要对其进行修改,将其传递给服务器,然后将控制权委托给 libmproxy.protocol.tcp(参见 https://github.com/mitmproxy/mitmproxy/blob/master/libmproxy/proxy/server.py#L169

    如果您还有其他问题,请随时在此处或 mitmproxy 的 IRC 频道上提问。


    回复评论#1:

    你不能从 mitmproxy 中得到太多,但至少你得到了头解析和处理的委托。

    # ...accept request, socket.makefile() etc...
    req = HTTPRequest.from_stream(client_conn.rfile, include_content=False)
    # manually forward to the server (req._assemble_head())
    # manually receive response body chunk by chunk and forward it to the server, see
    # https://github.com/mitmproxy/netlib/blob/master/netlib/http.py#L98
    resp = HTTPResponse.from_stream(server_conn.rfile, include_content=False)
    # manually forward headers
    # manually process body and forward
    

    话虽如此,这是一个相当复杂的话题。最终,您最好将其直接破解到 libmproxy.protocol.http.HTTPHandler 中。

    另一个选项,再次取决于您的用例:使用 mitmproxy,将 conntype 设置为 tcp 并按原样转发流量,并对 libmproxy.protocol.tcp 中的内容使用正则表达式替换。可能是最简单的方法,但也是最笨拙的方法。 如果您能提供一些背景信息,我可能会进一步引导您朝着正确的方向前进。


    关于评论 #2:

    在我们进入主要部分之前:如果您不想加密完整的 JSON 对象并将其视为单个字符串,那么 JSON 对于流/分块来说是一个非常糟糕的选择。如果您只想加密部分,则绝对应该考虑使用 tnetstrings 之类的东西。

    除此之外,挂接到 read_chunk 是可行的,但首先你需要到达可以实际接收线路上的块的地步。然后,就像读取单个块、加密并转发它们一样简单。

    【讨论】:

    • 您好,mhils,感谢您的回复和建议。我对这两个选项都不太了解,但选项 #1 可能对我来说是最好的(我想避免修改 mitmproxy)。如何使用github.com/mitmproxy/mitmproxy/blob/master/libmproxy/protocol/… 处理单个块?你能更准确一点或给我一个例子吗?谢谢
    • 您好 mhils,我刚刚编辑了答案并添加了有关我的用例的更多详细信息。如果我没记错的话,我认为最好在我的脚本中添加类似“handle_chunk(self, r, chunk)”的内容并从github.com/mitmproxy/netlib/blob/master/netlib/http.py#L98 调用此函数。你怎么看?
    • 我不知道您是否收到编辑通知 - 回复在上面。
    • 感谢您的回答。我终于开始看到隧道尽头的曙光了 :) 在您看来,读取单个块并向我的 mitmproxy 脚本发送通知的最佳选择是什么?我应该在哪里以及如何注入代码来添加此功能?谢谢
    猜你喜欢
    • 2012-10-11
    • 2016-02-14
    • 1970-01-01
    • 2018-08-07
    • 2011-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    相关资源
    最近更新 更多