Documentation and screenshots.
@ -1,28 +1,79 @@
|
|||||||
|
|
||||||
__mitmproxy__ is a console tool that allows interactive examination and
|
__mitmproxy__ is a console tool that allows interactive examination and
|
||||||
modification of HTTP traffic. The _?_ shortcut key shows complete documentation
|
modification of HTTP traffic. Use the _?_ shortcut key to view,
|
||||||
on __mitmproxy__'s functionality.
|
context-sensitive documentation from any __mitmproxy__ screen.
|
||||||
|
|
||||||
|
## Flow list
|
||||||
|
|
||||||
## The interface: connection list
|
The flow list shows an index of captured flows in chronological order.
|
||||||
|
|
||||||
<img src="@!urlTo("screenshots/mitmproxy.png")!@"/>
|
<img src="@!urlTo("screenshots/mitmproxy.png")!@"/>
|
||||||
|
|
||||||
|
- __1__: A GET request, returning a 302 Redirect response.
|
||||||
The connection list shows an index of captured flows in chronological order.
|
- __2__: A GET request, returning 16.75kb of text/html data.
|
||||||
So, in this case, we can we can see that we visited __gmail.com__, which then
|
- __3__: A replayed request.
|
||||||
returned a 301 redirect to mail.google.com.
|
- __4__: Intercepted flows are indicated with orange text. The user may edit
|
||||||
|
these flows, and then accept them (using the _a_ key) to continue. In this
|
||||||
The statusbar at the bottom tells us that there are 11 flows in the view, that
|
case, the request has been intercepted on the way to the server.
|
||||||
we are using the "pretty" view mode (more on that below), and that the proxy is
|
- __5__: A response intercepted from the server on the way to the client.
|
||||||
bound to port 8080 of all interfaces.
|
- __6__: The event log can be toggled on and off using the _e_ shorcut key. This
|
||||||
|
pane shows events and errors that may not result in a flow that shows up in the
|
||||||
Also visible is the __Event log__, which can be toggled on and off with the _v_
|
flow pane.
|
||||||
keyboard shortcut. This displays events like client connection information,
|
- __7__: Flow count.
|
||||||
errors, and script output.
|
- __8__: Various information on mitmproxy's state. In this case, we have an
|
||||||
|
interception pattern set to ".*".
|
||||||
|
- __9__: Bind address indicator - mitmproxy is listening on port 8080 of all
|
||||||
|
interfaces.
|
||||||
|
|
||||||
|
|
||||||
## Example: Interception
|
## Flow view
|
||||||
|
|
||||||
|
The __Flow View__ lets you inspect and manipulate a single flow:
|
||||||
|
|
||||||
|
<img src="@!urlTo("screenshots/mitmproxy-flowview.png")!@"/>
|
||||||
|
|
||||||
|
- __1__: Flow summary.
|
||||||
|
- __2__: The Request/Response tabs, showing you which part of the flow you are
|
||||||
|
currently viewing. In the example above, we're viewing the Response. Hit _tab_
|
||||||
|
to switch between the Response and the Request.
|
||||||
|
- __3__: Headers.
|
||||||
|
- __4__: Body.
|
||||||
|
- __5__: View Mode indicator. In this case, we're viewing the body in __hex__
|
||||||
|
mode. The other available modes are __pretty__, which uses a number of
|
||||||
|
heuristics to show you a friendly view of various content types, and __raw__,
|
||||||
|
which shows you exactly what's there without any changes. You can change modes
|
||||||
|
using the _m_ key.
|
||||||
|
|
||||||
|
|
||||||
|
## Key/Value Editor
|
||||||
|
|
||||||
|
It turns out that ordered key/value data is pervasive in HTTP communications,
|
||||||
|
so mitmproxy has a built-in editor to help edit and create this kind of data.
|
||||||
|
There are three ways to reach the __K/V Editor__ from the __Flow View__ screen:
|
||||||
|
|
||||||
|
- Editing request or response headers (_e_ for edit, then _h_ for headers)
|
||||||
|
- Editing a query string (_e_ for edit, then _q_ for query)
|
||||||
|
- Editing a URL-encoded form (_e_ for edit, then _f_ for form)
|
||||||
|
|
||||||
|
If there is is no form or query string, an empty __K/V Editor__ will be started
|
||||||
|
to let you add one. Here is the __K/V Editor__ showing the headers from a
|
||||||
|
request:
|
||||||
|
|
||||||
|
<img src="@!urlTo("screenshots/mitmproxy-kveditor.png")!@"/>
|
||||||
|
|
||||||
|
To edit, navigate to the key or value you want to modify using the arrow or vi
|
||||||
|
navigation keys, and press enter. The background color will change to show that
|
||||||
|
you are in edit mode for the specified field:
|
||||||
|
|
||||||
|
<img src="@!urlTo("screenshots/mitmproxy-kveditor-editmode.png")!@"/>
|
||||||
|
|
||||||
|
Modify the field as desired, and press escape or enter to exit edit mode when
|
||||||
|
you're done. You can also add a key/value pair (_a_ key), delete a pair (_d_
|
||||||
|
key), spawn an external editor on a field (_e_ key). Be sure to consult the
|
||||||
|
context-sensitive help (_?_ key) for more.
|
||||||
|
|
||||||
|
|
||||||
|
# Example: Interception
|
||||||
|
|
||||||
__mitmproxy__'s interception functionality lets you pause an HTTP request or
|
__mitmproxy__'s interception functionality lets you pause an HTTP request or
|
||||||
response, inspect and modify it, and then accept it to send it on to the server
|
response, inspect and modify it, and then accept it to send it on to the server
|
||||||
@ -31,27 +82,27 @@ or client.
|
|||||||
|
|
||||||
### 1: Set an interception pattern
|
### 1: Set an interception pattern
|
||||||
|
|
||||||
<img src="@!urlTo('intercept-filt.png')!@"/>
|
<img src="@!urlTo('mitmproxy-intercept-filt.png')!@"/>
|
||||||
|
|
||||||
We press _i_ to set an interception pattern. In this case, the __~q__ filter
|
We press _i_ to set an interception pattern. In this case, the __~q__ filter
|
||||||
pattern tells __mitmproxy__ to intercept all requests. For complete filter
|
pattern tells __mitmproxy__ to intercept all requests. For complete filter
|
||||||
syntax, see the [Filter expressions](@!urlTo("filters.html")!@) section of this
|
syntax, see the [Filter expressions](@!urlTo("filters.html")!@) section of this
|
||||||
document, or the built-in help function in __mitmproxy__.
|
document, or the built-in help function in __mitmproxy__.
|
||||||
|
|
||||||
### 2: Intercepted connections are indicated with a red exclamation mark:
|
### 2: Intercepted connections are indicated with orange text:
|
||||||
|
|
||||||
<img src="@!urlTo('intercept-mid.png')!@"/>
|
<img src="@!urlTo('mitmproxy-intercept-mid.png')!@"/>
|
||||||
|
|
||||||
### 3: You can now view and modify the request:
|
### 3: You can now view and modify the request:
|
||||||
|
|
||||||
<img src="@!urlTo('intercept-options.png')!@"/>
|
<img src="@!urlTo('mitmproxy-intercept-options.png')!@"/>
|
||||||
|
|
||||||
In this case, we viewed the request by selecting it, pressed _e_ for "edit"
|
In this case, we viewed the request by selecting it, pressed _e_ for "edit"
|
||||||
and _m_ for "method" to change the HTTP request method.
|
and _m_ for "method" to change the HTTP request method.
|
||||||
|
|
||||||
### 4: Accept the intercept to continue
|
### 4: Accept the intercept to continue:
|
||||||
|
|
||||||
<img src="@!urlTo('intercept-result.png')!@"/>
|
<img src="@!urlTo('mitmproxy-intercept-result.png')!@"/>
|
||||||
|
|
||||||
Finally, we press _a_ to accept the modified request, which is then sent on to
|
Finally, we press _a_ to accept the modified request, which is then sent on to
|
||||||
the server. In this case, we changed the request from an HTTP GET to to
|
the server. In this case, we changed the request from an HTTP GET to to
|
||||||
|
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 72 KiB |
Before Width: | Height: | Size: 40 KiB |
BIN
doc-src/screenshots/mitmproxy-flowview.png
Normal file
After Width: | Height: | Size: 334 KiB |
BIN
doc-src/screenshots/mitmproxy-intercept-filt.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
doc-src/screenshots/mitmproxy-intercept-mid.png
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
doc-src/screenshots/mitmproxy-intercept-options.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
doc-src/screenshots/mitmproxy-intercept-result.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
doc-src/screenshots/mitmproxy-kveditor-editmode.png
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
doc-src/screenshots/mitmproxy-kveditor.png
Normal file
After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 161 KiB |
@ -62,26 +62,6 @@ Called once on script shutdown, after any other events.
|
|||||||
The main classes you will deal with in writing mitmproxy scripts are:
|
The main classes you will deal with in writing mitmproxy scripts are:
|
||||||
|
|
||||||
<table class="kvtable">
|
<table class="kvtable">
|
||||||
<tr>
|
|
||||||
<th>libmproxy.flow.ScriptContext</th>
|
|
||||||
<td>A handle for interacting with mitmproxy's global state.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>libmproxy.flow.Flow</th>
|
|
||||||
<td>A collection of objects representing a single HTTP transaction.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>libmproxy.flow.Request</th>
|
|
||||||
<td>An HTTP request.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>libmproxy.flow.Response</th>
|
|
||||||
<td>An HTTP response.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>libmproxy.flow.Error</th>
|
|
||||||
<td>A communications error.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>libmproxy.flow.ClientConnection</th>
|
<th>libmproxy.flow.ClientConnection</th>
|
||||||
<td>Describes a client connection.</td>
|
<td>Describes a client connection.</td>
|
||||||
@ -90,12 +70,38 @@ The main classes you will deal with in writing mitmproxy scripts are:
|
|||||||
<th>libmproxy.flow.ClientDisconnection</th>
|
<th>libmproxy.flow.ClientDisconnection</th>
|
||||||
<td>Describes a client disconnection.</td>
|
<td>Describes a client disconnection.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>libmproxy.flow.Error</th>
|
||||||
|
<td>A communications error.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>libmproxy.flow.Flow</th>
|
||||||
|
<td>A collection of objects representing a single HTTP transaction.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>libmproxy.flow.Headers</th>
|
<th>libmproxy.flow.Headers</th>
|
||||||
<td>HTTP headers for a request or response.</td>
|
<td>HTTP headers for a request or response.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
<tr>
|
||||||
|
<th>libmproxy.flow.ODict</th>
|
||||||
|
|
||||||
|
<td>A dictionary-like object for managing sets of key/value data. There
|
||||||
|
is also a variant called CaselessODict that ignores key case for some
|
||||||
|
calls.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>libmproxy.flow.Response</th>
|
||||||
|
<td>An HTTP response.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>libmproxy.flow.Request</th>
|
||||||
|
<td>An HTTP request.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>libmproxy.flow.ScriptContext</th>
|
||||||
|
<td>A handle for interacting with mitmproxy's global state.</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
The canonical API documentation is the code. You can view the API documentation
|
The canonical API documentation is the code. You can view the API documentation
|
||||||
using pydoc (which is installed with Python by default), like this:
|
using pydoc (which is installed with Python by default), like this:
|
||||||
|
@ -318,7 +318,6 @@ class ConsoleMaster(flow.FlowMaster):
|
|||||||
('heading_key', "q"), ":back",
|
('heading_key', "q"), ":back",
|
||||||
]
|
]
|
||||||
footer_text_flowview = [
|
footer_text_flowview = [
|
||||||
('heading_key', "tab"), ":toggle view ",
|
|
||||||
('heading_key', "?"), ":help ",
|
('heading_key', "?"), ":help ",
|
||||||
('heading_key', "q"), ":back ",
|
('heading_key', "q"), ":back ",
|
||||||
]
|
]
|
||||||
|
@ -84,6 +84,8 @@ def fcol(s, attr):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
REPLAY_SYMBOL = u"\u21ba"
|
||||||
|
|
||||||
def format_flow(f, focus, extended=False, padding=2):
|
def format_flow(f, focus, extended=False, padding=2):
|
||||||
pile = []
|
pile = []
|
||||||
|
|
||||||
@ -98,7 +100,7 @@ def format_flow(f, focus, extended=False, padding=2):
|
|||||||
else:
|
else:
|
||||||
req.append(fcol(">>" if focus else " ", "focus"))
|
req.append(fcol(">>" if focus else " ", "focus"))
|
||||||
if f.request.is_replay():
|
if f.request.is_replay():
|
||||||
req.append(fcol(u"\u267B", "replay"))
|
req.append(fcol(REPLAY_SYMBOL, "replay"))
|
||||||
req.append(fcol(f.request.method, "method"))
|
req.append(fcol(f.request.method, "method"))
|
||||||
|
|
||||||
preamble = sum(i[1] for i in req) + len(req) -1
|
preamble = sum(i[1] for i in req) + len(req) -1
|
||||||
@ -126,7 +128,7 @@ def format_flow(f, focus, extended=False, padding=2):
|
|||||||
|
|
||||||
if f.response:
|
if f.response:
|
||||||
if f.response.is_replay():
|
if f.response.is_replay():
|
||||||
resp.append(fcol(u"\u267B", "replay"))
|
resp.append(fcol(REPLAY_SYMBOL, "replay"))
|
||||||
if f.response.code in [200, 304]:
|
if f.response.code in [200, 304]:
|
||||||
resp.append(fcol(f.response.code, "goodcode"))
|
resp.append(fcol(f.response.code, "goodcode"))
|
||||||
else:
|
else:
|
||||||
|
@ -58,6 +58,10 @@ class ODict:
|
|||||||
return self.lst == other.lst
|
return self.lst == other.lst
|
||||||
|
|
||||||
def __getitem__(self, k):
|
def __getitem__(self, k):
|
||||||
|
"""
|
||||||
|
Returns a list of values matching key.
|
||||||
|
|
||||||
|
"""
|
||||||
ret = []
|
ret = []
|
||||||
k = self._kconv(k)
|
k = self._kconv(k)
|
||||||
for i in self.lst:
|
for i in self.lst:
|
||||||
@ -73,18 +77,28 @@ class ODict:
|
|||||||
return new
|
return new
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
|
"""
|
||||||
|
Total number of (key, value) pairs.
|
||||||
|
"""
|
||||||
return len(self.lst)
|
return len(self.lst)
|
||||||
|
|
||||||
def __setitem__(self, k, values):
|
def __setitem__(self, k, valuelist):
|
||||||
if isinstance(values, basestring):
|
"""
|
||||||
raise ValueError("ODict values should be lists.")
|
Sets the values for key k. If there are existing values for this
|
||||||
|
key, they are cleared.
|
||||||
|
"""
|
||||||
|
if isinstance(valuelist, basestring):
|
||||||
|
raise ValueError("ODict valuelist should be lists.")
|
||||||
k = self._kconv(k)
|
k = self._kconv(k)
|
||||||
new = self._filter_lst(k, self.lst)
|
new = self._filter_lst(k, self.lst)
|
||||||
for i in values:
|
for i in valuelist:
|
||||||
new.append((k, i))
|
new.append((k, i))
|
||||||
self.lst = new
|
self.lst = new
|
||||||
|
|
||||||
def __delitem__(self, k):
|
def __delitem__(self, k):
|
||||||
|
"""
|
||||||
|
Delete all items matching k.
|
||||||
|
"""
|
||||||
self.lst = self._filter_lst(k, self.lst)
|
self.lst = self._filter_lst(k, self.lst)
|
||||||
|
|
||||||
def __contains__(self, k):
|
def __contains__(self, k):
|
||||||
|