深入了解mitmproxy(二)

主题
   修改request或者response内容

介绍
  mitmdump无交互界面的命令,与python脚本对接,来源于mitmproxy支持inline script,这里的script指的是python脚本,inline script提供了http、Websocket、tcp等各个时间点事件(events)的hook函数,如http中的request、response等

主要events一览表
   需要修改各种事件内容时,重写以下对应方法,这里主要用的是request、response方法

import typing

import mitmproxy.addonmanager
import mitmproxy.connections
import mitmproxy.http
import mitmproxy.log
import mitmproxy.tcp
import mitmproxy.websocket
import mitmproxy.proxy.protocol

class Events:
# HTTP lifecycle
def http_connect(self, flow: mitmproxy.http.HTTPFlow):
"""
An HTTP CONNECT request was received. Setting a non 2xx response on
the flow will return the response to the client abort the
connection. CONNECT requests and responses do not generate the usual
HTTP handler events. CONNECT requests are only valid in regular and
upstream proxy modes.
"""

def requestheaders(self, flow: mitmproxy.http.HTTPFlow):
    """
        HTTP request headers were successfully read. At this point, the body
        is empty.
    """

def request(self, flow: mitmproxy.http.HTTPFlow):
    """
        The full HTTP request has been read.
    """

def responseheaders(self, flow: mitmproxy.http.HTTPFlow):
    """
        HTTP response headers were successfully read. At this point, the body
        is empty.
    """

def response(self, flow: mitmproxy.http.HTTPFlow):
    """
        The full HTTP response has been read.
    """

def error(self, flow: mitmproxy.http.HTTPFlow):
    """
        An HTTP error has occurred, e.g. invalid server responses, or
        interrupted connections. This is distinct from a valid server HTTP
        error response, which is simply a response with an HTTP error code.
    """

# TCP lifecycle
def tcp_start(self, flow: mitmproxy.tcp.TCPFlow):
    """
        A TCP connection has started.
    """

def tcp_message(self, flow: mitmproxy.tcp.TCPFlow):
    """
        A TCP connection has received a message. The most recent message
        will be flow.messages[-1]. The message is user-modifiable.
    """

def tcp_error(self, flow: mitmproxy.tcp.TCPFlow):
    """
        A TCP error has occurred.
    """

def tcp_end(self, flow: mitmproxy.tcp.TCPFlow):
    """
        A TCP connection has ended.
    """

# Websocket lifecycle
def websocket_handshake(self, flow: mitmproxy.http.HTTPFlow):
    """
        Called when a client wants to establish a WebSocket connection. The
        WebSocket-specific headers can be manipulated to alter the
        handshake. The flow object is guaranteed to have a non-None request
        attribute.
    """

def websocket_start(self, flow: mitmproxy.websocket.WebSocketFlow):
    """
        A websocket connection has commenced.
    """

def websocket_message(self, flow: mitmproxy.websocket.WebSocketFlow):
    """
        Called when a WebSocket message is received from the client or
        server. The most recent message will be flow.messages[-1]. The
        message is user-modifiable. Currently there are two types of
        messages, corresponding to the BINARY and TEXT frame types.
    """

def websocket_error(self, flow: mitmproxy.websocket.WebSocketFlow):
    """
        A websocket connection has had an error.
    """

def websocket_end(self, flow: mitmproxy.websocket.WebSocketFlow):
    """
        A websocket connection has ended.
    """

# Network lifecycle
def clientconnect(self, layer: mitmproxy.proxy.protocol.Layer):
    """
        A client has connected to mitmproxy. Note that a connection can
        correspond to multiple HTTP requests.
    """

def clientdisconnect(self, layer: mitmproxy.proxy.protocol.Layer):
    """
        A client has disconnected from mitmproxy.
    """

def serverconnect(self, conn: mitmproxy.connections.ServerConnection):
    """
        Mitmproxy has connected to a server. Note that a connection can
        correspond to multiple requests.
    """

def serverdisconnect(self, conn: mitmproxy.connections.ServerConnection):
    """
        Mitmproxy has disconnected from a server.
    """

def next_layer(self, layer: mitmproxy.proxy.protocol.Layer):
    """
        Network layers are being switched. You may change which layer will
        be used by returning a new layer object from this event.
    """

# General lifecycle
def configure(self, updated: typing.Set[str]):
    """
        Called when configuration changes. The updated argument is a
        set-like object containing the keys of all changed options. This
        event is called during startup with all options in the updated set.
    """

def done(self):
    """
        Called when the addon shuts down, either by being removed from
        the mitmproxy instance, or when mitmproxy itself shuts down. On
        shutdown, this event is called after the event loop is
        terminated, guaranteeing that it will be the final event an addon
        sees. Note that log handlers are shut down at this point, so
        calls to log functions will produce no output.
    """

def load(self, entry: mitmproxy.addonmanager.Loader):
    """
        Called when an addon is first loaded. This event receives a Loader
        object, which contains methods for adding options and commands. This
        method is where the addon configures itself.
    """

def log(self, entry: mitmproxy.log.LogEntry):
    """
        Called whenever a new log entry is created through the mitmproxy
        context. Be careful not to log from this event, which will cause an
        infinite loop!
    """

