usingmitmproxy
还不错的一个 proxy
是一个代理,加了个插件,导出 cookie 给 httpie 使用,还不错 目前把功能加强了一点点:
如果是来自 chrome 的请求,则保存header和cookie
否则从保存的记录load header和cookie
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