mitmproxy安装的正确姿势
本文以windows为准(windows7、windows8),红色字体部分非常关键
第一步、windows下载mitmproxy并安装,我选择的是较低的4.0版本;
第二步、iPhone和Android手机安装证书;
这一步很关键,网上有很多是错误的;
1) 在电脑上找到证书文件(而不是访问 mitm.it 下载),证书文件一般在这个目录下 C:\Users\Administrator\.mitmproxy\ ,文件名是 mitmproxy-ca-cert.pem ;
2) 把 上面的 证书文件发送到手机端口,正确的发送方式是,发到有126 或者 163 邮箱,然后用 手机自带浏览器下载(注意,QQ邮箱在iPhone的浏览器无法正常下载,所以不能用QQ邮箱);
3) 在手机上安装证书,我用的是ios15.1版,iPhone 还需要在 “设置”→“通用”→“关于本机”→“证书信任设置” 将 mitmproxy 的完全信任开关打开;
第三步、正确启动 mitmdump,打开cmd,命令行输入如下命令:
mitmdump -s tls_passthrough.py
如果没有参数 -s tls_passthrough.py, 手机访问不了https的网址,很多app也无法链接网络;
tls_passthrough.py 文件内容如下:
""" This inline script allows conditional TLS Interception based on a user-defined strategy. Example: > mitmdump -s tls_passthrough.py 1. curl --proxy http://localhost:8080 https://example.com --insecure // works - we'll also see the contents in mitmproxy 2. curl --proxy http://localhost:8080 https://example.com --insecure // still works - we'll also see the contents in mitmproxy 3. curl --proxy http://localhost:8080 https://example.com // fails with a certificate error, which we will also see in mitmproxy 4. curl --proxy http://localhost:8080 https://example.com // works again, but mitmproxy does not intercept and we do *not* see the contents Authors: Maximilian Hils, Matthew Tuusberg """ import collections import random from enum import Enum import mitmproxy from mitmproxy import ctx from mitmproxy.exceptions import TlsProtocolException from mitmproxy.proxy.protocol import TlsLayer, RawTCPLayer class InterceptionResult(Enum): success = True failure = False skipped = None class _TlsStrategy: """ Abstract base class for interception strategies. """ def __init__(self): # A server_address -> interception results mapping self.history = collections.defaultdict(lambda: collections.deque(maxlen=200)) def should_intercept(self, server_address): """ Returns: True, if we should attempt to intercept the connection. False, if we want to employ pass-through instead. """ raise NotImplementedError() def record_success(self, server_address): self.history[server_address].append(InterceptionResult.success) def record_failure(self, server_address): self.history[server_address].append(InterceptionResult.failure) def record_skipped(self, server_address): self.history[server_address].append(InterceptionResult.skipped) class ConservativeStrategy(_TlsStrategy): """ Conservative Interception Strategy - only intercept if there haven't been any failed attempts in the history. """ def should_intercept(self, server_address): if InterceptionResult.failure in self.history[server_address]: return False return True class ProbabilisticStrategy(_TlsStrategy): """ Fixed probability that we intercept a given connection. """ def __init__(self, p): self.p = p super(ProbabilisticStrategy, self).__init__() def should_intercept(self, server_address): return random.uniform(0, 1) < self.p class TlsFeedback(TlsLayer): """ Monkey-patch _establish_tls_with_client to get feedback if TLS could be established successfully on the client connection (which may fail due to cert pinning). """ def _establish_tls_with_client(self): server_address = self.server_conn.address try: super(TlsFeedback, self)._establish_tls_with_client() except TlsProtocolException as e: tls_strategy.record_failure(server_address) raise e else: tls_strategy.record_success(server_address) # inline script hooks below. tls_strategy = None def load(l): l.add_option( "tlsstrat", int, 0, "TLS passthrough strategy (0-100)", ) def configure(updated): global tls_strategy if ctx.options.tlsstrat > 0: tls_strategy = ProbabilisticStrategy(float(ctx.options.tlsstrat) / 100.0) else: tls_strategy = ConservativeStrategy() def next_layer(next_layer): """ This hook does the actual magic - if the next layer is planned to be a TLS layer, we check if we want to enter pass-through mode instead. """ if isinstance(next_layer, TlsLayer) and next_layer._client_tls: server_address = next_layer.server_conn.address if tls_strategy.should_intercept(server_address): # We try to intercept. # Monkey-Patch the layer to get feedback from the TLSLayer if interception worked. next_layer.__class__ = TlsFeedback else: # We don't intercept - reply with a pass-through layer and add a "skipped" entry. mitmproxy.ctx.log("TLS passthrough for %s" % repr(next_layer.server_conn.address), "info") next_layer_replacement = RawTCPLayer(next_layer.ctx, ignore=True) next_layer.reply.send(next_layer_replacement) tls_strategy.record_skipped(server_address) # 所有发出的请求数据包都会被这个方法所处理 # 所谓的处理,我们这里只是打印一下一些项;当然可以修改这些项的值直接给这些项赋值即可 def request(flow): print(flow.request.host) # 所有服务器响应的数据包都会被这个方法处理 # 所谓的处理,我们这里只是打印一下一些项 def response(flow): print("len:" + str(len(flow.response.text)))