测试协议代理神器mitmproxy

mitmproxy 是什么

mitmproxy 是一个免费的开源交互式的 HTTPS 代理。mitmproxy 就是用于MITM 的proxy,MITM即中间人攻击(Man-in-the-middle attack),用于中间人攻击的代理首先会向正常的代理一样转发请求,保障服务端与客户端的通信,其次会看看请求或者响应结果信息,记录其截获的数据或篡改数据,引发服务端或客户端特定的行为。

为什么选择mitmproxy

  • 相对于我们常用的 fiddle 代理工具,它是可以跨平台;

  • 相对于跨平台的 charles 代理工具,它是开源免费的;

  • 最重要的一点,也是为什么我们采用     mitmproxy 来进行做     Mock,它支持使用     Python 进行二次开发,这样就可以结合业务进行灵活拓展了。

mitmproxy 构成

  • mitmproxy:是一个控制台工具,允许交互式检查和修改 HTTP 流量

  • mitmweb:mitmproxy 是基于 Web 的用户界面,它允许交互式检查和修改 HTTP 流量

  • mitmdump:mitmproxy 的命令行版本。它提供了类似 tcpdump 的功能,可查看、记录和以编程方式转换 HTTP 流量(我们在接下来的场景中使用的就是这个)

环境安装

sudo apt-get install mitmproxy

pip3 install mitmproxy

核心 API介绍

mitmproxy 插件编写主要是基于事件可以在不同层面上分为 5 类:HTTP、TCP、WebSocket、Network、General。

其中最常用的就是 HTTP 事件,主要如下:(其中我们在我们接下来的使用场景主要会用到 request、response这两个事件函数)

1. 收到了来自客户端的HTTP CONNECT 请求

在 flow 上设置非 2xx 响应将返回该响应并断开连接。

CONNECT 不是常用的HTTP 请求方法,目的是与服务器建立代理连接,仅是 client 与proxy 的之间的交流,所以CONNECT 请求不会触发request、response等其他常规的 HTTP 事件。

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

2. 来自客户端的HTTP 请求的头部被成功读取

此时 flow 中的 request 的body 是空的。

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

3. 来自客户端的HTTP 请求被成功完整读取

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

4. 来自服务端的HTTP 响应的头部被成功读取

此时 flow 中的 response 的body 是空的。

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

5. 来自服务端端的HTTP 响应被成功完整读取

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

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

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

关键字段介绍(flow 对象)

flow.request.host 请求 host

flow.request.method 请求方法

flow.request.scheme 请求协议

flow.request.url 请求 URL 链接

flow.request.query 请求 URL 查询参数

flow.request.path 请求 URL 路径

flow.request.urlencoded_form 请求 POST 参数

flow.response.status_code HTTP 响应状态码

flow.response.headers HTTP 响应头信息

flow.response.get_text HTTP 响应内容

如何编写一个插件

插件的作用主要是用于拦截请求,根据自身业务需求,在不同的事件函数中,添加业务逻辑处理代码。

插件的编写格式相对比较简单,如果不熟悉如何编写,可参考官方样例:

https://github.com/mitmproxy/mitmproxy/blob/master/examples/addons

Mock 测试场景

场景介绍:测试“我关注的人”列表,超过一屏,是否能够正常显示。(为了便于快速测试,所以我们采用 Mock 的方式,构造数据)

拦截篡改 http 请求的工具类,包含的功能主要有:

  • 拦截请求并请求 header 信息

  • 拦截请求及修改 body 信息

  • 拦截请求方法及修改类型,e.g. get/post

  • 拦截请求及修改 query 参数

  • 拦截响应并修改响应状态码

  • 拦截响应并修改响应头信息

  • 拦截响应并修改响应正文信息

  • 拦截响应并构造响应信息,e.g. 状态码、响应头、响应体

classHTTPRecordModifier:

def__init__(self, flow: http.HTTPFlow):

self.flow = flow

//设置请求头信息

defset_request_header(self, headers):

for header_key, header_value in headers.items():

self.flow.request.headers[header_key]= header_value

//设置请求 body 参数

defset_request_body(self, body):

self.flow.request.content =bytes(body,"utf-8")

//设置请求方法

defset_request_method(self, method):

self.flow.request.method = method

//设置请求 query 参数

defset_request_query(self, key, value):

self.flow.request.query[key]= value

//设置响应状态码

defset_response_status_code(self, code):

self.flow.response.status_code = code

//设置响应头信息

defset_response_header(self, headers):

for header_key, header_value in headers.items():

self.flow.response.headers[header_key]= header_value

//设置响应体内容

defset_response_body(self, body):

self.flow.response.content =bytes(body,"utf-8")

//构造响应报文

defcreate_mocked_response(self, code=200, header={}, body=""):

self.flow.response = http.HTTPResponse.make(code,bytes(body,"utf-8"), header)

启动 mitmproxy 插件脚本,如下:

mitmdump -s ./mockbusiness.py

Mitmproxy也有Java版本,帮助快速拆分服务构建代理。

(0)

相关推荐