|
- #!/usr/bin/python3
- #
- # Replay a stream, as if mitmproxy were sending filter requests via the filter/apply API
- #
- # Usage:
- #
- # breplay_stream.py path_prefix
- #
- # path_prefix : some file prefix
- #
- # This will list all files matching the prefix, sort them, and play them back.
- # These files should come in triplets: a .url file, a .headers.json file, and a .data file/
- #
- # To capture requests for later playback:
- # * Set debug_stream_fqdn and debug_stream_uri in mitmproxy/bubble_config.py and restart mitmproxy servers
- # * Request a matching using a device whose traffic will be routed through the mitmproxy
- # * Capture files will be written to /tmp/bubble_stream_[request-id]_chunkXXXX.[url, headers.json, data]
- #
- import glob
- import json
- import requests
- import sys
-
- HEADER_FILTER_PASSTHRU = 'X-Bubble-Passthru'
-
-
- def log (message):
- print(message, file=sys.stderr, flush=True)
-
-
- def replay_stream (prefix, out):
- url_files = glob.glob(prefix+'*.url')
- if url_files is None or len(url_files) == 0:
- log('No files found matching prefix: '+prefix)
- return
-
- url_files.sort()
- for u in url_files:
- chunk_file = replace_suffix(u, '.data')
- headers_file = replace_suffix(u, '.headers.json')
- with open(u, mode='r') as f:
- url = f.read()
- with open(headers_file, mode='r') as f:
- headers = json.load(f)
- with open(chunk_file, mode='rb') as f:
- chunk = f.read()
- log('sending '+str(len(chunk))+' bytes to '+url)
- try:
- response_data = replay_request(url, headers, chunk)
- except Exception as e:
- log('error sending filter request: '+repr(e))
- raise e
- log('received '+str(len(response_data))+' bytes')
- if len(response_data) > 0:
- out.write(response_data)
-
-
- def replace_suffix(f, suffix):
- return f[0:f.rfind('.')] + suffix
-
-
- def replay_request(url, headers, chunk):
- response = requests.post(url, data=chunk, headers=headers)
- if not response.ok:
- log('replay_request: Error fetching ' + url + ', HTTP status ' + str(response.status_code))
- return b''
-
- elif HEADER_FILTER_PASSTHRU in response.headers:
- log('replay_request: server returned X-Bubble-Passthru, not filtering subsequent requests')
- return chunk
-
- return response.content
-
-
- if __name__ == "__main__":
- with open('/tmp/replay_response', mode='wb') as out:
- replay_stream(sys.argv[1], out)
- out.close()
|