def running(self):
    """
        Called when the proxy is completely up and running. At this point,
        you can expect the proxy to be bound to a port, and all addons to be
        loaded.
    """

def update(self, flows: typing.Sequence[mitmproxy.flow.Flow]):
    """
        Update is called when one or more flow objects have been modified,
        usually from a different addon.
    """

针对http,常用的API

http.HTTPFlow 实例 flow

flow.request.headers #获取所有头信息,包含Host、User-Agent、Content-type等字段
flow.request.url #完整的请求地址,包含域名及请求参数,但是不包含放在body里面的请求参数
flow.request.pretty_url #同flow.request.url目前没看出什么差别
flow.request.host #域名
flow.request.method #请求方式。POST、GET等
flow.request.scheme #什么请求 ,如https
flow.request.path # 请求的路径,url除域名之外的内容
flow.request.get_text() #请求中body内容,有一些http会把请求参数放在body里面,那么可通过此方法获取,返回字典类型
flow.request.query #返回MultiDictView类型的数据,url直接带的键值参数
flow.request.get_content()#bytes,结果如flow.request.get_text()
flow.request.raw_content #bytes,结果如flow.request.get_content()
flow.request.urlencoded_form #MultiDictView,content-type:application/x-www-form-urlencoded时的请求参数,不包含url直接带的键值参数
flow.request.multipart_form #MultiDictView,content-type:multipart/form-data
时的请求参数,不包含url直接带的键值参数

以上均为获取request信息的一些常用方法,对于response,同理

flow.response.status_code #状态码
flow.response.text#返回内容,已解码
flow.response.content #返回内容,二进制
flow.response.setText()#修改返回内容,不需要转码

以上为不完全列举

示例

修改response内容,这里是服务器已经有返回了结果,再更改,也可以做不经过服务器处理,直接返回,看需求

def response(flow:http.HTTPFlow)-> None:
#特定接口需要返回1001结果
interface_list=["page/**"] #由于涉及公司隐私问题,隐藏实际的接口

url_path=flow.request.path
if  url_path.split("?")[0] in  interface_list:
    ctx.log.info("#"*50)
    ctx.log.info("待修改路径的内容:"+url_path)
    ctx.log.info("修改成:1001错误返回")
    ctx.log.info("修改前:\n")
    ctx.log.info(flow.response.text)
    flow.response.set_text(json.dumps({"result":"1001","message":"服务异常"}))#修改,使用set_text不用转码
    ctx.log.info("修改后:\n")
    ctx.log.info(flow.response.text)
    ctx.log.info("#"*50)
elif  flow.request.host in  host_list:#host_list 域名列表,作为全局变量,公司有多个域名,也隐藏
    ctx.log.info("response= "+flow.response.text)

应用
   移动app测试中,为了测试app的容错能力,在不改动数据库或者折腾服务器的情况下,脚本修改request或者response内容【这里也可以选择第三方工具,如fiddler同样支持,看个人需求】,查看app的表现;亦或是根据接口定义检查app的接口请求情况

作者:小蜗牛的成长
链接:https://www.jianshu.com/p/a495cc016682
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

转载于:https://www.cnblogs.com/c-x-a/p/9753526.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
mitmproxy 是一种强大的用于网络代理和拦截的工具,可以用于网络流量的拦截、修改和篡改,同时也能够实时展示网络流量的信息。对于想要深入了解 mitmproxy 工具背后实现原理的开发者来说,进行源码分析是必不可少的一步。 mitmproxy 的源码分析可以从以下几个方面展开: 1. 代理服务器的搭建:mitmproxy 的核心功能就是作为一个代理服务器,接收来自客户端的请求,并将其转发至服务器,同时还可以拦截和修改请求和响应数据。源码分析时,可以关注 mitmproxy 如何建立起与客户端和服务器之间的连接,以及如何实现请求和响应数据的转发和拦截。 2. 数据的拦截和修改:mitmproxy 对于请求和响应数据的拦截和修改非常灵活,可以通过编写自定义的脚本来实现各种功能。源码分析时,可以研究 mitmproxy 是如何根据用户配置的规则对数据进行拦截和修改的,能够深入了解其中的原理和实现细节。 3. 流量监控和分析:mitmproxy 能够实时展示网络流量的信息,包括请求和响应的头部信息、数据内容以及相关的时间、大小等信息。源码分析时,可以研究 mitmproxy 是如何实现数据的抓取和展示的,了解其底层的流程和机制。 4. 功能扩展和插件开发:mitmproxy 提供了丰富的功能扩展接口,开发者可以通过编写插件来扩展 mitmproxy 的功能。源码分析时,可以研究 mitmproxy 提供的插件接口和开发文档,了解如何通过开发插件来扩展 mitmproxy。 总之,mitmproxy 的源码分析能够深入了解其实现原理和内部机制,为后续的定制化开发和功能扩展提供基础。通过研究 mitmproxy 的源码,开发者可以更好地理解其使用方式和限制,并在实践中更好地应用 mitmproxy 工具。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值