测试协议代理神器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版本,帮助快速拆分服务构建代理。