代码改变世界

代理工具 Mitmproxy(二)

2020-08-12 00:09  虫师  阅读(4263)  评论(0编辑  收藏  举报

这一节教大家编写 Mitmproxy 自定义脚本,这才是 Mitmproxy 真正强大的在方。

Mitmproxy官方给了很多例子:

https://docs.mitmproxy.org/stable/addons-examples/

我们演示一个简单的例子 http-add-header.py, 为每一个 response 中增一个数字,标明是当前是第几个请求。

"""Add an HTTP header to each response."""


class AddHeader:
    def __init__(self):
        self.num = 0

    def response(self, flow):
        self.num = self.num + 1
        flow.response.headers["count"] = str(self.num)

addons = [
    AddHeader()
]

mitmweb

为了直观的看到请求和响应的数据,我们使用 mitmweb 命令运行脚本。

>  mitmweb -s .\http-add-header.py 
Web server listening at http://127.0.0.1:8081/
Loading script .\http-add-header.py
Proxy server listening at http://*:8080
...

这个命令就比较厉害了,它启动默认浏览器,并打开一个web版的抓包工具。

打开postman 或其他任何接口调用工具,随便访问一个接口。例如

http://httpbin.org/get

然后,你会发现mitmproxy已经抓取到请求了,并且为每一个请求的response的响应头增加了一个字段。

有没有很强大。那么我们可以用它来干啥。

  • 修改request/response 参数。
  • 打断点,解析某个请求的结果并修改里面的参数。
  • 过滤请求,只记录某个 host 的请求信息。
  • 将某些接口的数据拦截-解析-保存到数据库。

当然,我上面这些大部分你用 fiddler/charles 工具也能完成,但Mitmproxy 可玩性更高,也更加强大。

HTTP生命周期

我们工作中测试的大部分接口都是HTTP的。所以,我们要了解一个HTTP的生命周期。

def http_connect(self, flow: mitmproxy.http.HTTPFlow):

(Called when) 收到了来自客户端的 HTTP CONNECT 请求。在 flow 上设置非 2xx 响应将返回该响应并断开连接。CONNECT 不是常用的 HTTP 请求方法,目的是与服务器建立代理连接,仅是 client 与 proxy 的之间的交流,所以 CONNECT 请求不会触发 request、response 等其他常规的 HTTP 事件。

def requestheaders(self, flow: mitmproxy.http.HTTPFlow):

(Called when) 来自客户端的 HTTP 请求的头部被成功读取。此时 flow 中的 request 的 body 是空的。

def request(self, flow: mitmproxy.http.HTTPFlow):

(Called when) 来自客户端的 HTTP 请求被成功完整读取。

def responseheaders(self, flow: mitmproxy.http.HTTPFlow):

(Called when) 来自服务端的 HTTP 响应的头部被成功读取。此时 flow 中的 response 的 body 是空的。

def response(self, flow: mitmproxy.http.HTTPFlow):

(Called when) 来自服务端端的 HTTP 响应被成功完整读取。

def error(self, flow: mitmproxy.http.HTTPFlow):

(Called when) 发生了一个 HTTP 错误。比如无效的服务端响应、连接断开等。注意与“有效的 HTTP 错误返回”不是一回事,后者是一个正确的服务端响应,只是 HTTP code 表示错误而已。

Web Page Counters
Computer Desks