mitmproxy is your swiss-army knife for interactive HTTP/HTTPS proxy. In fact, it can be used to intercept, inspect, modify and replay web traffic such as HTTP/1, HTTP/2, WebSockets, or any other SSL/TLS-protected protocols.
Moreover, mitproxy has a powerful Python API offers full control over any intercepted request and response.
ref:
https://mitmproxy.org/
https://docs.mitmproxy.org/stable/
Concept
ref:
https://docs.mitmproxy.org/stable/concepts-howmitmproxyworks/
Installation
$ brew install mitmproxy
$ mitmproxy --version
Mitmproxy: 4.0.4
Python: 3.7.0
OpenSSL: OpenSSL 1.0.2p 14 Aug 2018
Platform: Darwin-18.0.0-x86_64-i386-64bit
ref:
https://docs.mitmproxy.org/stable/overview-installation/
Configuration
Make your computer become the man of man-in-the-middle attack.
macOS
$ ipconfig getifaddr en0
192.168.0.128
$ mitmproxy -p 8888
# or
$ mitmweb -p 8888
$ open http://127.0.0.1:8081/
Flow List keys:
?
: Show helpq
: Exit the current viewf
: Set view filterr
: Replay this flowi
: Set intercept filterhjkl
orarrow
: Move left/down/up/rightenter
: Select
Flow Details keys:
tab
: Select nextm
: Set flow view modee
: Edit this flow (request or response)a
: Accept this intercepted flow
ref:
https://docs.mitmproxy.org/stable/tools-mitmproxy/
https://github.com/mitmproxy/mitmproxy/blob/master/mitmproxy/tools/console/defaultkeys.py
iOS
- Go to Settings > Wi-Fi > Your Wi-Fi > Configure Proxy
- Select Manual, enter the following values:
- Server:
192.168.0.128
- Port:
8888
- Authentication: unchecked
- Server:
- Select Manual, enter the following values:
- Open http://mitm.it/ on Safari
- Install the corresponding certificate for your device
- Go to Settings > General > About > Certificate Trust Settings
- Turn on the
mitmproxy
certificate
- Turn on the
- Open any app you want to watch
ref:
https://docs.mitmproxy.org/stable/concepts-certificates/
Usage
The most exciting feature is you could alter any request and response using a Python script, mitmdump -s
!
ref:
https://docs.mitmproxy.org/stable/tools-mitmdump/
https://github.com/mitmproxy/mitmproxy/tree/master/examples
Deal With Certificate Pinning
You can use your own certificate by passing the --certs example.com=/path/to/example.com.pem
option to mitmproxy. Mitmproxy then uses the provided certificate for interception of the specified domain.
The certificate file is expected to be in the PEM format which would roughly looks like this:
-----BEGIN PRIVATE KEY-----
<private key>
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
<cert>
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
<intermediary cert (optional)>
-----END CERTIFICATE-----
$ mitmproxy -p 8888 --certs example.com=example.com.pem
ref:
https://docs.mitmproxy.org/stable/concepts-certificates/#using-a-custom-server-certificate
Redirect Requests To Your Local Development Server
# redirect_to_localhost.py
from mitmproxy import ctx
from mitmproxy import http
REMOTE_HOST = 'api.example.com'
DEV_HOST = '192.168.0.128'
DEV_PORT = 8000
def request(flow: http.HTTPFlow) -> None:
if flow.request.pretty_host in [REMOTE_HOST, DEV_HOST]:
ctx.log.info('=== request')
ctx.log.info(str(flow.request.headers))
ctx.log.info(f'content: {str(flow.request.content)}')
flow.request.scheme = 'http'
flow.request.host = DEV_HOST
flow.request.port = DEV_PORT
def response(flow: http.HTTPFlow) -> None:
if flow.request.pretty_host == DEV_HOST:
ctx.log.info('=== response')
ctx.log.info(str(flow.response.headers))
if flow.response.headers.get('Content-Type', '').startswith('image/'):
return
ctx.log.info(f'body: {str(flow.response.get_content())}')
ref:
https://discourse.mitmproxy.org/t/reverse-mode-change-request-host-according-to-the-sni-https/466
You could use negative regex with --ignore-hosts
to only watch specific domains. Of course, you are still able to blacklist any domain you don't want: --ignore-hosts 'apple.com|icloud.com|itunes.com|facebook.com|googleapis.com|crashlytics.com'
.
Currently, changing the Host
server for HTTP/2 connections is not allowed, but you could just disable HTTP/2 proxy to solve the issue if you don't need HTTP/2 for local development.
$ mitmdump -p 8888 \
--certs example.com=example.com.pem \
-v --flow-detail 3 \
--ignore-hosts '^(?!.*example\.com)' \
--no-http2 \
-s redirect_to_localhost.py
ref:
https://stackoverflow.com/questions/29414158/regex-negative-lookahead-with-wildcard