usingmitmproxy

还不错的一个 proxy

是一个代理,加了个插件,导出 cookiehttpie 使用,还不错 目前把功能加强了一点点:

  1. 如果是来自 chrome 的请求,则保存header和cookie

  2. 否则从保存的记录load header和cookie

  3. store是直接做到http的session文件上的:

    $ fd|head |perl -pe 's/(?<=\.).+(?=\.)/******/g'
    sessions
    sessions/app.******.com
    sessions/app.******.json
    sessions/appcenter.******.com
    sessions/appcenter.******.json
    sessions/artemis.******.com
    sessions/artemis.******.json
    sessions/bat.******.com
    sessions/bat.******.json
    sessions/bat.******.com  
    

    所以 http --session=default 还是可以用的

# encoding=utf-8
"""HTTP-specific events.

Run as follows: mitmproxy -s anatomy.py
"""
import os
from mitmproxy import ctx
from mitmproxy.net.http.headers import Headers
import mitmproxy.http
import shutil
import subprocess
import json


class Events:
    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.
        """
        request = flow.request
        header_dict = dict(request.headers)
        if "User-Agent" in header_dict and "Chrome" in header_dict["User-Agent"]:
            self.save_header(request)
        else:
            self.load_header(request)

    def load_header(self, request):
        # 实例化输出类
        info = ctx.log.info
        host_dir = request.host if request.port == 80 else f"{ request.host }_{request.port}"
        header_dict = dict(request.headers)
        # cookies = header_dict["Cookie"]
        output_path = f"{os.getenv('HOME')}/.config/httpie/sessions/{host_dir}"
        output_file = f"{output_path}/default.json"
        if not os.path.exists(output_path):
            return
        with open(output_file, "r") as default_session:
            data = json.load(default_session)
        header_dict.update(data["headers"])
        try:
            request.headers.fields = tuple({(k.encode("utf-8"), v.encode("utf-8")) for k, v in header_dict.items()})
        except Exception as ex:
            info(ex)
        info("request update")

    def save_header(self, request):
        # 实例化输出类
        info = ctx.log.info
        header_dict = dict(request.headers)
        host_dir = request.host if request.port == 80 else f"{ request.host }_{request.port}"
        cookies = header_dict["Cookie"]
        output_path = f"{os.getenv('HOME')}/.config/httpie/sessions/{host_dir}"
        output_file = f"{output_path}/default.json"
        if not os.path.exists(output_path):
            subprocess.call(["mkdir", "-p", output_path])
        with open(output_file, "w") as default_session:
            default_session.write("""{
    "__meta__": {
        "about": "HTTPie session file",
        "help": "https://httpie.org/doc#sessions",
        "httpie": "2.2.0"
    },
    "auth": {
        "password": null,
        "type": null,
        "username": null
    },
    "cookies": {},
    "headers": {
        "Cookie": "%s",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36"
    }
}""" % cookies)
        info(f"update {output_file}")

    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.
        """


addons = [
    Events()
]

但是上游代理的设置可能不是很友好 可以使用 tinyproxy 来做上游代理,see : https://stackoverflow.com/questions/64616358/conditional-upstream-proxying-with-mitmproxy-pac-equivalent-module-script