mitmproxy介绍
mitmproxy is a free and open source interactive HTTPS proxy.
mitmproxy 主要包含3个核心工具:
- mitmproxy:一个交互式的、具有HTTP/1、HTTP/2和WebSocket的控制台接口的、支持SSL/TLS的拦截代理。
- mitmweb:mitmproxy的web的界面
- mitmdump:mitmproxy的命令行版本
安装
注意:python 3.8 以上
pip install mitmproxy==7.0.4
配置
启动代理
# mitmweb Web server listening at http://127.0.0.1:8081/ Proxy server listening at http://*:8080
客户端设置网络代理
客户端设置网络代理,代理端口设置为8080端口(如上)
客户端安装mitmproxy证书
客户端设置好代理后,访问http://mitm.it 即可显示证书,根据系统选择对应证书进行安装即可。
mitmproxy Addons 插件机制
anatomy.py:
"""
Basic skeleton of a mitmproxy addon.
Run as follows: mitmproxy -s anatomy.py
"""
from mitmproxy import ctx
class Counter:
def __init__(self):
self.num = 0
def request(self, flow):
self.num = self.num + 1
ctx.log.info("We've seen %d flows" % self.num)
addons = [
Counter()
]
mitmdump -s 指定py脚本
mitmdump -s ./anatomy.py
上面是一个简单的插件,它跟踪我们看到的流(或者更具体地说HTTP请求)的数量
(venv) E:\workspace\>mitmdump -s anatomy.py
Loading script anatomy.py
Proxy server listening at http://*:8080
192.168.198.169:38882: client connect
We've seen 1 flows
192.168.198.169:38882: server connect aps.amap.com:80 (106.11.23.53:80)
192.168.198.169:38882: POST http://aps.amap.com/APS/r?ver=5.1&q=0&csid=e1e8d28c-c81c-45d3-bcce-b6eeadf283ee
<< 200 363b
192.168.198.169:38882: server disconnect aps.amap.com:80 (106.11.23.53:80)
192.168.198.169:38882: client disconnect
We've seen 2 flows
...
钩子函数
插件通过事件挂钩连接到mitmproxy的内部机制。
许多事件接收流对象作为参数-通过修改这些对象,插件可以动态更改流量。
下面举例常见的钩子如request,response,修改请求信息,修改响应信息
"""
Basic skeleton of a mitmproxy addon.
Run as follows: mitmproxy -s anatomy.py
"""
from mitmproxy import ctx
from mitmproxy import http
import json
class Counter:
def __init__(self):
self.num = 0
def request(self, flow):
self.num = self.num + 1
ctx.log.info("We've seen %d flows" % self.num)
class MyTest:
def request(self,flow:http.HTTPFlow) -> None:
""" request 钩子:处理request拦截,参数修改,制造mocke响应,重定向等"""
if "postman-echo" in flow.request.host:
# 修改get querystring参数
if flow.request.method.lower()=="get" and "get" in flow.request.pretty_url:
flow.request.query["name"] = "Milton_Proxy"
# 修改post 表单参数
if flow.request.method.lower()=="post":
if flow.request.urlencoded_form:
# If there's already a form, one can just add items to the dict:
ctx.log.info(flow.request.urlencoded_form)
flow.request.urlencoded_form["name"] = "Milton_Proxy"
# 制造mock响应
if flow.request.method.lower()=="patch":
content = {"msg":"map_local"}
flow.response = http.Response.make(
status_code=200,
content=json.dumps(content),
headers={"Content-Type":"application/json"}
)
def response(self,flow:http.HTTPFlow) -> None:
""" response 钩子:修改响应信息"""
if "postman-echo" in flow.request.host and "delete" in flow.request.pretty_url:
data = json.loads(flow.response.content)
data["data"]={"msg":"reponse_modify"}
flow.response.text = json.dumps(data)
addons = [
Counter(),MyTest()
]
# 测试命令:
# curl --proxy http://127.0.0.1:8080 http://postman-echo.com/get?name=tom
# curl --proxy http://127.0.0.1:8080 -X POST http://postman-echo.com/post -d "name=Jack" -H "Content-Type: application/x-www-form-urlencoded"
# curl --proxy http://127.0.0.1:8080 -X PATCH http://postman-echo.com/patch
# curl --proxy http://127.0.0.1:8080 -X DELETE http://postman-echo.com/delete
测试情况:
- 篡改get请求中的querystring
# curl --proxy http://127.0.0.1:8080 http://postman-echo.com/get?name=tom {"args":{"name":"Milton_Proxy"},"headers":{"x-forwarded-proto":"http","x-forwarded-port":"80","host":"postman-echo.com","x-amzn-trace-id":"Root=1-61cd80b7-64f6c8f668e2a29b59201848","user-agent":"curl/7.80.0","accept":"*/*","proxy-connection":"Keep-Alive"},"url":"http://postman-echo.com/get?name=Milton_Proxy"}
- 篡改post请求中的form表单参数
# curl --proxy http://127.0.0.1:8080 -X POST http://postman-echo.com/post -d "name=Jack" -H "Content-Type: application/x-www-form-urlencoded" {"args":{},"data":"","files":{},"form":{"name":"Milton_Proxy"},"headers":{"x-forwarded-proto":"http","x-forwarded-port":"80","host":"postman-echo.com","x-amzn-trace-id":"Root=1-61cd8129-60130e9b255eb7b77856bd84","content-length":"17","user-agent":"curl/7.80.0","accept":"*/*","proxy-connection":"Keep-Alive","content-type":"application/x-www-form-urlencoded"},"json":{"name":"Milton_Proxy"},"url":"http://postman-echo.com/post"}
- request钩子中,直接mock响应
# curl --proxy http://127.0.0.1:8080 -X PATCH http://postman-echo.com/patch {"msg": "map_local"}
- reponse钩子中,篡改服务端响应数据
# curl --proxy http://127.0.0.1:8080 -X DELETE http://postman-echo.com/delete {"args": {}, "data": {"msg": "reponse_modify"}, "files": {}, "form": {}, "headers": {"x-forwarded-proto": "http", "x-forwarded-port": "80", "host": "postman-echo.com", "x-amzn-trace-id": "Root=1-61cd8201-67d81c874137d0f173ccb8b3", "user-agent": "curl/7.80.0", "accept": "*/*", "proxy-connection": "Keep-Alive", "content-type": "application/json"}, "json": null, "url": "http://postman-echo.com/delete"}
tips:
更多钩子函数与示例,可参考以下:
- https://docs.mitmproxy.org/stable/api/events.html
- https://github.com/mitmproxy/mitmproxy/tree/main/examples/
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。