diff options
Diffstat (limited to 'docs')
105 files changed, 6431 insertions, 0 deletions
diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..69fa449d --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +_build/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..a22bc8a2 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,195 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/mitmproxy.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/mitmproxy.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/mitmproxy" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/mitmproxy" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." + +livehtml: + sphinx-autobuild -b html -z '../libmproxy' -r '___jb_(old|bak)___$$' $(ALLSPHINXOPTS) $(BUILDDIR)/html
\ No newline at end of file diff --git a/docs/certinstall-webapp.png b/docs/certinstall-webapp.png Binary files differnew file mode 100644 index 00000000..10e795cd --- /dev/null +++ b/docs/certinstall-webapp.png diff --git a/docs/certinstall.rst b/docs/certinstall.rst new file mode 100644 index 00000000..96227217 --- /dev/null +++ b/docs/certinstall.rst @@ -0,0 +1,174 @@ +.. _certinstall: + +About Certificates +================== + +Introduction +------------ + +Mitmproxy can decrypt encrypted traffic on the fly, as long as the client +trusts its built-in certificate authority. Usually this means that the +mitmproxy CA certificates have to be installed on the client device. + +Quick Setup +----------- + +By far the easiest way to install the mitmproxy certificates is to use the +built-in certificate installation app. To do this, just start mitmproxy and +configure your target device with the correct proxy settings. Now start a +browser on the device, and visit the magic domain **mitm.it**. You should see +something like this: + +.. image:: certinstall-webapp.png + +Click on the relevant icon, follow the setup instructions for the platform +you're on and you are good to go. + + +Installing the mitmproxy CA certificate manually +------------------------------------------------ + +Sometimes using the quick install app is not an option - Java or the iOS +Simulator spring to mind - or you just need to do it manually for some other +reason. Below is a list of pointers to manual certificate installation +documentation for some common platforms. + +The mitmproxy CA cert is located in ``~/.mitmproxy`` after it has been generated at the first +start of mitmproxy. + + +iOS +^^^ + +http://kb.mit.edu/confluence/pages/viewpage.action?pageId=152600377 + +iOS Simulator +^^^^^^^^^^^^^ + +See https://github.com/ADVTOOLS/ADVTrustStore#how-to-use-advtruststore + +Java +^^^^ + +See http://docs.oracle.com/cd/E19906-01/820-4916/geygn/index.html + +Android/Android Simulator +^^^^^^^^^^^^^^^^^^^^^^^^^ + +See http://wiki.cacert.org/FAQ/ImportRootCert#Android_Phones_.26_Tablets + +Windows +^^^^^^^ + +See http://windows.microsoft.com/en-ca/windows/import-export-certificates-private-keys#1TC=windows-7 + +Windows (automated) +^^^^^^^^^^^^^^^^^^^ + +>>> certutil.exe -importpfx mitmproxy-ca-cert.p12 + +See also: https://technet.microsoft.com/en-us/library/cc732443.aspx + +Mac OS X +^^^^^^^^ + +See https://support.apple.com/kb/PH7297?locale=en_US + +Ubuntu/Debian +^^^^^^^^^^^^^ + +See http://askubuntu.com/questions/73287/how-do-i-install-a-root-certificate/94861#94861 + +Mozilla Firefox +^^^^^^^^^^^^^^^ + +See https://wiki.mozilla.org/MozillaRootCertificate#Mozilla_Firefox + +Chrome on Linux +^^^^^^^^^^^^^^^ + +See https://code.google.com/p/chromium/wiki/LinuxCertManagement + + +More on mitmproxy certificates +------------------------------ + +The first time **mitmproxy** or **mitmdump** is run, the mitmproxy Certificate +Authority (CA) is created in the config directory (``~/.mitmproxy`` by default). +This CA is used for on-the-fly generation of dummy certificates for each of the +SSL sites that your client visits. Since your browser won't trust the +mitmproxy CA out of the box , you will see an SSL certificate warning every +time you visit a new SSL domain through mitmproxy. When you are testing a +single site through a browser, just accepting the bogus SSL cert manually is +not too much trouble, but there are a many circumstances where you will want to +configure your testing system or browser to trust the mitmproxy CA as a +signing root authority. For security reasons, the mitmproxy CA is generated uniquely on the first +start and is not shared between mitmproxy installations on different devices. + + +CA and cert files +----------------- + +The files created by mitmproxy in the .mitmproxy directory are as follows: + +===================== ========================================================================== +mitmproxy-ca.pem The certificate **and the private key** in PEM format. +mitmproxy-ca-cert.pem The certificate in PEM format. + Use this to distribute on most non-Windows platforms. +mitmproxy-ca-cert.p12 The certificate in PKCS12 format. For use on Windows. +mitmproxy-ca-cert.cer Same file as .pem, but with an extension expected by some Android devices. +===================== ========================================================================== + +Using a custom certificate +-------------------------- + +You can use your own certificate by passing the ``--cert`` option to +mitmproxy. Mitmproxy then uses the provided certificate for interception of the +specified domains instead of generating a certificate signed by its own CA. + +The certificate file is expected to be in the PEM format. You can include +intermediary certificates right below your leaf certificate, so that you PEM +file roughly looks like this: + +.. code-block:: none + + -----BEGIN PRIVATE KEY----- + <private key> + -----END PRIVATE KEY----- + -----BEGIN CERTIFICATE----- + <cert> + -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- + <intermediary cert (optional)> + -----END CERTIFICATE----- + + +For example, you can generate a certificate in this format using these instructions: + + +>>> openssl genrsa -out cert.key 2048 +>>> openssl req -new -x509 -key cert.key -out cert.crt + (Specify the mitm domain as Common Name, e.g. *.google.com) +>>> cat cert.key cert.crt > cert.pem +>>> mitmproxy --cert=cert.pem + + +Using a custom certificate authority +------------------------------------ + +By default, mitmproxy will use ``~/.mitmproxy/mitmproxy-ca.pem`` as +the certificate authority to generate certificates for all domains for which no +custom certificate is provided (see above). You can use your own certificate +authority by passing the ``--confdir`` option to mitmproxy. Mitmproxy +will then look for ``mitmproxy-ca.pem`` in the specified directory. If +no such file exists, it will be generated automatically. + + +Using a client side certificate +------------------------------- + +You can use a client certificate by passing the ``--client-certs DIRECTORY`` option to mitmproxy. +If you visit example.org, mitmproxy looks for a file named ``example.org.pem`` in the specified +directory and uses this as the client cert. The certificate file needs to be in the PEM format and +should contain both the unencrypted private key and the certificate. + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..1e686007 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# +# mitmproxy documentation build configuration file, created by +# sphinx-quickstart on Thu Sep 03 14:04:13 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('..')) + +import libmproxy.version + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.viewcode', + 'sphinx.ext.napoleon', + 'sphinxcontrib.documentedlist' +] + +autodoc_member_order = "bysource" + +# Add any paths that contain templates here, relative to this directory. +#templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'mitmproxy docs' +copyright = u'2015, the mitmproxy project' +author = u'The mitmproxy project' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = libmproxy.version.VERSION +# The full version, including alpha/beta/rc tags. +release = libmproxy.version.VERSION + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +modindex_common_prefix = ['libmproxy.'] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'sphinx_rtd_theme' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +html_theme_options = { + # 'logo_only': True, +} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +html_title = "mitmproxy %s documentation" % version + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = "mitmproxy-long.png" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = "favicon.ico" + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +# html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'mitmproxydoc'
\ No newline at end of file diff --git a/docs/config.rst b/docs/config.rst new file mode 100644 index 00000000..634b8703 --- /dev/null +++ b/docs/config.rst @@ -0,0 +1,86 @@ +.. _config: + +Configuration +============= + +Mitmproxy is configured through a set of files in the users ~/.mitmproxy +directory. + +mitmproxy.conf + Settings for the :program:`mitmproxy`. This file can contain any options supported by + mitmproxy. + +mitmdump.conf + Settings for the :program:`mitmdump`. This file can contain any options supported by mitmdump. + +common.conf + Settings shared between all command-line tools. Settings in this file are over-ridden by those + in the tool-specific files. Only options shared by mitmproxy and mitmdump should be used in + this file. + +Syntax +------ + +Comments +^^^^^^^^ + +.. code-block:: none + + # this is a comment + ; this is also a comment (.ini style) + --- and this is a comment too (yaml style) + +Key/Value pairs +^^^^^^^^^^^^^^^ + +- Keys and values are case-sensitive +- Whitespace is ignored +- Lists are comma-delimited, and enclosed in square brackets + +.. code-block:: none + + name = value # (.ini style) + name: value # (yaml style) + --name value # (command-line option style) + + fruit = [apple, orange, lemon] + indexes = [1, 12, 35 , 40] + +Flags +^^^^^ + +These are boolean options that take no value but true/false. + +.. code-block:: none + + name = true # (.ini style) + name + --name # (command-line option style) + +Options +------- + +The options available in the config files are precisely those available as +command-line flags, with the key being the option's long name. To get a +complete list of these, use the :option:`--help` option on each of the tools. Be +careful to only specify common options in the **common.conf** file - +unsupported options in this file will be detected as an error on startup. + +Examples +-------- + +common.conf +^^^^^^^^^^^ + +Note that :option:`--port` is an option supported by all tools. + +.. code-block:: none + + port = 8080 + +mitmproxy.conf +^^^^^^^^^^^^^^ + +.. code-block:: none + + palette = light diff --git a/docs/custom-routing.txt b/docs/custom-routing.txt new file mode 100644 index 00000000..2ba2281f --- /dev/null +++ b/docs/custom-routing.txt @@ -0,0 +1,24 @@ +# Adapted from http://tldp.org/HOWTO/TransparentProxy-6.html (6.2 Second method) +# Note that the choice of firewall mark (3) and routing table (2) was fairly arbitrary. +# If you are already using policy routing or firewall marking for some other purpose, +# make sure you choose unique numbers here. Otherwise, don't worry about it. + + + +# On the router, run + +PROXY_IP=192.168.1.100 +TARGET_IP=192.168.1.110 + +iptables -t mangle -A PREROUTING -j ACCEPT -p tcp -m multiport --dports 80,443 -s ! $TARGET_IP +# Alternative to MITM the whole network: +# iptables -t mangle -A PREROUTING -j ACCEPT -p tcp -m multiport --dports 80,443 -s $PROXY_IP +iptables -t mangle -A PREROUTING -j MARK --set-mark 3 -p tcp -m multiport --dports 80,443 +ip rule add fwmark 3 table 2 +ip route add default via $PROXY_IP dev br0 table 2 + + + +# On the proxy machine, run + +iptables -A PREROUTING -t nat -i eth0 -p tcp -m multiport --dports 80,443 -j REDIRECT --to-port 8080 diff --git a/docs/dev/addingviews.html b/docs/dev/addingviews.html new file mode 100644 index 00000000..12623a31 --- /dev/null +++ b/docs/dev/addingviews.html @@ -0,0 +1,52 @@ +As discussed in [the Flow View section of the mitmproxy +overview](@!urlTo("mitmproxy.html")!@), mitmproxy allows you to inspect and +manipulate flows. When inspecting a single flow, mitmproxy uses a number of +heuristics to show a friendly view of various content types; if mitmproxy +cannot show a friendly view, mitmproxy defaults to a __raw__ view. + +Each content type invokes a different flow viewer to parse the data and display +the friendly view. Users can add custom content viewers by adding a view class +to contentview.py, discussed below. + +## Adding a new View class to contentview.py + +The content viewers used by mitmproxy to present a friendly view of various +content types are stored in contentview.py. Reviewing this file shows a number +of classes named ViewSomeDataType, each with the properties: __name__, +__prompt__, and __content\_types__ and a function named __\_\_call\_\___. + +Adding a new content viewer to parse a data type is as simple as writing a new +View class. Your new content viewer View class should have the same properties +as the other View classes: __name__, __prompt__, and __content\_types__ and a +__\_\_call\_\___ function to parse the content of the request/response. + +* The __name__ property should be a string describing the contents and new content viewer; +* The __prompt__ property should be a two item tuple: + + - __1__: A string that will be used to display the new content viewer's type; and + - __2__: A one character string that will be the hotkey used to select the new content viewer from the Flow View screen; + +* The __content\_types__ property should be a list of strings of HTTP Content\-Types that the new content viewer can parse. + * Note that mitmproxy will use the content\_types to try and heuristically show a friendly view of content and that you can override the built-in views by populating content\_types with values for content\_types that are already parsed -- e.g. "image/png". + +After defining the __name__, __prompt__, and __content\_types__ properties of +the class, you should write the __\_\_call\_\___ function, which will parse the +request/response data and provide a friendly view of the data. The +__\_\_call\_\___ function should take the following arguments: __self__, +__hdrs__, __content__, __limit__; __hdrs__ is a ODictCaseless object containing +the headers of the request/response; __content__ is the content of the +request/response, and __limit__ is an integer representing the amount of data +to display in the view window. + +The __\_\_call\_\___ function returns two values: (1) a string describing the +parsed data; and (2) the parsed data for friendly display. The parsed data to +be displayed should be a list of strings formatted for display. You can use +the __\_view\_text__ function in contentview.py to format text for display. +Alternatively, you can display content as a series of key-value pairs; to do +so, prepare a list of lists, where each list item is a two item list -- a key +that describes the data, and then the data itself; after preparing the list of +lists, use the __common.format\_keyvals__ function on it to prepare it as text +for display. + +If the new content viewer fails or throws an exception, mitmproxy will default +to a __raw__ view. diff --git a/docs/dev/architecture.rst b/docs/dev/architecture.rst new file mode 100644 index 00000000..e7995141 --- /dev/null +++ b/docs/dev/architecture.rst @@ -0,0 +1,14 @@ +.. _architecture: + +Architecture +============ + +To give you a better understanding of how mitmproxy works, mitmproxy's +high-level architecture is detailed in the following graphic: + +.. image:: ../schematics/architecture.png + +:download:`architecture.pdf <../schematics/architecture.pdf>` + +Please don't refrain from asking any further +questions on the mailing list, the Slack channel or the GitHub issue tracker. diff --git a/docs/dev/exceptions.rst b/docs/dev/exceptions.rst new file mode 100644 index 00000000..dab10e74 --- /dev/null +++ b/docs/dev/exceptions.rst @@ -0,0 +1,9 @@ +.. _exceptions: + +Exceptions +========== + +.. automodule:: libmproxy.exceptions + :show-inheritance: + :members: + :undoc-members: diff --git a/docs/dev/models.rst b/docs/dev/models.rst new file mode 100644 index 00000000..9929e4b2 --- /dev/null +++ b/docs/dev/models.rst @@ -0,0 +1,25 @@ +.. _models: + +Models +====== + +.. warning:: + The documentation for models has not been converted to rst yet and **many attributes/features + are missing**. + Please read the source code instead. + +.. automodule:: libmproxy.models + :show-inheritance: + :members: + :undoc-members: + + +.. automodule:: netlib.http.semantics + :members: Request, Response + :undoc-members: + + .. autoclass:: Headers + :show-inheritance: + :members: + :special-members: + :no-undoc-members: diff --git a/docs/dev/protocols.rst b/docs/dev/protocols.rst new file mode 100644 index 00000000..1f8cca9a --- /dev/null +++ b/docs/dev/protocols.rst @@ -0,0 +1,15 @@ +.. _protocols: + +Protocols +========= + +.. automodule:: libmproxy.protocol + + .. autoclass:: Layer + :members: + :special-members: + + .. autoclass:: ServerConnectionMixin + :members: + + .. autoexception:: Kill diff --git a/docs/dev/proxy.rst b/docs/dev/proxy.rst new file mode 100644 index 00000000..dbd6fe67 --- /dev/null +++ b/docs/dev/proxy.rst @@ -0,0 +1,12 @@ +.. _proxy: + +Proxy Server +============ + +.. automodule:: libmproxy.proxy + + .. autoclass:: ProxyServer + .. autoclass:: DummyServer + .. autoclass:: ProxyConfig + .. autoclass:: RootContext + :members: diff --git a/docs/dev/sslkeylogfile.rst b/docs/dev/sslkeylogfile.rst new file mode 100644 index 00000000..04b86cc4 --- /dev/null +++ b/docs/dev/sslkeylogfile.rst @@ -0,0 +1,14 @@ +.. _sslkeylogfile: + +TLS Master Secrets +================== + +The SSL master keys can be logged by mitmproxy so that external programs can decrypt TLS +connections both from and to the proxy. Key logging is enabled by setting the environment variable +:envvar:`SSLKEYLOGFILE` so that it points to a writable text file. +Recent versions of WireShark can use these log files to decrypt packets. +You can specify the key file path in WireShark via +:samp:`Edit -> Preferences -> Protocols -> SSL -> (Pre)-Master-Secret log filename`. + +Note that :envvar:`SSLKEYLOGFILE` is respected by other programs as well, e.g. Firefox and Chrome. +If this creates any issues, you can set :envvar:`MITMPROXY_SSLKEYLOGFILE` alternatively. diff --git a/docs/dev/testing.rst b/docs/dev/testing.rst new file mode 100644 index 00000000..36c85426 --- /dev/null +++ b/docs/dev/testing.rst @@ -0,0 +1,46 @@ +.. _testing: + +Testing +======= + +All the mitmproxy projects strive to maintain 100% code coverage. In general, +patches and pull requests will be declined unless they're accompanied by a +suitable extension to the test suite. + +Our tests are written for the nose_ test framework. +At the point where you send your pull request, a command like this: + +>>> nosetests --with-cov --cov-report term-missing ./test + +Should give output something like this: + +.. code-block:: none + + > ---------- coverage: platform darwin, python 2.7.2-final-0 -- + > Name Stmts Miss Cover Missing + > ---------------------------------------------------- + > libmproxy/__init__ 0 0 100% + > libmproxy/app 4 0 100% + > libmproxy/cmdline 100 0 100% + > libmproxy/controller 69 0 100% + > libmproxy/dump 150 0 100% + > libmproxy/encoding 39 0 100% + > libmproxy/filt 201 0 100% + > libmproxy/flow 891 0 100% + > libmproxy/proxy 427 0 100% + > libmproxy/script 27 0 100% + > libmproxy/utils 133 0 100% + > libmproxy/version 4 0 100% + > ---------------------------------------------------- + > TOTAL 2045 0 100% + > ---------------------------------------------------- + > Ran 251 tests in 11.864s + + +There are exceptions to the coverage requirement - for instance, much of the +console interface code can't sensibly be unit tested. These portions are +excluded from coverage analysis either in the **.coveragerc** file, or using +**#pragma no-cover** directives. To keep our coverage analysis relevant, we use +these measures as sparingly as possible. + +.. _nose: https://nose.readthedocs.org/en/latest/ diff --git a/docs/favicon.ico b/docs/favicon.ico Binary files differnew file mode 100644 index 00000000..3c3b891c --- /dev/null +++ b/docs/favicon.ico diff --git a/docs/features/anticache.rst b/docs/features/anticache.rst new file mode 100644 index 00000000..65d22bab --- /dev/null +++ b/docs/features/anticache.rst @@ -0,0 +1,15 @@ +.. _anticache: + +Anticache +========= +When the :option:`--anticache` option is passed to mitmproxy, it removes headers +(``if-none-match`` and ``if-modified-since``) that might elicit a +``304 not modified`` response from the server. This is useful when you want to make +sure you capture an HTTP exchange in its totality. It's also often used during +:ref:`clientreplay`, when you want to make sure the server responds with complete data. + + +================== ====================== +command-line :option:`--anticache` +mitmproxy shortcut :kbd:`o` then :kbd:`a` +================== ====================== diff --git a/docs/features/clientreplay.rst b/docs/features/clientreplay.rst new file mode 100644 index 00000000..b0eb6792 --- /dev/null +++ b/docs/features/clientreplay.rst @@ -0,0 +1,18 @@ +.. _clientreplay: + +Client-side replay +================== + +Client-side replay does what it says on the tin: you provide a previously saved +HTTP conversation, and mitmproxy replays the client requests one by one. Note +that mitmproxy serializes the requests, waiting for a response from the server +before starting the next request. This might differ from the recorded +conversation, where requests may have been made concurrently. + +You may want to use client-side replay in conjunction with the +:ref:`anticache` option, to make sure the server responds with complete data. + +================== ================= +command-line :option:`-c path` +mitmproxy shortcut :kbd:`c` +================== ================= diff --git a/docs/features/filters.rst b/docs/features/filters.rst new file mode 100644 index 00000000..2adcfb70 --- /dev/null +++ b/docs/features/filters.rst @@ -0,0 +1,39 @@ +.. _filters: + +Filter expressions +================== + +Many commands in :program:`mitmproxy` and :program:`mitmdump` take a filter expression. +Filter expressions consist of the following operators: + +.. documentedlist:: + :header: "Expression" "Description" + :listobject: libmproxy.filt.help + +- Regexes are Python-style +- Regexes can be specified as quoted strings +- Header matching (~h, ~hq, ~hs) is against a string of the form "name: value". +- Strings with no operators are matched against the request URL. +- The default binary operator is &. + +Examples +-------- + +URL containing "google.com": + +.. code-block:: none + + google\.com + +Requests whose body contains the string "test": + +.. code-block:: none + + ~q ~b test + +Anything but requests with a text/html content type: + +.. code-block:: none + + !(~q & ~t "text/html") + diff --git a/docs/features/passthrough.rst b/docs/features/passthrough.rst new file mode 100644 index 00000000..80521393 --- /dev/null +++ b/docs/features/passthrough.rst @@ -0,0 +1,97 @@ +.. _passthrough: + +Ignore Domains +============== + +There are two main reasons why you may want to exempt some traffic from mitmproxy's interception +mechanism: + +- **Certificate pinning:** Some traffic is is protected using `Certificate Pinning`_ and + mitmproxy's interception leads to errors. For example, the Twitter app, Windows Update or + the Apple App Store fail to work if mitmproxy is active. +- **Convenience:** You really don't care about some parts of the traffic and just want them to go + away. + +If you want to peek into (SSL-protected) non-HTTP connections, check out the :ref:`tcpproxy` +feature. +If you want to ignore traffic from mitmproxy's processing because of large response bodies, +take a look at the :ref:`responsestreaming` feature. + +How it works +------------ + +================== ============================= +command-line :option:`--ignore regex` +mitmproxy shortcut :kbd:`o` then :kbd:`I` +================== ============================= + + +mitmproxy allows you to specify a regex which is matched against a ``host:port`` string +(e.g. "example.com:443") to determine hosts that should be excluded. + +There are two important quirks to consider: + +- **In transparent mode, the ignore pattern is matched against the IP.** While we usually infer the + hostname from the Host header if the :option:`--host` argument is passed to mitmproxy, we do not + have access to this information before the SSL handshake. +- In regular mode, explicit HTTP requests are never ignored. [#explicithttp]_ The ignore pattern is + applied on CONNECT requests, which initiate HTTPS or clear-text WebSocket connections. + +Tutorial +-------- + +If you just want to ignore one specific domain, there's usually a bulletproof method to do so: + +1. Run mitmproxy or mitmdump in verbose mode (:option:`-v`) and observe the ``host:port`` + information in the serverconnect messages. mitmproxy will filter on these. +2. Take the ``host:port`` string, surround it with ^ and $, escape all dots (. becomes \\.) + and use this as your ignore pattern: + +.. code-block:: none + :emphasize-lines: 6,7,9 + + >>> mitmdump -v + 127.0.0.1:50588: clientconnect + 127.0.0.1:50588: request + -> CONNECT example.com:443 HTTP/1.1 + 127.0.0.1:50588: Set new server address: example.com:443 + 127.0.0.1:50588: serverconnect + -> example.com:443 + ^C + >>> mitmproxy --ignore ^example\.com:443$ + + +Here are some other examples for ignore patterns: + +.. code-block:: none + + # Exempt traffic from the iOS App Store (the regex is lax, but usually just works): + --ignore apple.com:443 + # "Correct" version without false-positives: + --ignore '^(.+\.)?apple\.com:443$' + + # Ignore example.com, but not its subdomains: + --ignore '^example.com:' + + # Ignore everything but example.com and mitmproxy.org: + --ignore '^(?!example\.com)(?!mitmproxy\.org)' + + # Transparent mode: + --ignore 17\.178\.96\.59:443 + # IP address range: + --ignore 17\.178\.\d+\.\d+:443 + + +.. seealso:: + + - :ref:`tcpproxy` + - :ref:`responsestreaming` + +.. rubric:: Footnotes + +.. [#explicithttp] This stems from an limitation of explicit HTTP proxying: + A single connection can be re-used for multiple target domains - a + ``GET http://example.com/`` request may be followed by a ``GET http://evil.com/`` request on the + same connection. If we start to ignore the connection after the first request, + we would miss the relevant second one. +.. _Certificate Pinning: https://security.stackexchange.com/questions/29988/what-is-certificate-pinning diff --git a/docs/features/proxyauth.rst b/docs/features/proxyauth.rst new file mode 100644 index 00000000..bfd32fbd --- /dev/null +++ b/docs/features/proxyauth.rst @@ -0,0 +1,17 @@ +.. _proxyauth: + +Proxy Authentication +==================== + + +Asks the user for authentication before they are permitted to use the proxy. +Authentication headers are stripped from the flows, so they are not passed to +upstream servers. For now, only HTTP Basic authentication is supported. The +proxy auth options are not compatible with the transparent, socks or reverse proxy +mode. + +================== ============================= +command-line :option:`--nonanonymous`, + :option:`--singleuser USER`, + :option:`--htpasswd PATH` +================== ============================= diff --git a/docs/features/replacements.rst b/docs/features/replacements.rst new file mode 100644 index 00000000..8f760866 --- /dev/null +++ b/docs/features/replacements.rst @@ -0,0 +1,72 @@ +.. _replacements: + +Replacements +============ + +Mitmproxy lets you specify an arbitrary number of patterns that define text +replacements within flows. Each pattern has 3 components: a filter that defines +which flows a replacement applies to, a regular expression that defines what +gets replaced, and a target value that defines what is substituted in. + +Replace hooks fire when either a client request or a server response is +received. Only the matching flow component is affected: so, for example, if a +replace hook is triggered on server response, the replacement is only run on +the Response object leaving the Request intact. You control whether the hook +triggers on the request, response or both using the filter pattern. If you need +finer-grained control than this, it's simple to create a script using the +replacement API on Flow components. + +Replacement hooks are extremely handy in interactive testing of applications. +For instance you can use a replace hook to replace the text "XSS" with a +complicated XSS exploit, and then "inject" the exploit simply by interacting +with the application through the browser. When used with tools like Firebug and +mitmproxy's own interception abilities, replacement hooks can be an amazingly +flexible and powerful feature. + + +On the command-line +------------------- + +The replacement hook command-line options use a compact syntax to make it easy +to specify all three components at once. The general form is as follows: + +.. code-block:: none + + /patt/regex/replacement + +Here, **patt** is a mitmproxy filter expression, **regex** is a valid Python +regular expression, and **replacement** is a string literal. The first +character in the expression (``/`` in this case) defines what the separation +character is. Here's an example of a valid expression that replaces "foo" with +"bar" in all requests: + +.. code-block:: none + + :~q:foo:bar + +In practice, it's pretty common for the replacement literal to be long and +complex. For instance, it might be an XSS exploit that weighs in at hundreds or +thousands of characters. To cope with this, there's a variation of the +replacement hook specifier that lets you load the replacement text from a file. +So, you might start **mitmdump** as follows: + +>>> mitmdump --replace-from-file :~q:foo:~/xss-exploit + +This will load the replacement text from the file ``~/xss-exploit``. + +Both the :option:`--replace` and :option:`--replace-from-file` flags can be passed multiple +times. + + +Interactively +------------- + +The :kbd:`R` shortcut key in the mitmproxy options menu (:kbd:`o`) lets you add and edit +replacement hooks using a built-in editor. The context-sensitive help (:kbd:`?`) has +complete usage information. + +================== ============================= +command-line :option:`--replace`, + :option:`--replace-from-file` +mitmproxy shortcut :kbd:`o` then :kbd:`R` +================== ============================= diff --git a/docs/features/responsestreaming.rst b/docs/features/responsestreaming.rst new file mode 100644 index 00000000..af3d889a --- /dev/null +++ b/docs/features/responsestreaming.rst @@ -0,0 +1,69 @@ +.. _responsestreaming: + +Response Streaming +================== + +By using mitmproxy's streaming feature, response contents can be passed to the client incrementally +before they have been fully received by the proxy. This is especially useful for large binary files +such as videos, where buffering the whole file slows down the client's browser. + +By default, mitmproxy will read the entire response, perform any indicated +manipulations on it and then send the (possibly modified) response to +the client. In some cases this is undesirable and you may wish to "stream" +the reponse back to the client. When streaming is enabled, the response is +not buffered on the proxy but directly sent back to the client instead. + +On the command-line +------------------- + +Streaming can be enabled on the command line for all response bodies exceeding a certain size. +The SIZE argument understands k/m/g suffixes, e.g. 3m for 3 megabytes. + +================== ============================= +command-line :option:`--stream SIZE` +================== ============================= + +.. warning:: + + When response streaming is enabled, **streamed response contents will not be + recorded or preserved in any way.** + +.. note:: + + When response streaming is enabled, the response body cannot be modified by the usual means. + +Customizing Response Streaming +------------------------------ + +You can also use an :ref:`inlinescripts` to customize exactly +which responses are streamed. + +Responses that should be tagged for streaming by setting their ``.stream`` attribute to ``True``: + +.. literalinclude:: ../../examples/stream.py + :caption: examples/stream.py + :language: python + +Implementation Details +---------------------- + +When response streaming is enabled, portions of the code which would have otherwise performed +changes on the response body will see an empty response body instead +(:py:data:`netlib.http.CONTENT_MISSING`). Any modifications will be ignored. + +Streamed responses are usually sent in chunks of 4096 bytes. If the response is sent with a +``Transfer-Encoding: chunked`` header, the response will be streamed one chunk at a time. + +Modifying streamed data +----------------------- + +If the ``.stream`` attribute is callable, ``.stream`` will wrap the generator that yields all +chunks. + +.. literalinclude:: ../../examples/stream_modify.py + :caption: examples/stream_modify.py + :language: python + +.. seealso:: + + - :ref:`passthrough` diff --git a/docs/features/reverseproxy.rst b/docs/features/reverseproxy.rst new file mode 100644 index 00000000..77e9327c --- /dev/null +++ b/docs/features/reverseproxy.rst @@ -0,0 +1,57 @@ +.. _reverseproxy: + +Reverse Proxy +============= + +In reverse proxy mode, mitmproxy accepts standard HTTP requests and forwards +them to the specified upstream server. This is in contrast to :ref:`upstreamproxy`, in which +mitmproxy forwards HTTP proxy requests to an upstream proxy server. + +================== ===================================== +command-line :option:`-R http[s]://hostname[:port]` +================== ===================================== + +Here, **scheme** signifies if the proxy should use TLS to connect to the server. +mitmproxy always accepts both encrypted and unencrypted requests and transforms +them to what the server expects. + +.. code-block:: none + + >>> mitmdump -R https://httpbin.org -p 80 + >>> curl http://localhost/ + # requests will be transparently upgraded to TLS by mitmproxy + + >>> mitmdump -R https://httpbin.org -p 443 + >>> curl https://localhost/ + # mitmproxy will use TLS on both ends. + + +Host Header +----------- + +In reverse proxy mode, mitmproxy does not rewrite the host header. While often useful, this +may lead to issues with public web servers. For example, consider the following scenario: + +.. code-block:: none + :emphasize-lines: 5 + + >>> mitmdump -d -R http://example.com/ + >>> curl http://localhost:8080/ + + >> GET https://example.com/ + Host: localhost:8080 + User-Agent: curl/7.35.0 + [...] + + << 404 Not Found 345B + +Since the Host header doesn't match "example.com", an error is returned. +There are two ways to solve this: + +1. Modify the hosts file of your OS so that "example.com" resolves to your proxy's IP. + Then, access example.com directly. Make sure that your proxy can still resolve the original IP + or specify an IP in mitmproxy. +2. Use mitmproxy's :ref:`setheaders` feature to rewrite the host header: + ``--setheader :~q:Host:example.com``. + However, keep in mind that absolute URLs within the returned document or HTTP redirects will + cause the client application to bypass the proxy. diff --git a/docs/features/serverreplay.rst b/docs/features/serverreplay.rst new file mode 100644 index 00000000..261a1bd6 --- /dev/null +++ b/docs/features/serverreplay.rst @@ -0,0 +1,39 @@ +.. _serverreplay: + +Server-side replay +================== + +Server-side replay lets us replay server responses from a saved HTTP +conversation. + +Matching requests with responses +-------------------------------- + +By default, :program:`mitmproxy` excludes request headers when matching incoming +requests with responses from the replay file. This works in most circumstances, +and makes it possible to replay server responses in situations where request +headers would naturally vary, e.g. using a different user agent. +The :option:`--rheader headername` command-line option allows you to override +this behaviour by specifying individual headers that should be included in matching. + + +Response refreshing +------------------- + +Simply replaying server responses without modification will often result in +unexpected behaviour. For example cookie timeouts that were in the future at +the time a conversation was recorded might be in the past at the time it is +replayed. By default, :program:`mitmproxy` refreshes server responses before sending +them to the client. The **date**, **expires** and **last-modified** headers are +all updated to have the same relative time offset as they had at the time of +recording. So, if they were in the past at the time of recording, they will be +in the past at the time of replay, and vice versa. Cookie expiry times are +updated in a similar way. + +You can turn off response refreshing using the :option:`--norefresh` argument, or using +the :kbd:`o` options shortcut within :program:`mitmproxy`. + +================== ================= +command-line :option:`-S path` +mitmproxy shortcut :kbd:`S` +================== ================= diff --git a/docs/features/setheaders.rst b/docs/features/setheaders.rst new file mode 100644 index 00000000..cbc8b6a5 --- /dev/null +++ b/docs/features/setheaders.rst @@ -0,0 +1,19 @@ +.. _setheaders: + +Set Headers +=========== + +This feature lets you specify a set of headers to be added to requests or +responses, based on a filter pattern. You can specify these either on the +command-line, or through an interactive editor in mitmproxy. + +Example: Set the **Host** header to "example.com" for all requests. + +.. code-block:: none + + mitmdump -R http://example.com --setheader :~q:Host:example.com + +================== ============================= +command-line :option:`--setheader PATTERN` +mitmproxy shortcut :kbd:`o` then :kbd:`H` +================== ============================= diff --git a/docs/features/socksproxy.rst b/docs/features/socksproxy.rst new file mode 100644 index 00000000..76d4cda9 --- /dev/null +++ b/docs/features/socksproxy.rst @@ -0,0 +1,10 @@ +.. _socksproxy: + +SOCKS Mode +========== + +In this mode, mitmproxy acts as a SOCKS5 proxy server. + +================== ================= +command-line :option:`--socks` +================== ================= diff --git a/docs/features/sticky.rst b/docs/features/sticky.rst new file mode 100644 index 00000000..a79cbe8d --- /dev/null +++ b/docs/features/sticky.rst @@ -0,0 +1,41 @@ +.. _sticky: + +Sticky cookies and auth +======================= + +Sticky cookies +-------------- + +When the sticky cookie option is set, __mitmproxy__ will add the cookie most +recently set by the server to any cookie-less request. Consider a service that +sets a cookie to track the session after authentication. Using sticky cookies, +you can fire up mitmproxy, and authenticate to a service as you usually would +using a browser. After authentication, you can request authenticated resources +through mitmproxy as if they were unauthenticated, because mitmproxy will +automatically add the session tracking cookie to requests. Among other things, +this lets you script interactions with authenticated resources (using tools +like wget or curl) without having to worry about authentication. + +Sticky cookies are especially powerful when used in conjunction with :ref:`clientreplay` - you can +record the authentication process once, and simply replay it on startup every time you need +to interact with the secured resources. + +================== ====================== +command-line :option:`-t FILTER` +mitmproxy shortcut :kbd:`o` then :kbd:`t` +================== ====================== + + +Sticky auth +----------- + +The sticky auth option is analogous to the sticky cookie option, in that HTTP +**Authorization** headers are simply replayed to the server once they have been +seen. This is enough to allow you to access a server resource using HTTP Basic +authentication through the proxy. Note that :program:`mitmproxy` doesn't (yet) support +replay of HTTP Digest authentication. + +================== ====================== +command-line :option:`-u FILTER` +mitmproxy shortcut :kbd:`o` then :kbd:`A` +================== ====================== diff --git a/docs/features/tcpproxy.rst b/docs/features/tcpproxy.rst new file mode 100644 index 00000000..fd0746a2 --- /dev/null +++ b/docs/features/tcpproxy.rst @@ -0,0 +1,31 @@ +.. _tcpproxy: + +TCP Proxy +========= + +WebSockets or other non-HTTP protocols are not supported by mitmproxy yet. However, you can exempt +hostnames from processing, so that mitmproxy acts as a generic TCP forwarder. +This feature is closely related to the :ref:`passthrough` functionality, +but differs in two important aspects: + +- The raw TCP messages are printed to the event log. +- SSL connections will be intercepted. + +Please note that message interception or modification are not possible yet. +If you are not interested in the raw TCP messages, you should use the ignore domains feature. + +How it works +------------ + +================== ====================== +command-line :option:`--tcp HOST` +mitmproxy shortcut :kbd:`o` then :kbd:`T` +================== ====================== + +For a detailed description how the hostname pattern works, please look at the :ref:`passthrough` +feature. + +.. seealso:: + + - :ref:`passthrough` + - :ref:`responsestreaming` diff --git a/docs/features/upstreamcerts.rst b/docs/features/upstreamcerts.rst new file mode 100644 index 00000000..c687aec7 --- /dev/null +++ b/docs/features/upstreamcerts.rst @@ -0,0 +1,23 @@ +.. _upstreamcerts: + +Upstream Certificates +===================== + +When mitmproxy receives a connection destined for an SSL-protected service, it +freezes the connection before reading its request data, and makes a connection +to the upstream server to "sniff" the contents of its SSL certificate. The +information gained - the **Common Name** and **Subject Alternative Names** - is +then used to generate the interception certificate, which is sent to the client +so the connection can continue. + +This rather intricate little dance lets us seamlessly generate correct +certificates even if the client has specifed only an IP address rather than the +hostname. It also means that we don't need to sniff additional data to generate +certs in transparent mode. + +Upstream cert sniffing is on by default, and can optionally be turned off. + +================== ============================= +command-line :option:`--no-upstream-cert` +mitmproxy shortcut :kbd:`o` then :kbd:`U` +================== ============================= diff --git a/docs/features/upstreamproxy.rst b/docs/features/upstreamproxy.rst new file mode 100644 index 00000000..e06833c2 --- /dev/null +++ b/docs/features/upstreamproxy.rst @@ -0,0 +1,12 @@ +.. _upstreamproxy: + +Upstream proxy mode +=================== + +In this mode, mitmproxy accepts proxy requests and unconditionally forwards all +requests to a specified upstream proxy server. This is in contrast to :ref:`reverseproxy`, +in which mitmproxy forwards ordinary HTTP requests to an upstream server. + +================== =================================== +command-line :option:`-U http://hostname[:port]` +================== =================================== diff --git a/docs/howmitmproxy.rst b/docs/howmitmproxy.rst new file mode 100644 index 00000000..7dcb4c30 --- /dev/null +++ b/docs/howmitmproxy.rst @@ -0,0 +1,239 @@ +How mitmproxy works +=================== + +Mitmproxy is an enormously flexible tool. Knowing exactly how the proxying +process works will help you deploy it creatively, and take into account its +fundamental assumptions and how to work around them. This document explains +mitmproxy's proxy mechanism in detail, starting with the simplest unencrypted +explicit proxying, and working up to the most complicated interaction - +transparent proxying of SSL-protected traffic [#ssl]_ in the presence of `Server Name Indication`_. + +Explicit HTTP +------------- + +Configuring the client to use mitmproxy as an explicit proxy is the simplest +and most reliable way to intercept traffic. The proxy protocol is codified in the +`HTTP RFC`_, so the behaviour of both +the client and the server is well defined, and usually reliable. In the +simplest possible interaction with mitmproxy, a client connects directly to the +proxy, and makes a request that looks like this: + +.. code-block:: http + + GET http://example.com/index.html HTTP/1.1 + +This is a proxy GET request - an extended form of the vanilla HTTP GET request +that includes a schema and host specification, and it includes all the +information mitmproxy needs to proceed. + +.. image:: schematics/how-mitmproxy-works-explicit.png + :align: center + +1. The client connects to the proxy and makes a request. +2. Mitmproxy connects to the upstream server and simply forwards the request on. + + +Explicit HTTPS +-------------- + +The process for an explicitly proxied HTTPS connection is quite different. The +client connects to the proxy and makes a request that looks like this: + +.. code-block:: http + + CONNECT example.com:443 HTTP/1.1 + +A conventional proxy can neither view nor manipulate an SSL-encrypted data +stream, so a CONNECT request simply asks the proxy to open a pipe between the +client and server. The proxy here is just a facilitator - it blindly forwards +data in both directions without knowing anything about the contents. The +negotiation of the SSL connection happens over this pipe, and the subsequent +flow of requests and responses are completely opaque to the proxy. + +The MITM in mitmproxy +^^^^^^^^^^^^^^^^^^^^^ + +This is where mitmproxy's fundamental trick comes into play. The MITM in its +name stands for Man-In-The-Middle - a reference to the process we use to +intercept and interfere with these theoretically opaque data streams. The basic +idea is to pretend to be the server to the client, and pretend to be the client +to the server, while we sit in the middle decoding traffic from both sides. The +tricky part is that the `Certificate Authority`_ system is +designed to prevent exactly this attack, by allowing a trusted third-party to +cryptographically sign a server's SSL certificates to verify that they are +legit. If this signature doesn't match or is from a non-trusted party, a secure +client will simply drop the connection and refuse to proceed. Despite the many +shortcomings of the CA system as it exists today, this is usually fatal to +attempts to MITM an SSL connection for analysis. Our answer to this conundrum +is to become a trusted Certificate Authority ourselves. Mitmproxy includes a +full CA implementation that generates interception certificates on the fly. To +get the client to trust these certificates, we :ref:`register mitmproxy as a trusted +CA with the device manually <certinstall>`. + +Complication 1: What's the remote hostname? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To proceed with this plan, we need to know the domain name to use in the +interception certificate - the client will verify that the certificate is for +the domain it's connecting to, and abort if this is not the case. At first +blush, it seems that the CONNECT request above gives us all we need - in this +example, both of these values are "example.com". But what if the client had +initiated the connection as follows: + +.. code-block:: http + + CONNECT 10.1.1.1:443 HTTP/1.1 + +Using the IP address is perfectly legitimate because it gives us enough +information to initiate the pipe, even though it doesn't reveal the remote +hostname. + +Mitmproxy has a cunning mechanism that smooths this over - :ref:`upstream +certificate sniffing <upstreamcerts>`. As soon as we +see the CONNECT request, we pause the client part of the conversation, and +initiate a simultaneous connection to the server. We complete the SSL handshake +with the server, and inspect the certificates it used. Now, we use the Common +Name in the upstream SSL certificates to generate the dummy certificate for the +client. Voila, we have the correct hostname to present to the client, even if +it was never specified. + + +Complication 2: Subject Alternative Name +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Enter the next complication. Sometimes, the certificate Common Name is not, in +fact, the hostname that the client is connecting to. This is because of the +optional `Subject Alternative Name`_ field in the SSL certificate +that allows an arbitrary number of alternative domains to be specified. If the +expected domain matches any of these, the client will proceed, even though the +domain doesn't match the certificate Common Name. The answer here is simple: +when we extract the CN from the upstream cert, we also extract the SANs, and +add them to the generated dummy certificate. + + +Complication 3: Server Name Indication +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +One of the big limitations of vanilla SSL is that each certificate requires its +own IP address. This means that you couldn't do virtual hosting where multiple +domains with independent certificates share the same IP address. In a world +with a rapidly shrinking IPv4 address pool this is a problem, and we have a +solution in the form of the `Server Name Indication`_ extension to +the SSL and TLS protocols. This lets the client specify the remote server name +at the start of the SSL handshake, which then lets the server select the right +certificate to complete the process. + +SNI breaks our upstream certificate sniffing process, because when we connect +without using SNI, we get served a default certificate that may have nothing to +do with the certificate expected by the client. The solution is another tricky +complication to the client connection process. After the client connects, we +allow the SSL handshake to continue until just _after_ the SNI value has been +passed to us. Now we can pause the conversation, and initiate an upstream +connection using the correct SNI value, which then serves us the correct +upstream certificate, from which we can extract the expected CN and SANs. + +Putting it all together +^^^^^^^^^^^^^^^^^^^^^^^ + +Lets put all of this together into the complete explicitly proxied HTTPS flow. + +.. image:: schematics/how-mitmproxy-works-explicit-https.png + :align: center + +1. The client makes a connection to mitmproxy, and issues an HTTP CONNECT request. +2. Mitmproxy responds with a ``200 Connection Established``, as if it has set up the CONNECT pipe. +3. The client believes it's talking to the remote server, and initiates the SSL connection. + It uses SNI to indicate the hostname it is connecting to. +4. Mitmproxy connects to the server, and establishes an SSL connection using the SNI hostname + indicated by the client. +5. The server responds with the matching SSL certificate, which contains the CN and SAN values + needed to generate the interception certificate. +6. Mitmproxy generates the interception cert, and continues the + client SSL handshake paused in step 3. +7. The client sends the request over the established SSL connection. +8. Mitmproxy passes the request on to the server over the SSL connection initiated in step 4. + +Transparent HTTP +---------------- + +When a transparent proxy is used, the HTTP/S connection is redirected into a +proxy at the network layer, without any client configuration being required. +This makes transparent proxying ideal for those situations where you can't +change client behaviour - proxy-oblivious Android applications being a common +example. + +To achieve this, we need to introduce two extra components. The first is a +redirection mechanism that transparently reroutes a TCP connection destined for +a server on the Internet to a listening proxy server. This usually takes the +form of a firewall on the same host as the proxy server - `iptables`_ on Linux or +pf_ on OSX. Once the client has initiated the connection, it makes a vanilla HTTP request, +which might look something like this: + +.. code-block:: http + + GET /index.html HTTP/1.1 + +Note that this request differs from the explicit proxy variation, in that it +omits the scheme and hostname. How, then, do we know which upstream host to +forward the request to? The routing mechanism that has performed the +redirection keeps track of the original destination for us. Each routing +mechanism has a different way of exposing this data, so this introduces the +second component required for working transparent proxying: a host module that +knows how to retrieve the original destination address from the router. In +mitmproxy, this takes the form of a built-in set of +modules_ that know how to talk to each platform's redirection mechanism. +Once we have this information, the process is fairly straight-forward. + +.. image:: schematics/how-mitmproxy-works-transparent.png + :align: center + +1. The client makes a connection to the server. +2. The router redirects the connection to mitmproxy, which is typically listening on a local port + of the same host. Mitmproxy then consults the routing mechanism to establish what the original + destination was. +3. Now, we simply read the client's request... +4. ... and forward it upstream. + +Transparent HTTPS +----------------- + +The first step is to determine whether we should treat an incoming connection +as HTTPS. The mechanism for doing this is simple - we use the routing mechanism +to find out what the original destination port is. By default, we treat all +traffic destined for ports 443 and 8443 as SSL. + +From here, the process is a merger of the methods we've described for +transparently proxying HTTP, and explicitly proxying HTTPS. We use the routing +mechanism to establish the upstream server address, and then proceed as for +explicit HTTPS connections to establish the CN and SANs, and cope with SNI. + +.. image:: schematics/how-mitmproxy-works-transparent-https.png + :align: center + +1. The client makes a connection to the server. +2. The router redirects the connection to mitmproxy, which is typically listening on a local port + of the same host. Mitmproxy then consults the routing mechanism to establish what the original + destination was. +3. The client believes it's talking to the remote server, and initiates the SSL connection. + It uses SNI to indicate the hostname it is connecting to. +4. Mitmproxy connects to the server, and establishes an SSL connection using the SNI hostname + indicated by the client. +5. The server responds with the matching SSL certificate, which contains the CN and SAN values + needed to generate the interception certificate. +6. Mitmproxy generates the interception cert, and continues the client SSL handshake paused in + step 3. +7. The client sends the request over the established SSL connection. +8. Mitmproxy passes the request on to the server over the SSL connection initiated in step 4. + +.. rubric:: Footnotes + +.. [#ssl] I use "SSL" to refer to both SSL and TLS in the generic sense, unless otherwise + specified. + +.. _Server Name Indication: https://en.wikipedia.org/wiki/Server_Name_Indication +.. _HTTP RFC: https://tools.ietf.org/html/rfc7230 +.. _Certificate Authority: https://en.wikipedia.org/wiki/Certificate_authority +.. _Subject Alternative Name: https://en.wikipedia.org/wiki/SubjectAltName +.. _iptables: http://www.netfilter.org/ +.. _pf: https://en.wikipedia.org/wiki/PF_\(firewall\) +.. _modules: https://github.com/mitmproxy/mitmproxy/tree/master/libmproxy/platform diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..30fb4027 --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,83 @@ +.. include:: introduction.rst + + +.. toctree:: + :hidden: + :maxdepth: 1 + + introduction + install + certinstall + howmitmproxy + modes + +.. toctree:: + :hidden: + :caption: Tools + + mitmproxy + mitmdump + config + +.. toctree:: + :hidden: + :caption: Features + + features/anticache + features/filters + features/replacements + features/clientreplay + features/serverreplay + features/setheaders + features/passthrough + features/proxyauth + features/reverseproxy + features/responsestreaming + features/socksproxy + features/sticky + features/tcpproxy + features/upstreamproxy + features/upstreamcerts + +.. toctree:: + :hidden: + :caption: Transparent Proxying + + transparent + transparent/linux + transparent/osx + +.. toctree:: + :hidden: + :caption: Scripting + + scripting/inlinescripts + scripting/libmproxy + + +.. toctree:: + :hidden: + :caption: Tutorials + + tutorials/30second + tutorials/gamecenter + tutorials/transparent-dhcp + +.. toctree:: + :hidden: + :caption: Hacking + + dev/architecture + dev/testing + dev/sslkeylogfile + dev/protocols + dev/proxy + dev/exceptions + dev/models + +.. Indices and tables + ================== + + * :ref:`genindex` + * :ref:`modindex` + diff --git a/docs/install.rst b/docs/install.rst new file mode 100644 index 00000000..b3afa6d0 --- /dev/null +++ b/docs/install.rst @@ -0,0 +1,100 @@ +.. _install: + +Installation +============ + +.. _install-ubuntu: + +Installation On Ubuntu +---------------------- + +Ubuntu comes with Python but we need to install pip, python-dev and several libraries. +This was tested on a fully patched installation of Ubuntu 14.04. + +>>> sudo apt-get install python-pip python-dev libffi-dev libssl-dev libxml2-dev libxslt1-dev +>>> sudo pip install mitmproxy + +Once installation is complete you can run :ref:`mitmproxy` or :ref:`mitmdump` from a terminal. + +Installation From Source (Ubuntu) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you would like to install mitmproxy directly from the master branch on GitHub or would like to +get set up to contribute to the project, install the dependencies as you would for a regular +mitmproxy installation (see :ref:`install-ubuntu`). +Then see the Hacking_ section of the README on GitHub. + + + +Installation On Mac OS X +------------------------ + +The easiest way to get up and running on OSX is to download the pre-built binary packages from +`mitmproxy.org`_. + +There are a few bits of customization you might want to do to make mitmproxy comfortable to use on +OSX. The default color scheme is optimized for a dark background terminal, but you can select a +palette for a light terminal background with the ``--palette`` option. +You can use the OSX **open** program to create a simple and effective ``~/.mailcap`` file to view +request and response bodies: + +.. code-block:: none + + application/*; /usr/bin/open -Wn %s + audio/*; /usr/bin/open -Wn %s + image/*; /usr/bin/open -Wn %s + video/*; /usr/bin/open -Wn %s + +Once installation is complete you can run :ref:`mitmproxy` or :ref:`mitmdump` from a terminal. + + +Installation From Source (Mac OS X) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you would like to install mitmproxy directly from the master branch on GitHub or would like to +get set up to contribute to the project, there are a few OS X specific things to keep in mind. + +- Make sure that XCode is installed from the App Store, and that the command-line tools have been + downloaded (XCode/Preferences/Downloads). +- If you're running a Python interpreter installed with homebrew (or similar), you may have to + install some dependencies by hand. + +Then see the Hacking_ section of the README on GitHub. + +Installation On Windows +----------------------- + +.. note:: + Please note that mitmdump is the only component of mitmproxy that is supported on Windows at + the moment. + + **There is no interactive user interface on Windows.** + + +First, install the latest version of Python 2.7 from the `Python website`_. +If you already have an older version of Python 2.7 installed, make sure to install pip_ +(pip is included in Python 2.7.9+ by default). + +Next, add Python and the Python Scripts directory to your **PATH** variable. +You can do this easily by running the following in powershell: + +>>> [Environment]::SetEnvironmentVariable("Path", "$env:Path;C:\Python27;C:\Python27\Scripts", "User") + +Now, you can install mitmproxy by running + +>>> pip install mitmproxy + +Once the installation is complete, you can run :ref:`mitmdump` from a command prompt. + +Installation From Source (Windows) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you would like to install mitmproxy directly from the master branch on GitHub or would like to +get set up to contribute to the project, install Python as outlined above, then see the +Hacking_ section of the README on GitHub. + + +.. _Hacking: https://github.com/mitmproxy/mitmproxy/blob/master/README.mkd#hacking +.. _mitmproxy.org: https://mitmproxy.org/ +.. _`Python website`: https://www.python.org/downloads/windows/ +.. _pip: https://pip.pypa.io/en/latest/installing.html diff --git a/docs/introduction.rst b/docs/introduction.rst new file mode 100644 index 00000000..c8593daf --- /dev/null +++ b/docs/introduction.rst @@ -0,0 +1,26 @@ +Introduction +============ + +**mitmproxy** is an interactive, SSL-capable man-in-the-middle proxy for HTTP +with a console interface. + +**mitmdump** is the command-line version of mitmproxy. Think tcpdump for HTTP. + +**libmproxy** is the library that mitmproxy and mitmdump are built on. + +Documentation, tutorials and distribution packages can be found on the +mitmproxy website: `mitmproxy.org <https://mitmproxy.org/>`_ + + +.. rubric:: Features + + +- Intercept HTTP requests and responses and modify them on the fly. +- Save complete HTTP conversations for later replay and analysis. +- Replay the client-side of an HTTP conversations. +- Replay HTTP responses of a previously recorded server. +- Reverse proxy mode to forward traffic to a specified server. +- Transparent proxy mode on OSX and Linux. +- Make scripted changes to HTTP traffic using Python. +- SSL certificates for interception are generated on the fly. +- And much, much more. diff --git a/docs/mitmdump.rst b/docs/mitmdump.rst new file mode 100644 index 00000000..d9b4a26b --- /dev/null +++ b/docs/mitmdump.rst @@ -0,0 +1,66 @@ +.. _mitmdump: +.. program:: mitmdump + +mitmdump +======== + + +**mitmdump** is the command-line companion to mitmproxy. It provides +tcpdump-like functionality to let you view, record, and programmatically +transform HTTP traffic. See the :option:`--help` flag output for complete +documentation. + + + +Examples +-------- + +Saving traffic +^^^^^^^^^^^^^^ + +>>> mitmdump -w outfile + +Start up mitmdump in proxy mode, and write all traffic to **outfile**. + + +Filtering saved traffic +^^^^^^^^^^^^^^^^^^^^^^^ + +>>> mitmdump -nr infile -w outfile "~m post" + +Start mitmdump without binding to the proxy port (:option:`-n`), read all flows from +infile, apply the specified filter expression (only match POSTs), and write to +outfile. + + +Client replay +^^^^^^^^^^^^^ + +>>> mitmdump -nc outfile + +Start mitmdump without binding to the proxy port (:option:`-n`), then replay all +requests from outfile (:option:`-c filename`). Flags combine in the obvious way, so +you can replay requests from one file, and write the resulting flows to +another: + +>>> mitmdump -nc srcfile -w dstfile + +See the :ref:`clientreplay` section for more information. + + +Running a script +^^^^^^^^^^^^^^^^ + +>>> mitmdump -s examples/add_header.py + +This runs the **add_header.py** example script, which simply adds a new header +to all responses. + +Scripted data transformation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +>>> mitmdump -ns examples/add_header.py -r srcfile -w dstfile + +This command loads flows from **srcfile**, transforms it according to the +specified script, then writes it back to **dstfile**. + diff --git a/docs/mitmproxy-long.png b/docs/mitmproxy-long.png Binary files differnew file mode 100644 index 00000000..f9397d1e --- /dev/null +++ b/docs/mitmproxy-long.png diff --git a/docs/mitmproxy.rst b/docs/mitmproxy.rst new file mode 100644 index 00000000..fa3b57c7 --- /dev/null +++ b/docs/mitmproxy.rst @@ -0,0 +1,126 @@ +.. _mitmproxy: +.. program:: mitmproxy + +mitmproxy +========= + + +**mitmproxy** is a console tool that allows interactive examination and +modification of HTTP traffic. It differs from mitmdump in that all flows are +kept in memory, which means that it's intended for taking and manipulating +small-ish samples. Use the :kbd:`?` shortcut key to view, context-sensitive +documentation from any **mitmproxy** screen. + +Flow list +--------- + +The flow list shows an index of captured flows in chronological order. + +.. image:: screenshots/mitmproxy.png + +- **1**: A GET request, returning a 302 Redirect response. +- **2**: A GET request, returning 16.75kb of text/html data. +- **3**: A replayed request. +- **4**: Intercepted flows are indicated with orange text. The user may edit + these flows, and then accept them (using the :kbd:`a` key) to continue. In this + case, the request has been intercepted on the way to the server. +- **5**: A response intercepted from the server on the way to the client. +- **6**: The event log can be toggled on and off using the :kbd:`e` shortcut key. This + pane shows events and errors that may not result in a flow that shows up in the + flow pane. +- **7**: Flow count. +- **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. + + +Flow view +--------- + +The **Flow View** lets you inspect and manipulate a single flow: + +.. image:: 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 :kbd:`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 :kbd:`m` key. + + +Grid Editor +----------- + +Much of the data that we'd like to interact with in mitmproxy is structured. +For instance, headers, queries and form data can all be thought of as a list of +key/value pairs. Mitmproxy has a built-in editor that lays this type of data +out in a grid for easy manipulation. + +At the moment, the Grid Editor is used in four parts of mitmproxy: + + - Editing request or response headers (:kbd:`e` for edit, then :kbd:`h` for headers in flow view) + - Editing a query string (:kbd:`e` for edit, then :kbd:`q` for query in flow view) + - Editing a URL-encoded form (:kbd:`e` for edit, then :kbd:`f` for form in flow view) + - Editing replacement patterns (:kbd:`o` for options, then :kbd:`R` for Replacement Patterns) + +If there is is no data, an empty editor will be started to let you add some. +Here is the editor showing the headers from a request: + +.. image:: 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: + +.. image:: screenshots/mitmproxy-kveditor-editmode.png + +Modify the field as desired, then press escape to exit edit mode when you're +done. You can also add a row (:kbd:`a` key), delete a row (:kbd:`d` key), spawn an +external editor on a field (:kbd:`e` key). Be sure to consult the context-sensitive +help (:kbd:`?` key) for more. + +Example: Interception +--------------------- + +**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 +or client. + + +1: Set an interception pattern +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: screenshots/mitmproxy-intercept-filt.png + +We press :kbd:`i` to set an interception pattern. In this case, the ``~q`` filter +pattern tells **mitmproxy** to intercept all requests. For complete filter +syntax, see the :ref:`filters` section of the documentation, +or the built-in help function in **mitmproxy**. + +2: Intercepted connections are indicated with orange text: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: screenshots/mitmproxy-intercept-mid.png + +3: You can now view and modify the request: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: screenshots/mitmproxy-intercept-options.png + +In this case, we viewed the request by selecting it, pressed :kbd:`e` for "edit" +and :kbd:`m` for "method" to change the HTTP request method. + +4: Accept the intercept to continue: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: screenshots/mitmproxy-intercept-result.png + +Finally, we press :kbd:`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 +OPTIONS, and Google's server has responded with a 405 "Method not allowed". diff --git a/docs/modes.rst b/docs/modes.rst new file mode 100644 index 00000000..2c87b2a3 --- /dev/null +++ b/docs/modes.rst @@ -0,0 +1,193 @@ +.. _modes: + +Modes of Operation +================== + +Mitmproxy has four modes of operation that allow you to use mitmproxy in a +variety of scenarios: + +- **Regular** (the default) +- **Transparent** +- **Reverse Proxy** +- **Upstream Proxy** + + +Now, which one should you pick? Use this flow chart: + +.. image:: schematics/proxy-modes-flowchart.png + :align: center + +Regular Proxy +------------- + +Mitmproxy's regular mode is the simplest and the easiest to set up. + +1. Start mitmproxy. +2. Configure your client to use mitmproxy by explicitly setting an HTTP proxy. +3. Quick Check: You should already be able to visit an unencrypted HTTP site through the proxy. +4. Open the magic domain **mitm.it** and install the certificate for your device. + +.. note:: + Unfortunately, some applications bypass the system HTTP proxy settings - Android applications + are a common example. In these cases, you need to use mitmproxy's transparent mode. + +If you are proxying an external device, your network will probably look like this: + +.. image:: schematics/proxy-modes-regular.png + :align: center + +The square brackets signify the source and destination IP addresses. Your +client explicitly connects to mitmproxy and mitmproxy explicitly connects +to the target server. + +Transparent Proxy +----------------- + +In transparent mode, traffic is directed into a proxy at the network layer, +without any client configuration required. This makes transparent proxying +ideal for situations where you can't change client behaviour. In the graphic +below, a machine running mitmproxy has been inserted between the router and +the internet: + +.. image:: schematics/proxy-modes-transparent-1.png + :align: center + +The square brackets signify the source and destination IP addresses. Round +brackets mark the next hop on the *Ethernet/data link* layer. This distinction +is important: when the packet arrives at the mitmproxy machine, it must still +be addressed to the target server. This means that Network Address Translation +should not be applied before the traffic reaches mitmproxy, since this would +remove the target information, leaving mitmproxy unable to determine the real +destination. + +.. image:: schematics/proxy-modes-transparent-wrong.png + :align: center + +Common Configurations +^^^^^^^^^^^^^^^^^^^^^ + +There are many ways to configure your network for transparent proxying. We'll +look at two common scenarios: + +1. Configuring the client to use a custom gateway/router/"next hop" +2. Implementing custom routing on the router + +In most cases, the first option is recommended due to its ease of use. + +(a) Custom Gateway +~~~~~~~~~~~~~~~~~~ + +One simple way to get traffic to the mitmproxy machine with the destination IP +intact, is to simply configure the client with the mitmproxy box as the +default gateway. + +.. image:: schematics/proxy-modes-transparent-2.png + :align: center + +In this scenario, we would: + +1. Configure the proxy machine for transparent mode. You can find instructions + in the :ref:`transparent` section. +2. Configure the client to use the proxy machine's IP as the default gateway. +3. Quick Check: At this point, you should already be able to visit an + unencrypted HTTP site over the proxy. +4. Open the magic domain **mitm.it** and install the certificate + for your device. + +Setting the custom gateway on clients can be automated by serving the settings +out to clients over DHCP. This lets set up an interception network where all +clients are proxied automatically, which can save time and effort. + +.. admonition:: Troubleshooting Transparent Mode + :class: note + + Incorrect transparent mode configurations are a frequent source of + error. If it doesn't work for you, try the following things: + + - Open mitmproxy's event log (press :kbd:`e`) - do you see clientconnect messages? + If not, the packets are not arriving at the proxy. One common cause is the occurrence of ICMP + redirects, which means that your machine is telling the client that there's a faster way to + the internet by contacting your router directly (see the :ref:`transparent` section on how to + disable them). If in doubt, Wireshark_ may help you to see whether something arrives at your + machine or not. + - Make sure you have not explicitly configured an HTTP proxy on the client. + This is not needed in transparent mode. + - Re-check the instructions in the :ref:`transparent` section. Anything you missed? + + If you encounter any other pitfalls that should be listed here, please let us know! + +(b) Custom Routing +~~~~~~~~~~~~~~~~~~ + +In some cases, you may need more fine-grained control of which traffic reaches +the mitmproxy instance, and which doesn't. You may, for instance, choose only +to divert traffic to some hosts into the transparent proxy. There are a huge +number of ways to accomplish this, and much will depend on the router or +packet filter you're using. In most cases, the configuration will look like +this: + +.. image:: schematics/proxy-modes-transparent-3.png + :align: center + + +Reverse Proxy +------------- + +mitmproxy is usually used with a client that uses the proxy to access the +Internet. Using reverse proxy mode, you can use mitmproxy to act like a normal +HTTP server: + +.. image:: schematics/proxy-modes-reverse.png + :align: center + +There are various use-cases: + +- Say you have an internal API running at http://example.local/. You could now + set up mitmproxy in reverse proxy mode at http://debug.example.local/ and + dynamically point clients to this new API endpoint, which provides them + with the same data and you with debug information. Similarly, you could move + your real server to a different IP/port and set up mitmproxy in the original + place to debug and or redirect all sessions. + +- Say you're a web developer working on http://example.com/ (with a development + version running on http://localhost:8000/). You can modify your hosts file so that + example.com points to 127.0.0.1 and then run mitmproxy in reverse proxy mode + on port 80. You can test your app on the example.com domain and get all + requests recorded in mitmproxy. + +- Say you have some toy project that should get SSL support. Simply set up + mitmproxy as a reverse proxy on port 443 and you're done (``mitmdump -p 443 -R + http://localhost:80/``). Mitmproxy auto-detects TLS traffic and intercepts it dynamically. + There are better tools for this specific task, but mitmproxy is very quick and simple way to + set up an SSL-speaking server. + +- Want to add a non-SSL-capable compression proxy in front of your server? You + could even spawn a mitmproxy instance that terminates SSL (``-R http://...``), + point it to the compression proxy and let the compression proxy point to a + SSL-initiating mitmproxy (``-R https://...``), which then points to the real + server. As you see, it's a fairly flexible thing. + +.. admonition:: Caveat: Interactive Use + :class: warning + + Reverse Proxy mode is usually not sufficient to create a copy of an interactive website at + different URL. The HTML served to the client remains unchanged - as soon as the user clicks on + an non-relative URL (or downloads a non-relative image resource), traffic no longer passes + through mitmproxy. + +Upstream Proxy +-------------- + +If you want to chain proxies by adding mitmproxy in front of a different proxy +appliance, you can use mitmproxy's upstream mode. In upstream mode, all +requests are unconditionally transferred to an upstream proxy of your choice. + +.. image:: schematics/proxy-modes-upstream.png + :align: center + +mitmproxy supports both explicit HTTP and explicit HTTPS in upstream proxy +mode. You could in theory chain multiple mitmproxy instances in a row, but +that doesn't make any sense in practice (i.e. outside of our tests). + + +.. _Wireshark: https://wireshark.org/ diff --git a/docs/schematics/_explicit.graffle/data.plist b/docs/schematics/_explicit.graffle/data.plist new file mode 100644 index 00000000..bc5ef104 --- /dev/null +++ b/docs/schematics/_explicit.graffle/data.plist @@ -0,0 +1,572 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>ActiveLayerIndex</key> + <integer>0</integer> + <key>ApplicationVersion</key> + <array> + <string>com.omnigroup.OmniGraffle.MacAppStore</string> + <string>139.16</string> + </array> + <key>AutoAdjust</key> + <true/> + <key>BackgroundGraphic</key> + <dict> + <key>Bounds</key> + <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string> + <key>Class</key> + <string>SolidGraphic</string> + <key>ID</key> + <integer>2</integer> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <key>BaseZoom</key> + <integer>0</integer> + <key>CanvasOrigin</key> + <string>{0, 0}</string> + <key>ColumnAlign</key> + <integer>1</integer> + <key>ColumnSpacing</key> + <real>36</real> + <key>CreationDate</key> + <string>2013-01-02 19:31:53 +0000</string> + <key>Creator</key> + <string>Aldo Cortesi</string> + <key>DisplayScale</key> + <string>1.000 cm = 1.000 cm</string> + <key>GraphDocumentVersion</key> + <integer>8</integer> + <key>GraphicsList</key> + <array> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4074</integer> + <key>Points</key> + <array> + <string>{300.4483540852865, 420.70833897590637}</string> + <string>{344.88497416178387, 420.70833897590654}</string> + <string>{362.21830749511713, 420.04167230923986}</string> + <string>{413.55166625976557, 419.70833905537921}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4070</integer> + <key>Points</key> + <array> + <string>{84.896692911783873, 420.66667453447985}</string> + <string>{129.33331298828122, 420.66667453448002}</string> + <string>{146.66664632161454, 420.00000786781334}</string> + <string>{198.00000508626297, 419.66667461395269}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{326.00000000000023, 391.39999198913591}, {62, 24}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4063</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 2: Forwarded \ +Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{110, 403.39997863769622}, {49, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4061</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 1: Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4026</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Server}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4025</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Client}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4004</integer> + <key>ImageID</key> + <integer>6</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4023</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Color</key> + <dict> + <key>b</key> + <string>0</string> + <key>g</key> + <string>0.463735</string> + <key>r</key> + <string>1</string> + </dict> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;\red37\green17\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf2 mitmproxy}</string> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>134</integer> + <key>ImageID</key> + <integer>3</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + </array> + <key>GridInfo</key> + <dict/> + <key>GuidesLocked</key> + <string>NO</string> + <key>GuidesVisible</key> + <string>YES</string> + <key>HPages</key> + <integer>1</integer> + <key>ImageCounter</key> + <integer>7</integer> + <key>ImageLinkBack</key> + <array> + <dict/> + <dict/> + </array> + <key>ImageList</key> + <array> + <string>image6.tiff</string> + <string>image3.icns</string> + </array> + <key>KeepToScale</key> + <false/> + <key>Layers</key> + <array> + <dict> + <key>Lock</key> + <string>NO</string> + <key>Name</key> + <string>Layer 1</string> + <key>Print</key> + <string>YES</string> + <key>View</key> + <string>YES</string> + </dict> + </array> + <key>LayoutInfo</key> + <dict> + <key>Animate</key> + <string>NO</string> + <key>circoMinDist</key> + <real>18</real> + <key>circoSeparation</key> + <real>0.0</real> + <key>layoutEngine</key> + <string>dot</string> + <key>neatoSeparation</key> + <real>0.0</real> + <key>twopiSeparation</key> + <real>0.0</real> + </dict> + <key>LinksVisible</key> + <string>NO</string> + <key>MagnetsVisible</key> + <string>NO</string> + <key>MasterSheets</key> + <array/> + <key>ModificationDate</key> + <string>2013-01-03 02:27:49 +0000</string> + <key>Modifier</key> + <string>Aldo Cortesi</string> + <key>NotesVisible</key> + <string>NO</string> + <key>Orientation</key> + <integer>2</integer> + <key>OriginVisible</key> + <string>NO</string> + <key>PageBreaks</key> + <string>YES</string> + <key>PrintInfo</key> + <dict> + <key>NSBottomMargin</key> + <array> + <string>float</string> + <string>41</string> + </array> + <key>NSHorizonalPagination</key> + <array> + <string>coded</string> + <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string> + </array> + <key>NSLeftMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSPaperSize</key> + <array> + <string>size</string> + <string>{595.19998741149902, 841.79998779296875}</string> + </array> + <key>NSPrintReverseOrientation</key> + <array> + <string>int</string> + <string>0</string> + </array> + <key>NSRightMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSTopMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + </dict> + <key>PrintOnePage</key> + <false/> + <key>ReadOnly</key> + <string>NO</string> + <key>RowAlign</key> + <integer>1</integer> + <key>RowSpacing</key> + <real>36</real> + <key>SheetTitle</key> + <string>Canvas 1</string> + <key>SmartAlignmentGuidesActive</key> + <string>YES</string> + <key>SmartDistanceGuidesActive</key> + <string>YES</string> + <key>UniqueID</key> + <integer>1</integer> + <key>UseEntirePage</key> + <false/> + <key>VPages</key> + <integer>1</integer> + <key>WindowInfo</key> + <dict> + <key>CurrentSheet</key> + <integer>0</integer> + <key>ExpandedCanvases</key> + <array> + <dict> + <key>name</key> + <string>Canvas 1</string> + </dict> + </array> + <key>Frame</key> + <string>{{300, 236}, {974, 874}}</string> + <key>ListView</key> + <true/> + <key>OutlineWidth</key> + <integer>142</integer> + <key>RightSidebar</key> + <false/> + <key>ShowRuler</key> + <true/> + <key>Sidebar</key> + <true/> + <key>SidebarWidth</key> + <integer>120</integer> + <key>VisibleRegion</key> + <string>{{0, 202}, {550, 469.33333333333337}}</string> + <key>Zoom</key> + <real>1.5</real> + <key>ZoomValues</key> + <array> + <array> + <string>Canvas 1</string> + <real>1.5</real> + <real>1</real> + </array> + </array> + </dict> +</dict> +</plist> diff --git a/docs/schematics/_explicit.graffle/image3.icns b/docs/schematics/_explicit.graffle/image3.icns Binary files differnew file mode 100644 index 00000000..964df4b8 --- /dev/null +++ b/docs/schematics/_explicit.graffle/image3.icns diff --git a/docs/schematics/_explicit.graffle/image6.tiff b/docs/schematics/_explicit.graffle/image6.tiff Binary files differnew file mode 100644 index 00000000..bd6ed534 --- /dev/null +++ b/docs/schematics/_explicit.graffle/image6.tiff diff --git a/docs/schematics/_explicit_https.graffle/data.plist b/docs/schematics/_explicit_https.graffle/data.plist new file mode 100644 index 00000000..306630a0 --- /dev/null +++ b/docs/schematics/_explicit_https.graffle/data.plist @@ -0,0 +1,1054 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>ActiveLayerIndex</key> + <integer>0</integer> + <key>ApplicationVersion</key> + <array> + <string>com.omnigroup.OmniGraffle.MacAppStore</string> + <string>139.16</string> + </array> + <key>AutoAdjust</key> + <true/> + <key>BackgroundGraphic</key> + <dict> + <key>Bounds</key> + <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string> + <key>Class</key> + <string>SolidGraphic</string> + <key>ID</key> + <integer>2</integer> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <key>BaseZoom</key> + <integer>0</integer> + <key>CanvasOrigin</key> + <string>{0, 0}</string> + <key>ColumnAlign</key> + <integer>1</integer> + <key>ColumnSpacing</key> + <real>36</real> + <key>CreationDate</key> + <string>2013-01-02 19:31:53 +0000</string> + <key>Creator</key> + <string>Aldo Cortesi</string> + <key>DisplayScale</key> + <string>1.000 cm = 1.000 cm</string> + <key>GraphDocumentVersion</key> + <integer>8</integer> + <key>GraphicsList</key> + <array> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4075</integer> + <key>Points</key> + <array> + <string>{299.94835408528644, 473.66668184598285}</string> + <string>{344.38497416178376, 473.66668184598302}</string> + <string>{361.71830749511713, 473.00001517931634}</string> + <string>{413.05166625976557, 472.66668192545569}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4074</integer> + <key>Points</key> + <array> + <string>{300.4483540852865, 420.70833897590637}</string> + <string>{344.88497416178387, 420.70833897590654}</string> + <string>{362.21830749511713, 420.04167230923986}</string> + <string>{413.55166625976557, 419.70833905537921}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>FilledArrow</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4073</integer> + <key>Points</key> + <array> + <string>{300.44835408528655, 367.66666611035561}</string> + <string>{344.88497416178393, 367.66666611035578}</string> + <string>{362.21830749511719, 366.99999944368909}</string> + <string>{413.55166625976568, 366.66666618982845}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4072</integer> + <key>Points</key> + <array> + <string>{84.896697998046875, 526.66670727729809}</string> + <string>{129.33331807454422, 526.6667072772982}</string> + <string>{146.66665140787754, 526.00004061063157}</string> + <string>{198.00001017252598, 525.66670735677087}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4071</integer> + <key>Points</key> + <array> + <string>{84.896687825520942, 472.91668446858688}</string> + <string>{197.99999491373694, 472.66668319702148}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>FilledArrow</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4070</integer> + <key>Points</key> + <array> + <string>{84.896692911783873, 420.66667453447985}</string> + <string>{129.33331298828122, 420.66667453448002}</string> + <string>{146.66664632161454, 420.00000786781334}</string> + <string>{198.00000508626297, 419.66667461395269}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{316.49998792012531, 326.66665395100904}, {65, 36}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4069</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 4: Initiate SSL \ +handshake \ +with SNI}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{317.00000000000006, 456.66707356770831}, {49, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4067</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 8: Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.187746683756515, 509.33333333333331}, {49, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4066</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 7: Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.1877466837567, 441.50006103515642}, {76, 24}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4065</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 6: Complete SSL\ +handshake}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{316.99998982747411, 403.66686820983904}, {64, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4063</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 5: CN & SANs}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.187741597493542, 380.00018183390387}, {65, 36}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4061</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 3: Initiate SSL \ +handshake \ +with SNI}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.187745571136503, 338.66666666666669}, {84, 24}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4060</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 2: 200 Connection \ +Established}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.187741915384976, 283.66659164428717}, {64, 24}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4058</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 1: CONNECT \ +request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4041</integer> + <key>Points</key> + <array> + <string>{84.896692911783944, 366.91666793823208}</string> + <string>{198, 366.66666666666669}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>FilledArrow</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>31</integer> + <key>Points</key> + <array> + <string>{84.896687825520857, 314.66666126251221}</string> + <string>{129.33330790201822, 314.66666126251238}</string> + <string>{146.66664123535153, 313.99999459584569}</string> + <string>{198, 313.66666134198505}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4026</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Server}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4025</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Client}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4004</integer> + <key>ImageID</key> + <integer>6</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4023</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Color</key> + <dict> + <key>b</key> + <string>0</string> + <key>g</key> + <string>0.463735</string> + <key>r</key> + <string>1</string> + </dict> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;\red37\green17\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf2 mitmproxy}</string> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>134</integer> + <key>ImageID</key> + <integer>3</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + </array> + <key>GridInfo</key> + <dict/> + <key>GuidesLocked</key> + <string>NO</string> + <key>GuidesVisible</key> + <string>YES</string> + <key>HPages</key> + <integer>1</integer> + <key>ImageCounter</key> + <integer>7</integer> + <key>ImageLinkBack</key> + <array> + <dict/> + <dict/> + </array> + <key>ImageList</key> + <array> + <string>image6.tiff</string> + <string>image3.icns</string> + </array> + <key>KeepToScale</key> + <false/> + <key>Layers</key> + <array> + <dict> + <key>Lock</key> + <string>NO</string> + <key>Name</key> + <string>Layer 1</string> + <key>Print</key> + <string>YES</string> + <key>View</key> + <string>YES</string> + </dict> + </array> + <key>LayoutInfo</key> + <dict> + <key>Animate</key> + <string>NO</string> + <key>circoMinDist</key> + <real>18</real> + <key>circoSeparation</key> + <real>0.0</real> + <key>layoutEngine</key> + <string>dot</string> + <key>neatoSeparation</key> + <real>0.0</real> + <key>twopiSeparation</key> + <real>0.0</real> + </dict> + <key>LinksVisible</key> + <string>NO</string> + <key>MagnetsVisible</key> + <string>NO</string> + <key>MasterSheets</key> + <array/> + <key>ModificationDate</key> + <string>2013-01-03 02:14:45 +0000</string> + <key>Modifier</key> + <string>Aldo Cortesi</string> + <key>NotesVisible</key> + <string>NO</string> + <key>Orientation</key> + <integer>2</integer> + <key>OriginVisible</key> + <string>NO</string> + <key>PageBreaks</key> + <string>YES</string> + <key>PrintInfo</key> + <dict> + <key>NSBottomMargin</key> + <array> + <string>float</string> + <string>41</string> + </array> + <key>NSHorizonalPagination</key> + <array> + <string>coded</string> + <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string> + </array> + <key>NSLeftMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSPaperSize</key> + <array> + <string>size</string> + <string>{595.19998741149902, 841.79998779296875}</string> + </array> + <key>NSPrintReverseOrientation</key> + <array> + <string>int</string> + <string>0</string> + </array> + <key>NSRightMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSTopMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + </dict> + <key>PrintOnePage</key> + <false/> + <key>ReadOnly</key> + <string>NO</string> + <key>RowAlign</key> + <integer>1</integer> + <key>RowSpacing</key> + <real>36</real> + <key>SheetTitle</key> + <string>Canvas 1</string> + <key>SmartAlignmentGuidesActive</key> + <string>YES</string> + <key>SmartDistanceGuidesActive</key> + <string>YES</string> + <key>UniqueID</key> + <integer>1</integer> + <key>UseEntirePage</key> + <false/> + <key>VPages</key> + <integer>1</integer> + <key>WindowInfo</key> + <dict> + <key>CurrentSheet</key> + <integer>0</integer> + <key>ExpandedCanvases</key> + <array> + <dict> + <key>name</key> + <string>Canvas 1</string> + </dict> + </array> + <key>Frame</key> + <string>{{271, 336}, {974, 874}}</string> + <key>ListView</key> + <true/> + <key>OutlineWidth</key> + <integer>142</integer> + <key>RightSidebar</key> + <false/> + <key>ShowRuler</key> + <true/> + <key>Sidebar</key> + <true/> + <key>SidebarWidth</key> + <integer>120</integer> + <key>VisibleRegion</key> + <string>{{0, 202}, {550, 469.33333333333337}}</string> + <key>Zoom</key> + <real>1.5</real> + <key>ZoomValues</key> + <array> + <array> + <string>Canvas 1</string> + <real>1.5</real> + <real>1</real> + </array> + </array> + </dict> +</dict> +</plist> diff --git a/docs/schematics/_explicit_https.graffle/image3.icns b/docs/schematics/_explicit_https.graffle/image3.icns Binary files differnew file mode 100644 index 00000000..964df4b8 --- /dev/null +++ b/docs/schematics/_explicit_https.graffle/image3.icns diff --git a/docs/schematics/_explicit_https.graffle/image6.tiff b/docs/schematics/_explicit_https.graffle/image6.tiff Binary files differnew file mode 100644 index 00000000..bd6ed534 --- /dev/null +++ b/docs/schematics/_explicit_https.graffle/image6.tiff diff --git a/docs/schematics/_transparent.graffle/data.plist b/docs/schematics/_transparent.graffle/data.plist new file mode 100644 index 00000000..722b4a44 --- /dev/null +++ b/docs/schematics/_transparent.graffle/data.plist @@ -0,0 +1,771 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>ActiveLayerIndex</key> + <integer>0</integer> + <key>ApplicationVersion</key> + <array> + <string>com.omnigroup.OmniGraffle.MacAppStore</string> + <string>139.16</string> + </array> + <key>AutoAdjust</key> + <true/> + <key>BackgroundGraphic</key> + <dict> + <key>Bounds</key> + <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string> + <key>Class</key> + <string>SolidGraphic</string> + <key>ID</key> + <integer>2</integer> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <key>BaseZoom</key> + <integer>0</integer> + <key>CanvasOrigin</key> + <string>{0, 0}</string> + <key>ColumnAlign</key> + <integer>1</integer> + <key>ColumnSpacing</key> + <real>36</real> + <key>CreationDate</key> + <string>2013-01-02 19:31:53 +0000</string> + <key>Creator</key> + <string>Aldo Cortesi</string> + <key>DisplayScale</key> + <string>1.000 cm = 1.000 cm</string> + <key>GraphDocumentVersion</key> + <integer>8</integer> + <key>GraphicsList</key> + <array> + <dict> + <key>Bounds</key> + <string>{{101.18773396809897, 358.41662979125977}, {62, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4079</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 2: Redirection}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{102.18775939941409, 405.16666666666663}, {78, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4078</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 3: HTTP Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ControlPoints</key> + <array> + <string>{-29.333333333333343, 15.666671991348267}</string> + <string>{-14, -7.3333333333333712}</string> + </array> + <key>ID</key> + <integer>37</integer> + <key>Points</key> + <array> + <string>{196.99999491373691, 331.83332316080725}</string> + <string>{198.00000508626303, 402.49998982747394}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>Bezier</key> + <true/> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>LineType</key> + <integer>1</integer> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{205.34387397766082, 289.3333333333328}, {84, 52.666667938232422}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4076</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Color</key> + <dict> + <key>b</key> + <string>0.547829</string> + <key>g</key> + <string>1</string> + <key>r</key> + <string>0.790866</string> + </dict> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;\red37\green17\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf2 router}</string> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4075</integer> + <key>Points</key> + <array> + <string>{304.061024983724, 422.16667167345679}</string> + <string>{348.49764506022132, 422.16667167345696}</string> + <string>{365.83097839355469, 421.50000500679027}</string> + <string>{417.16433715820312, 421.16667175292963}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{321.11267089843761, 405.16706339518225}, {49, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4067</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 4: Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{101.18773682912195, 295.66660690307623}, {62, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4058</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 1: Connection}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4041</integer> + <key>Points</key> + <array> + <string>{85.896713256836037, 421.41666793823208}</string> + <string>{199.00002034505209, 421.16666666666669}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>31</integer> + <key>Points</key> + <array> + <string>{84.896687825520857, 314.66666126251221}</string> + <string>{129.33330790201822, 314.66666126251238}</string> + <string>{146.66664123535153, 313.99999459584569}</string> + <string>{198, 313.66666134198505}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4026</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Server}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4025</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Client}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4004</integer> + <key>ImageID</key> + <integer>6</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4023</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Color</key> + <dict> + <key>b</key> + <string>0</string> + <key>g</key> + <string>0.463735</string> + <key>r</key> + <string>1</string> + </dict> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;\red37\green17\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf2 mitmproxy}</string> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>134</integer> + <key>ImageID</key> + <integer>3</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + </array> + <key>GridInfo</key> + <dict/> + <key>GuidesLocked</key> + <string>NO</string> + <key>GuidesVisible</key> + <string>YES</string> + <key>HPages</key> + <integer>1</integer> + <key>ImageCounter</key> + <integer>7</integer> + <key>ImageLinkBack</key> + <array> + <dict/> + <dict/> + </array> + <key>ImageList</key> + <array> + <string>image6.tiff</string> + <string>image3.icns</string> + </array> + <key>KeepToScale</key> + <false/> + <key>Layers</key> + <array> + <dict> + <key>Lock</key> + <string>NO</string> + <key>Name</key> + <string>Layer 1</string> + <key>Print</key> + <string>YES</string> + <key>View</key> + <string>YES</string> + </dict> + </array> + <key>LayoutInfo</key> + <dict> + <key>Animate</key> + <string>NO</string> + <key>circoMinDist</key> + <real>18</real> + <key>circoSeparation</key> + <real>0.0</real> + <key>layoutEngine</key> + <string>dot</string> + <key>neatoSeparation</key> + <real>0.0</real> + <key>twopiSeparation</key> + <real>0.0</real> + </dict> + <key>LinksVisible</key> + <string>NO</string> + <key>MagnetsVisible</key> + <string>NO</string> + <key>MasterSheets</key> + <array/> + <key>ModificationDate</key> + <string>2013-01-03 04:13:10 +0000</string> + <key>Modifier</key> + <string>Aldo Cortesi</string> + <key>NotesVisible</key> + <string>NO</string> + <key>Orientation</key> + <integer>2</integer> + <key>OriginVisible</key> + <string>NO</string> + <key>PageBreaks</key> + <string>YES</string> + <key>PrintInfo</key> + <dict> + <key>NSBottomMargin</key> + <array> + <string>float</string> + <string>41</string> + </array> + <key>NSHorizonalPagination</key> + <array> + <string>coded</string> + <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string> + </array> + <key>NSLeftMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSPaperSize</key> + <array> + <string>size</string> + <string>{595.19998741149902, 841.79998779296875}</string> + </array> + <key>NSPrintReverseOrientation</key> + <array> + <string>int</string> + <string>0</string> + </array> + <key>NSRightMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSTopMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + </dict> + <key>PrintOnePage</key> + <false/> + <key>ReadOnly</key> + <string>NO</string> + <key>RowAlign</key> + <integer>1</integer> + <key>RowSpacing</key> + <real>36</real> + <key>SheetTitle</key> + <string>Canvas 1</string> + <key>SmartAlignmentGuidesActive</key> + <string>YES</string> + <key>SmartDistanceGuidesActive</key> + <string>YES</string> + <key>UniqueID</key> + <integer>1</integer> + <key>UseEntirePage</key> + <false/> + <key>VPages</key> + <integer>1</integer> + <key>WindowInfo</key> + <dict> + <key>CurrentSheet</key> + <integer>0</integer> + <key>ExpandedCanvases</key> + <array> + <dict> + <key>name</key> + <string>Canvas 1</string> + </dict> + </array> + <key>Frame</key> + <string>{{295, 141}, {974, 874}}</string> + <key>ListView</key> + <true/> + <key>OutlineWidth</key> + <integer>142</integer> + <key>RightSidebar</key> + <false/> + <key>ShowRuler</key> + <true/> + <key>Sidebar</key> + <true/> + <key>SidebarWidth</key> + <integer>120</integer> + <key>VisibleRegion</key> + <string>{{0, 208}, {550, 469.33333333333337}}</string> + <key>Zoom</key> + <real>1.5</real> + <key>ZoomValues</key> + <array> + <array> + <string>Canvas 1</string> + <real>1.5</real> + <real>1</real> + </array> + </array> + </dict> +</dict> +</plist> diff --git a/docs/schematics/_transparent.graffle/image3.icns b/docs/schematics/_transparent.graffle/image3.icns Binary files differnew file mode 100644 index 00000000..964df4b8 --- /dev/null +++ b/docs/schematics/_transparent.graffle/image3.icns diff --git a/docs/schematics/_transparent.graffle/image6.tiff b/docs/schematics/_transparent.graffle/image6.tiff Binary files differnew file mode 100644 index 00000000..bd6ed534 --- /dev/null +++ b/docs/schematics/_transparent.graffle/image6.tiff diff --git a/docs/schematics/_transparent_https.graffle/data.plist b/docs/schematics/_transparent_https.graffle/data.plist new file mode 100644 index 00000000..9c1395d7 --- /dev/null +++ b/docs/schematics/_transparent_https.graffle/data.plist @@ -0,0 +1,1096 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>ActiveLayerIndex</key> + <integer>0</integer> + <key>ApplicationVersion</key> + <array> + <string>com.omnigroup.OmniGraffle.MacAppStore</string> + <string>139.16</string> + </array> + <key>AutoAdjust</key> + <true/> + <key>BackgroundGraphic</key> + <dict> + <key>Bounds</key> + <string>{{0, 0}, {559.19998741149902, 782.79998779296875}}</string> + <key>Class</key> + <string>SolidGraphic</string> + <key>ID</key> + <integer>2</integer> + <key>Style</key> + <dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <key>BaseZoom</key> + <integer>0</integer> + <key>CanvasOrigin</key> + <string>{0, 0}</string> + <key>ColumnAlign</key> + <integer>1</integer> + <key>ColumnSpacing</key> + <real>36</real> + <key>CreationDate</key> + <string>2013-01-02 19:31:53 +0000</string> + <key>Creator</key> + <string>Aldo Cortesi</string> + <key>DisplayScale</key> + <string>1.000 cm = 1.000 cm</string> + <key>GraphDocumentVersion</key> + <integer>8</integer> + <key>GraphicsList</key> + <array> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4075</integer> + <key>Points</key> + <array> + <string>{299.99999999999994, 470.90565482775372}</string> + <string>{344.43662007649726, 470.90565482775389}</string> + <string>{361.76995340983063, 470.23898816108721}</string> + <string>{413.10331217447907, 469.90565490722656}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4074</integer> + <key>Points</key> + <array> + <string>{300.5, 417.94731195767724}</string> + <string>{344.93662007649738, 417.94731195767741}</string> + <string>{362.26995340983063, 417.28064529101073}</string> + <string>{413.60331217447907, 416.94731203715008}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>FilledArrow</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4073</integer> + <key>Points</key> + <array> + <string>{300.50000000000006, 364.90563909212648}</string> + <string>{344.93662007649743, 364.90563909212665}</string> + <string>{362.26995340983069, 364.23897242545996}</string> + <string>{413.60331217447919, 363.90563917159932}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{316.55163383483881, 323.90562693277991}, {65, 36}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4069</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 4: Initiate SSL \ +handshake \ +with SNI}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{317.05164591471356, 453.90604654947919}, {49, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4067</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 8: Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{317.05163574218761, 400.90584119160991}, {64, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4063</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 5: CN & SANs}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4072</integer> + <key>Points</key> + <array> + <string>{85.333343505859332, 525.3331921100596}</string> + <string>{129.7699635823565, 525.3331921100596}</string> + <string>{147.10329691568987, 524.66652544339308}</string> + <string>{198.4366556803383, 524.33319218953238}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4071</integer> + <key>Points</key> + <array> + <string>{85.3333333333334, 471.58316930134964}</string> + <string>{198.43664042154924, 471.33316802978419}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>0</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>FilledArrow</string> + </dict> + </dict> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>4070</integer> + <key>Points</key> + <array> + <string>{85.33333841959633, 419.33315936724267}</string> + <string>{129.76995849609349, 419.33315936724279}</string> + <string>{147.10329182942687, 418.66649270057616}</string> + <string>{198.4366505940753, 418.33315944671557}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{97.957725524902315, 508.66666666666663}, {49, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4066</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 7: Request}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.624392191569157, 440.16654586791918}, {76, 24}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4065</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 6: Complete SSL\ +handshake}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.624387105305999, 377.33333333333331}, {65, 36}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4061</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 3: Initiate SSL \ +handshake \ +with SNI}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{94.624387105305971, 344.58320871988946}, {62, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4079</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 2: Redirection}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ControlPoints</key> + <array> + <string>{-29.333333333333343, 15.666671991348267}</string> + <string>{-14, -7.3333333333333712}</string> + </array> + <key>ID</key> + <integer>37</integer> + <key>Points</key> + <array> + <string>{197.43664042154938, 317.99990208943694}</string> + <string>{198.4366505940755, 388.66656875610363}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>Bezier</key> + <true/> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>LineType</key> + <integer>1</integer> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{205.34387397766082, 289.3333333333328}, {84, 52.666667938232422}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4076</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Color</key> + <dict> + <key>b</key> + <string>0.547829</string> + <key>g</key> + <string>1</string> + <key>r</key> + <string>0.790866</string> + </dict> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;\red37\green17\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf2 router}</string> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{97.957725842793792, 284.99970499674527}, {62, 12}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>FontInfo</key> + <dict> + <key>Font</key> + <string>Helvetica</string> + <key>Size</key> + <real>12</real> + </dict> + <key>ID</key> + <integer>4058</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs20 \cf0 1: Connection}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Class</key> + <string>LineGraphic</string> + <key>ID</key> + <integer>31</integer> + <key>Points</key> + <array> + <string>{85.333333333333329, 300.8332401911419}</string> + <string>{129.76995340983069, 300.83324019114207}</string> + <string>{147.10328674316401, 300.16657352447538}</string> + <string>{198.43664550781247, 299.83324027061474}</string> + </array> + <key>Style</key> + <dict> + <key>stroke</key> + <dict> + <key>HeadArrow</key> + <string>FilledArrow</string> + <key>Legacy</key> + <true/> + <key>TailArrow</key> + <string>0</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{430.83098347981803, 515.99999999999989}, {36, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4026</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Server}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{40.499999999999993, 486.66666666666663}, {31, 14}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>FitText</key> + <string>YES</string> + <key>Flow</key> + <string>Resize</string> + <key>ID</key> + <integer>4025</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Pad</key> + <integer>0</integer> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf0 Client}</string> + <key>VerticalPad</key> + <integer>0</integer> + </dict> + <key>Wrap</key> + <string>NO</string> + </dict> + <dict> + <key>Bounds</key> + <string>{{417.16432189941418, 323.90565299479198}, {63.333332061767578, 185.52200317382812}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4004</integer> + <key>ImageID</key> + <integer>6</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{205.34386889139773, 289.33333333333331}, {84, 248.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>4023</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Color</key> + <dict> + <key>b</key> + <string>0</string> + <key>g</key> + <string>0.463735</string> + <key>r</key> + <string>1</string> + </dict> + </dict> + </dict> + <key>Text</key> + <dict> + <key>Text</key> + <string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;\red37\green17\blue0;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs24 \cf2 mitmproxy}</string> + </dict> + </dict> + <dict> + <key>Bounds</key> + <string>{{4.6666666467984399, 351.33332316080771}, {102.66666412353516, 130.66667175292969}}</string> + <key>Class</key> + <string>ShapedGraphic</string> + <key>ID</key> + <integer>134</integer> + <key>ImageID</key> + <integer>3</integer> + <key>Shape</key> + <string>Rectangle</string> + <key>Style</key> + <dict> + <key>fill</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>shadow</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + <key>stroke</key> + <dict> + <key>Draws</key> + <string>NO</string> + </dict> + </dict> + </dict> + </array> + <key>GridInfo</key> + <dict/> + <key>GuidesLocked</key> + <string>NO</string> + <key>GuidesVisible</key> + <string>YES</string> + <key>HPages</key> + <integer>1</integer> + <key>ImageCounter</key> + <integer>7</integer> + <key>ImageLinkBack</key> + <array> + <dict/> + <dict/> + </array> + <key>ImageList</key> + <array> + <string>image6.tiff</string> + <string>image3.icns</string> + </array> + <key>KeepToScale</key> + <false/> + <key>Layers</key> + <array> + <dict> + <key>Lock</key> + <string>NO</string> + <key>Name</key> + <string>Layer 1</string> + <key>Print</key> + <string>YES</string> + <key>View</key> + <string>YES</string> + </dict> + </array> + <key>LayoutInfo</key> + <dict> + <key>Animate</key> + <string>NO</string> + <key>circoMinDist</key> + <real>18</real> + <key>circoSeparation</key> + <real>0.0</real> + <key>layoutEngine</key> + <string>dot</string> + <key>neatoSeparation</key> + <real>0.0</real> + <key>twopiSeparation</key> + <real>0.0</real> + </dict> + <key>LinksVisible</key> + <string>NO</string> + <key>MagnetsVisible</key> + <string>NO</string> + <key>MasterSheets</key> + <array/> + <key>ModificationDate</key> + <string>2013-01-03 04:16:32 +0000</string> + <key>Modifier</key> + <string>Aldo Cortesi</string> + <key>NotesVisible</key> + <string>NO</string> + <key>Orientation</key> + <integer>2</integer> + <key>OriginVisible</key> + <string>NO</string> + <key>PageBreaks</key> + <string>YES</string> + <key>PrintInfo</key> + <dict> + <key>NSBottomMargin</key> + <array> + <string>float</string> + <string>41</string> + </array> + <key>NSHorizonalPagination</key> + <array> + <string>coded</string> + <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string> + </array> + <key>NSLeftMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSPaperSize</key> + <array> + <string>size</string> + <string>{595.19998741149902, 841.79998779296875}</string> + </array> + <key>NSPrintReverseOrientation</key> + <array> + <string>int</string> + <string>0</string> + </array> + <key>NSRightMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + <key>NSTopMargin</key> + <array> + <string>float</string> + <string>18</string> + </array> + </dict> + <key>PrintOnePage</key> + <false/> + <key>ReadOnly</key> + <string>NO</string> + <key>RowAlign</key> + <integer>1</integer> + <key>RowSpacing</key> + <real>36</real> + <key>SheetTitle</key> + <string>Canvas 1</string> + <key>SmartAlignmentGuidesActive</key> + <string>YES</string> + <key>SmartDistanceGuidesActive</key> + <string>YES</string> + <key>UniqueID</key> + <integer>1</integer> + <key>UseEntirePage</key> + <false/> + <key>VPages</key> + <integer>1</integer> + <key>WindowInfo</key> + <dict> + <key>CurrentSheet</key> + <integer>0</integer> + <key>ExpandedCanvases</key> + <array> + <dict> + <key>name</key> + <string>Canvas 1</string> + </dict> + </array> + <key>Frame</key> + <string>{{869, 248}, {974, 874}}</string> + <key>ListView</key> + <true/> + <key>OutlineWidth</key> + <integer>142</integer> + <key>RightSidebar</key> + <false/> + <key>ShowRuler</key> + <true/> + <key>Sidebar</key> + <true/> + <key>SidebarWidth</key> + <integer>120</integer> + <key>VisibleRegion</key> + <string>{{0, 208}, {550, 469.33333333333337}}</string> + <key>Zoom</key> + <real>1.5</real> + <key>ZoomValues</key> + <array> + <array> + <string>Canvas 1</string> + <real>1.5</real> + <real>1</real> + </array> + </array> + </dict> +</dict> +</plist> diff --git a/docs/schematics/_transparent_https.graffle/image3.icns b/docs/schematics/_transparent_https.graffle/image3.icns Binary files differnew file mode 100644 index 00000000..964df4b8 --- /dev/null +++ b/docs/schematics/_transparent_https.graffle/image3.icns diff --git a/docs/schematics/_transparent_https.graffle/image6.tiff b/docs/schematics/_transparent_https.graffle/image6.tiff Binary files differnew file mode 100644 index 00000000..bd6ed534 --- /dev/null +++ b/docs/schematics/_transparent_https.graffle/image6.tiff diff --git a/docs/schematics/architecture.pdf b/docs/schematics/architecture.pdf Binary files differnew file mode 100644 index 00000000..77f5ad58 --- /dev/null +++ b/docs/schematics/architecture.pdf diff --git a/docs/schematics/architecture.png b/docs/schematics/architecture.png Binary files differnew file mode 100644 index 00000000..67d6c718 --- /dev/null +++ b/docs/schematics/architecture.png diff --git a/docs/schematics/architecture.vsdx b/docs/schematics/architecture.vsdx Binary files differnew file mode 100644 index 00000000..c4ff13d2 --- /dev/null +++ b/docs/schematics/architecture.vsdx diff --git a/docs/schematics/how-mitmproxy-works-explicit-https.png b/docs/schematics/how-mitmproxy-works-explicit-https.png Binary files differnew file mode 100644 index 00000000..1f1ca023 --- /dev/null +++ b/docs/schematics/how-mitmproxy-works-explicit-https.png diff --git a/docs/schematics/how-mitmproxy-works-explicit.png b/docs/schematics/how-mitmproxy-works-explicit.png Binary files differnew file mode 100644 index 00000000..c9ba26a7 --- /dev/null +++ b/docs/schematics/how-mitmproxy-works-explicit.png diff --git a/docs/schematics/how-mitmproxy-works-transparent-https.png b/docs/schematics/how-mitmproxy-works-transparent-https.png Binary files differnew file mode 100644 index 00000000..559cddd2 --- /dev/null +++ b/docs/schematics/how-mitmproxy-works-transparent-https.png diff --git a/docs/schematics/how-mitmproxy-works-transparent.png b/docs/schematics/how-mitmproxy-works-transparent.png Binary files differnew file mode 100644 index 00000000..3994d681 --- /dev/null +++ b/docs/schematics/how-mitmproxy-works-transparent.png diff --git a/docs/schematics/proxy-modes-flowchart.png b/docs/schematics/proxy-modes-flowchart.png Binary files differnew file mode 100644 index 00000000..716b5ee2 --- /dev/null +++ b/docs/schematics/proxy-modes-flowchart.png diff --git a/docs/schematics/proxy-modes-regular.png b/docs/schematics/proxy-modes-regular.png Binary files differnew file mode 100644 index 00000000..95bada08 --- /dev/null +++ b/docs/schematics/proxy-modes-regular.png diff --git a/docs/schematics/proxy-modes-reverse.png b/docs/schematics/proxy-modes-reverse.png Binary files differnew file mode 100644 index 00000000..071d3fc8 --- /dev/null +++ b/docs/schematics/proxy-modes-reverse.png diff --git a/docs/schematics/proxy-modes-transparent-1.png b/docs/schematics/proxy-modes-transparent-1.png Binary files differnew file mode 100644 index 00000000..002e0e76 --- /dev/null +++ b/docs/schematics/proxy-modes-transparent-1.png diff --git a/docs/schematics/proxy-modes-transparent-2.png b/docs/schematics/proxy-modes-transparent-2.png Binary files differnew file mode 100644 index 00000000..41997b05 --- /dev/null +++ b/docs/schematics/proxy-modes-transparent-2.png diff --git a/docs/schematics/proxy-modes-transparent-3.png b/docs/schematics/proxy-modes-transparent-3.png Binary files differnew file mode 100644 index 00000000..ee26cb4f --- /dev/null +++ b/docs/schematics/proxy-modes-transparent-3.png diff --git a/docs/schematics/proxy-modes-transparent-wrong.png b/docs/schematics/proxy-modes-transparent-wrong.png Binary files differnew file mode 100644 index 00000000..ca501e93 --- /dev/null +++ b/docs/schematics/proxy-modes-transparent-wrong.png diff --git a/docs/schematics/proxy-modes-upstream.png b/docs/schematics/proxy-modes-upstream.png Binary files differnew file mode 100644 index 00000000..d40a6494 --- /dev/null +++ b/docs/schematics/proxy-modes-upstream.png diff --git a/docs/schematics/proxy-modes.pdf b/docs/schematics/proxy-modes.pdf Binary files differnew file mode 100644 index 00000000..f07ea05e --- /dev/null +++ b/docs/schematics/proxy-modes.pdf diff --git a/docs/schematics/proxy-modes.vsdx b/docs/schematics/proxy-modes.vsdx Binary files differnew file mode 100644 index 00000000..c78cf8d0 --- /dev/null +++ b/docs/schematics/proxy-modes.vsdx diff --git a/docs/screenshots/firefox3-import.jpg b/docs/screenshots/firefox3-import.jpg Binary files differnew file mode 100644 index 00000000..47fcd672 --- /dev/null +++ b/docs/screenshots/firefox3-import.jpg diff --git a/docs/screenshots/firefox3-trust.jpg b/docs/screenshots/firefox3-trust.jpg Binary files differnew file mode 100644 index 00000000..50a2f341 --- /dev/null +++ b/docs/screenshots/firefox3-trust.jpg diff --git a/docs/screenshots/firefox3.jpg b/docs/screenshots/firefox3.jpg Binary files differnew file mode 100644 index 00000000..6c4613b6 --- /dev/null +++ b/docs/screenshots/firefox3.jpg diff --git a/docs/screenshots/ios-gateway.png b/docs/screenshots/ios-gateway.png Binary files differnew file mode 100644 index 00000000..2489cba3 --- /dev/null +++ b/docs/screenshots/ios-gateway.png diff --git a/docs/screenshots/ios-installed.png b/docs/screenshots/ios-installed.png Binary files differnew file mode 100644 index 00000000..2071e441 --- /dev/null +++ b/docs/screenshots/ios-installed.png diff --git a/docs/screenshots/ios-manual.png b/docs/screenshots/ios-manual.png Binary files differnew file mode 100644 index 00000000..3977acfe --- /dev/null +++ b/docs/screenshots/ios-manual.png diff --git a/docs/screenshots/ios-profile.png b/docs/screenshots/ios-profile.png Binary files differnew file mode 100644 index 00000000..5bcd5a0d --- /dev/null +++ b/docs/screenshots/ios-profile.png diff --git a/docs/screenshots/ios-reverse.png b/docs/screenshots/ios-reverse.png Binary files differnew file mode 100644 index 00000000..6ab5b7c0 --- /dev/null +++ b/docs/screenshots/ios-reverse.png diff --git a/docs/screenshots/ios-warning.png b/docs/screenshots/ios-warning.png Binary files differnew file mode 100644 index 00000000..d882c514 --- /dev/null +++ b/docs/screenshots/ios-warning.png diff --git a/docs/screenshots/mitmproxy-flowview.png b/docs/screenshots/mitmproxy-flowview.png Binary files differnew file mode 100644 index 00000000..154963fe --- /dev/null +++ b/docs/screenshots/mitmproxy-flowview.png diff --git a/docs/screenshots/mitmproxy-intercept-filt.png b/docs/screenshots/mitmproxy-intercept-filt.png Binary files differnew file mode 100644 index 00000000..60556ee7 --- /dev/null +++ b/docs/screenshots/mitmproxy-intercept-filt.png diff --git a/docs/screenshots/mitmproxy-intercept-mid.png b/docs/screenshots/mitmproxy-intercept-mid.png Binary files differnew file mode 100644 index 00000000..d5b03922 --- /dev/null +++ b/docs/screenshots/mitmproxy-intercept-mid.png diff --git a/docs/screenshots/mitmproxy-intercept-options.png b/docs/screenshots/mitmproxy-intercept-options.png Binary files differnew file mode 100644 index 00000000..8dc4ad2c --- /dev/null +++ b/docs/screenshots/mitmproxy-intercept-options.png diff --git a/docs/screenshots/mitmproxy-intercept-result.png b/docs/screenshots/mitmproxy-intercept-result.png Binary files differnew file mode 100644 index 00000000..7d9f5c94 --- /dev/null +++ b/docs/screenshots/mitmproxy-intercept-result.png diff --git a/docs/screenshots/mitmproxy-kveditor-editmode.png b/docs/screenshots/mitmproxy-kveditor-editmode.png Binary files differnew file mode 100644 index 00000000..a8315ee5 --- /dev/null +++ b/docs/screenshots/mitmproxy-kveditor-editmode.png diff --git a/docs/screenshots/mitmproxy-kveditor.png b/docs/screenshots/mitmproxy-kveditor.png Binary files differnew file mode 100644 index 00000000..144b9701 --- /dev/null +++ b/docs/screenshots/mitmproxy-kveditor.png diff --git a/docs/screenshots/mitmproxy.png b/docs/screenshots/mitmproxy.png Binary files differnew file mode 100644 index 00000000..42a10e32 --- /dev/null +++ b/docs/screenshots/mitmproxy.png diff --git a/docs/screenshots/osx-addcert-alwaystrust.png b/docs/screenshots/osx-addcert-alwaystrust.png Binary files differnew file mode 100644 index 00000000..4c5cc704 --- /dev/null +++ b/docs/screenshots/osx-addcert-alwaystrust.png diff --git a/docs/screenshots/win7-certstore-trustedroot.png b/docs/screenshots/win7-certstore-trustedroot.png Binary files differnew file mode 100644 index 00000000..e15a87f5 --- /dev/null +++ b/docs/screenshots/win7-certstore-trustedroot.png diff --git a/docs/screenshots/win7-certstore.png b/docs/screenshots/win7-certstore.png Binary files differnew file mode 100644 index 00000000..f8ce54bd --- /dev/null +++ b/docs/screenshots/win7-certstore.png diff --git a/docs/screenshots/win7-wizard.png b/docs/screenshots/win7-wizard.png Binary files differnew file mode 100644 index 00000000..eff6ad09 --- /dev/null +++ b/docs/screenshots/win7-wizard.png diff --git a/docs/screenshots/winpythoninstaller.jpg b/docs/screenshots/winpythoninstaller.jpg Binary files differnew file mode 100644 index 00000000..0473c66a --- /dev/null +++ b/docs/screenshots/winpythoninstaller.jpg diff --git a/docs/scripting/inlinescripts.rst b/docs/scripting/inlinescripts.rst new file mode 100644 index 00000000..19e17582 --- /dev/null +++ b/docs/scripting/inlinescripts.rst @@ -0,0 +1,214 @@ +.. _inlinescripts: + +Inline Scripts +============== + +**mitmproxy** has a powerful scripting API that allows you to modify flows +on-the-fly or rewrite previously saved flows locally. + +The mitmproxy scripting API is event driven - a script is simply a Python +module that exposes a set of event methods. Here's a complete mitmproxy script +that adds a new header to every HTTP response before it is returned to the +client: + +.. literalinclude:: ../../examples/add_header.py + :caption: examples/add_header.py + :language: python + +The first argument to each event method is an instance of +:py:class:`~libmproxy.script.ScriptContext` that lets the script interact with the global mitmproxy +state. The **response** event also gets an instance of :py:class:`~libmproxy.script.ScriptContext`, +which we can use to manipulate the response itself. + +We can now run this script using mitmdump or mitmproxy as follows: + +>>> mitmdump -s add_header.py + +The new header will be added to all responses passing through the proxy. + +Examples +-------- + +mitmproxy comes with a variety of example inline scripts, which demonstrate many basic tasks. +We encourage you to either browse them locally or on `GitHub`_. + + +Events +------ + +.. TODO: Split this into Connection, HTTP and TCP events once we have TCP events. + +The ``context`` argument passed to each event method is always a +:py:class:`~libmproxy.script.ScriptContext` instance. It is guaranteed to be the same object +for the scripts lifetime and is not shared between multiple inline scripts. You can safely use it +to store any form of state you require. + +Events are listed in the order they usually occur. + +.. py:function:: start(context, argv) + + Called once on startup, before any other events. + + :param List[str] argv: The inline scripts' arguments. + For example, ``mitmproxy -s 'example.py --foo 42'`` sets argv to ``["--foo", "42"]``. + +.. py:function:: clientconnect(context, root_layer) + + Called when a client initiates a connection to the proxy. Note that + a connection can correspond to multiple HTTP requests. + + .. versionchanged:: 0.14 + + :param Layer root_layer: The root layer (see :ref:`protocols` for an explanation what the root + layer is), which provides transparent access to all attributes of the + :py:class:`~libmproxy.proxy.RootContext`. For example, ``root_layer.client_conn.address`` + gives the remote address of the connecting client. + + +.. py:function:: request(context, flow) + + Called when a client request has been received. The ``flow`` object is + guaranteed to have a non-None ``request`` attribute. + + :param HTTPFlow flow: The flow containing the request which has been received. + The object is guaranteed to have a non-None ``request`` attribute. + +.. py:function:: serverconnect(context, server_conn) + + Called before the proxy initiates a connection to the target server. Note that + a connection can correspond to multiple HTTP requests. + + :param ServerConnection server_conn: The server connection object. It is guaranteed to have a + non-None ``address`` attribute. + +.. py:function:: responseheaders(context, flow) + + Called when the headers of a server response have been received. + This will always be called before the response hook. + + :param HTTPFlow flow: The flow containing the request and response. + The object is guaranteed to have non-None ``request`` and + ``response`` attributes. ``response.content`` will be ``None``, + as the response body has not been read yet. + +.. py:function:: response(context, flow) + + Called when a server response has been received. + + :param HTTPFlow flow: The flow containing the request and response. + The object is guaranteed to have non-None ``request`` and + ``response`` attributes. ``response.body`` will contain the raw response body, + unless response streaming has been enabled. + +.. py:function:: error(context, flow) + + Called when a flow 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. + + :param HTTPFlow flow: The flow containing the error. + It is guaranteed to have non-None ``error`` attribute. + +.. py:function:: serverdisconnect(context, server_conn) + + Called when the proxy has closed the server connection. + + .. versionadded:: 0.14 + + :param ServerConnection server_conn: see :py:func:`serverconnect` + +.. py:function:: clientdisconnect(context, root_layer) + + Called when a client disconnects from the proxy. + + .. versionchanged:: 0.14 + + :param Layer root_layer: see :py:func:`clientconnect` + +.. py:function:: done(context) + + Called once on script shutdown, after any other events. + + +API +--- + +The canonical API documentation is the code, which you can browse here, locally or on `GitHub`_. +*Use the Source, Luke!* + +The main classes you will deal with in writing mitmproxy scripts are: + +:py:class:`~libmproxy.script.ScriptContext` + - A handle for interacting with mitmproxy's Flow Master from within scripts. +:py:class:`~libmproxy.models.ClientConnection` + - Describes a client connection. +:py:class:`~libmproxy.models.ServerConnection` + - Describes a server connection. +:py:class:`~libmproxy.models.HTTPFlow` + - A collection of objects representing a single HTTP transaction. +:py:class:`~libmproxy.models.HTTPRequest` + - An HTTP request. +:py:class:`~libmproxy.models.HTTPResponse` + - An HTTP response. +:py:class:`~libmproxy.models.Error` + - A communications error. +:py:class:`netlib.http.Headers` + - A dictionary-like object for managing HTTP headers. +:py:class:`netlib.certutils.SSLCert` + - Exposes information SSL certificates. +:py:class:`libmproxy.flow.FlowMaster` + - The "heart" of libmproxy, usually subclassed as :py:class:`libmproxy.dump.DumpMaster` or + :py:class:`libmproxy.console.ConsoleMaster`. + +Script Context +-------------- + +.. autoclass:: libmproxy.script.ScriptContext + :members: + :undoc-members: + +Running scripts in parallel +--------------------------- + +We have a single flow primitive, so when a script is blocking, other requests are not processed. +While that's usually a very desirable behaviour, blocking scripts can be run threaded by using the +:py:obj:`libmproxy.script.concurrent` decorator. +**If your script does not block, you should avoid the overhead of the decorator.** + +.. literalinclude:: ../../examples/nonblocking.py + :caption: examples/nonblocking.py + :language: python + +Make scripts configurable with arguments +---------------------------------------- + +Sometimes, you want to pass runtime arguments to the inline script. This can be simply done by +surrounding the script call with quotes, e.g. ```mitmdump -s 'script.py --foo 42'``. +The arguments are then exposed in the start event: + +.. literalinclude:: ../../examples/modify_response_body.py + :caption: examples/modify_response_body.py + :language: python + +Running scripts on saved flows +------------------------------ + +Sometimes, we want to run a script on :py:class:`~libmproxy.models.Flow` objects that are already +complete. This happens when you start a script, and then load a saved set of flows from a file +(see the "scripted data transformation" example `here <https://mitmproxy.org/doc/mitmdump.html>`_). +It also happens when you run a one-shot script on a single flow through the ``|`` (pipe) shortcut +in mitmproxy. + +In this case, there are no client connections, and the events are run in the following order: +**start**, **request**, **responseheaders**, **response**, **error**, **done**. +If the flow doesn't have a **response** or **error** associated with it, the matching events will +be skipped. + +Spaces in the script path +------------------------- + +By default, spaces are interpreted as a separator between the inline script and its arguments +(e.g. ``-s 'foo.py 42'``). Consequently, the script path needs to be wrapped in a separate pair of +quotes if it contains spaces: ``-s '\'./foo bar/baz.py\' 42'``. + +.. _GitHub: https://github.com/mitmproxy/mitmproxy diff --git a/docs/scripting/libmproxy.rst b/docs/scripting/libmproxy.rst new file mode 100644 index 00000000..92fa5277 --- /dev/null +++ b/docs/scripting/libmproxy.rst @@ -0,0 +1,27 @@ +.. _libmproxy: + +libmproxy +========= + +.. note:: + + We strongly encourage you to use :ref:`inlinescripts` rather than libmproxy. + - Inline Scripts are equally powerful and provide an easier syntax. + - Most examples are written as inline scripts. + - Multiple inline scripts can be used together. + - Inline Scripts can either be executed headless with mitmdump or within the mitmproxy UI. + + +All of mitmproxy's basic functionality is exposed through the **libmproxy** +library. The example below shows a simple implementation of the "sticky cookie" +functionality included in the interactive mitmproxy program. Traffic is +monitored for ``Cookie`` and ``Set-Cookie`` headers, and requests are rewritten +to include a previously seen cookie if they don't already have one. In effect, +this lets you log in to a site using your browser, and then make subsequent +requests using a tool like curl, which will then seem to be part of the +authenticated session. + + +.. literalinclude:: ../../examples/stickycookies + :caption: examples/stickycookies + :language: python diff --git a/docs/transparent.rst b/docs/transparent.rst new file mode 100644 index 00000000..eb77c76c --- /dev/null +++ b/docs/transparent.rst @@ -0,0 +1,24 @@ +.. _transparent: + +Transparent Proxying +==================== + +When a transparent proxy is used, traffic is redirected into a proxy at the +network layer, without any client configuration being required. This makes +transparent proxying ideal for those situations where you can't change client +behaviour - proxy-oblivious Android applications being a common example. + +To set up transparent proxying, we need two new components. The first is a +redirection mechanism that transparently reroutes a TCP connection destined for +a server on the Internet to a listening proxy server. This usually takes the +form of a firewall on the same host as the proxy server - iptables_ on Linux +or pf_ on OSX. When the proxy receives a redirected connection, it sees a vanilla +HTTP request, without a host specification. This is where the second new component +comes in - a host module that allows us to query the redirector for the original +destination of the TCP connection. + +At the moment, mitmproxy supports transparent proxying on OSX Lion and above, +and all current flavors of Linux. + +.. _iptables: http://www.netfilter.org/ +.. _pf: https://en.wikipedia.org/wiki/PF_\(firewall\) diff --git a/docs/transparent/linux.rst b/docs/transparent/linux.rst new file mode 100644 index 00000000..ce79128c --- /dev/null +++ b/docs/transparent/linux.rst @@ -0,0 +1,45 @@ +.. _linux: + +Linux +===== + +On Linux, mitmproxy integrates with the iptables redirection mechanism to +achieve transparent mode. + + 1. :ref:`Install the mitmproxy certificate on the test device <certinstall>` + + 2. Enable IP forwarding: + + >>> sysctl -w net.ipv4.ip_forward=1 + + You may also want to consider enabling this permanently in ``/etc/sysctl.conf``. + + 3. If your target machine is on the same physical network and you configured it to use a custom + gateway, disable ICMP redirects: + + >>> echo 0 | sudo tee /proc/sys/net/ipv4/conf/*/send_redirects + + You may also want to consider enabling this permanently in ``/etc/sysctl.conf`` + as demonstrated `here <https://unix.stackexchange.com/a/58081>`_. + + 4. Create an iptables ruleset that redirects the desired traffic to the + mitmproxy port. Details will differ according to your setup, but the + ruleset should look something like this: + + .. code-block:: none + + iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080 + iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8080 + + 5. Fire up mitmproxy. You probably want a command like this: + + >>> mitmproxy -T --host + + The :option:`-T` flag turns on transparent mode, and the :option:`--host` + argument tells mitmproxy to use the value of the Host header for URL display. + + 6. Finally, configure your test device to use the host on which mitmproxy is + running as the default gateway. + + +For a detailed walkthrough, have a look at the :ref:`transparent-dhcp` tutorial. diff --git a/docs/transparent/osx.rst b/docs/transparent/osx.rst new file mode 100644 index 00000000..5a4a3173 --- /dev/null +++ b/docs/transparent/osx.rst @@ -0,0 +1,70 @@ +.. _osx: + +OSX +=== + +OSX Lion integrated the pf_ packet filter from the OpenBSD project, +which mitmproxy uses to implement transparent mode on OSX. +Note that this means we don't support transparent mode for earlier versions of OSX. + + 1. :ref:`Install the mitmproxy certificate on the test device <certinstall>` + + 2. Enable IP forwarding: + + >>> sudo sysctl -w net.inet.ip.forwarding=1 + + 3. Place the following two lines in a file called, say, **pf.conf**: + + .. code-block:: none + + rdr on en2 inet proto tcp to any port 80 -> 127.0.0.1 port 8080 + rdr on en2 inet proto tcp to any port 443 -> 127.0.0.1 port 8080 + + These rules tell pf to redirect all traffic destined for port 80 or 443 + to the local mitmproxy instance running on port 8080. You should + replace ``en2`` with the interface on which your test device will appear. + + 4. Configure pf with the rules: + + >>> sudo pfctl -f pf.conf + + 5. And now enable it: + + >>>sudo pfctl -e + + 6. Configure sudoers to allow mitmproxy to access pfctl. Edit the file + **/etc/sudoers** on your system as root. Add the following line to the end + of the file: + + .. code-block:: none + + ALL ALL=NOPASSWD: /sbin/pfctl -s state + + Note that this allows any user on the system to run the command + ``/sbin/pfctl -s state`` as root without a password. This only allows + inspection of the state table, so should not be an undue security risk. If + you're special feel free to tighten the restriction up to the user running + mitmproxy. + + 7. Fire up mitmproxy. You probably want a command like this: + + >>> mitmproxy -T --host + + The :option:`-T` flag turns on transparent mode, and the :option:`--host` + argument tells mitmproxy to use the value of the Host header for URL display. + + 8. Finally, configure your test device to use the host on which mitmproxy is + running as the default gateway. + +.. note:: + + Note that the **rdr** rules in the pf.conf given above only apply to inbound + traffic. **This means that they will NOT redirect traffic coming from the box + running pf itself.** We can't distinguish between an outbound connection from a + non-mitmproxy app, and an outbound connection from mitmproxy itself - if you + want to intercept your OSX traffic, you should use an external host to run + mitmproxy. None the less, pf is flexible to cater for a range of creative + possibilities, like intercepting traffic emanating from VMs. See the + **pf.conf** man page for more. + +.. _pf: https://en.wikipedia.org/wiki/PF_\(firewall\) diff --git a/docs/tutorials/30second.rst b/docs/tutorials/30second.rst new file mode 100644 index 00000000..4c8bf326 --- /dev/null +++ b/docs/tutorials/30second.rst @@ -0,0 +1,66 @@ +.. _30second: + +Client playback: a 30 second example +==================================== + +My local cafe is serviced by a rickety and unreliable wireless network, +generously sponsored with ratepayers' money by our city council. After +connecting, you are redirected to an SSL-protected page that prompts you for a +username and password. Once you've entered your details, you are free to enjoy +the intermittent dropouts, treacle-like speeds and incorrectly configured +transparent proxy. + +I tend to automate this kind of thing at the first opportunity, on the theory +that time spent now will be more than made up in the long run. In this case, I +might use Firebug_ to ferret out the form post +parameters and target URL, then fire up an editor to write a little script +using Python's urllib_ to simulate a submission. +That's a lot of futzing about. With mitmproxy we can do the job +in literally 30 seconds, without having to worry about any of the details. +Here's how. + +1. Run mitmdump to record our HTTP conversation to a file. +---------------------------------------------------------- + +>>> mitmdump -w wireless-login + +2. Point your browser at the mitmdump instance. +----------------------------------------------- + +I use a tiny Firefox addon called `Toggle Proxy`_ to switch quickly to and from mitmproxy. +I'm assuming you've already :ref:`configured +your browser with mitmproxy's SSL certificate +authority <certinstall>`. + +3. Log in as usual. +------------------- + +And that's it! You now have a serialized version of the login process in the +file wireless-login, and you can replay it at any time like this: + +>>> mitmdump -c wireless-login + +Embellishments +-------------- + +We're really done at this point, but there are a couple of embellishments we +could make if we wanted. I use wicd_ to +automatically join wireless networks I frequent, and it lets me specify a +command to run after connecting. I used the client replay command above and +voila! - totally hands-free wireless network startup. + +We might also want to prune requests that download CSS, JS, images and so +forth. These add only a few moments to the time it takes to replay, but they're +not really needed and I somehow feel compelled to trim them anyway. So, we fire up +the mitmproxy console tool on our serialized conversation, like so: + +>>> mitmproxy -r wireless-login + +We can now go through and manually delete (using the :kbd:`d` keyboard shortcut) +everything we want to trim. When we're done, we use :kbd:`w` to save the +conversation back to the file. + +.. _Firebug: https://getfirebug.com/ +.. _urllib: https://docs.python.org/library/urllib.html +.. _Toggle Proxy: https://addons.mozilla.org/en-us/firefox/addon/toggle-proxy-51740/ +.. _wicd: https://launchpad.net/wicd diff --git a/docs/tutorials/gamecenter.rst b/docs/tutorials/gamecenter.rst new file mode 100644 index 00000000..96c30437 --- /dev/null +++ b/docs/tutorials/gamecenter.rst @@ -0,0 +1,128 @@ +.. _gamecenter: + +Setting highscores on Apple's GameCenter +======================================== + +The setup +--------- + +In this tutorial, I'm going to show you how simple it is to creatively +interfere with Apple Game Center traffic using mitmproxy. To set things up, +:ref:`install the mitmproxy root certificate <certinstall>`. Then +start mitmproxy on your desktop, and confige the iPhone to use it as a proxy. + + +Taking a look at the Game Center traffic +---------------------------------------- + +Lets take a first look at the Game Center traffic. The game I'll use in this +tutorial is `Super Mega Worm`_ - a great little retro-apocalyptic sidescroller for the iPhone: + +.. image:: supermega.png + :align: center + + +After finishing a game (take your time), watch the traffic flowing through +mitmproxy: + +.. image:: one.png + :align: center + +We see a bunch of things we might expect - initialisation, the retrieval of +leaderboards and so forth. Then, right at the end, there's a POST to this +tantalising URL: + +.. code-block:: none + + https://service.gc.apple.com/WebObjects/GKGameStatsService.woa/wa/submitScore + +The contents of the submission are particularly interesting: + +.. code-block:: xml + + <!--(block|syntax("xml"))--> + <plist version="1.0"> + <dict> + <key>scores</key> + <array> + <dict> + <key>category</key> + <string>SMW_Adv_USA1</string> + <key>context</key> + <integer>0</integer> + <key>score-value</key> + <integer>0</integer> + <key>timestamp</key> + <integer>1363515361321</integer> + </dict> + </array> + </dict> + </plist> + <!--(end)--> + +This is a `property list`_, containing an identifier for the game, +a score (55, in this case), and a timestamp. Looks pretty simple to mess with. + +Modifying and replaying the score submission +-------------------------------------------- + +Lets edit the score submission. First, select it in mitmproxy, then press +:kbd:`enter` to view it. Make sure you're viewing the request, not the response - +you can use :kbd:`tab` to flick between the two. Now press :kbd:`e` for edit. You'll +be prompted for the part of the request you want to change - press :kbd:`r` for +raw body. Your preferred editor (taken from the EDITOR environment variable) will +now fire up. Lets bump the score up to something a bit more ambitious: + +.. code-block:: xml + + <!--(block|syntax("xml"))--> + <plist version="1.0"> + <dict> + <key>scores</key> + <array> + <dict> + <key>category</key> + <string>SMW_Adv_USA1</string> + <key>context</key> + <integer>0</integer> + <key>score-value</key> + <integer>2200272667</integer> + <key>timestamp</key> + <integer>1363515361321</integer> + </dict> + </array> + </dict> + </plist> + <!--(end)--> + +Save the file and exit your editor. + +The final step is to replay this modified request. Simply press :kbd:`r` for replay. + + +The glorious result and some intrigue +------------------------------------- + +.. image:: leaderboard.png + :align: center + +And that's it - according to the records, I am the greatest Super Mega Worm +player of all time. + +There's a curious addendum to this tale. When I first wrote this tutorial, all +the top competitors' scores were the same: 2,147,483,647 (this is no longer the +case, beacause there are now so many fellow cheaters using this tutorial). If +you think that number seems familiar, you're right: it's 2^31-1, the maximum +value you can fit into a signed 32-bit int. Now let me tell you another +peculiar thing about Super Mega Worm - at the end of every game, it submits +your highest previous score to the Game Center, not your current score. This +means that it stores your highscore somewhere, and I'm guessing that it reads +that stored score back into a signed integer. So, if you _were_ to cheat by the +relatively pedestrian means of modifying the saved score on your jailbroken +phone, then 2^31-1 might well be the maximum score you could get. Then again, +if the game itself stores its score in a signed 32-bit int, you could get the +same score through perfect play, effectively beating the game. So, which is it +in this case? I'll leave that for you to decide. + +.. _Super Mega Worm: https://itunes.apple.com/us/app/super-mega-worm/id388541990?mt=8 +.. _property list: https://en.wikipedia.org/wiki/Property_list diff --git a/docs/tutorials/leaderboard.png b/docs/tutorials/leaderboard.png Binary files differnew file mode 100644 index 00000000..c1be8df5 --- /dev/null +++ b/docs/tutorials/leaderboard.png diff --git a/docs/tutorials/one.png b/docs/tutorials/one.png Binary files differnew file mode 100644 index 00000000..78a636cf --- /dev/null +++ b/docs/tutorials/one.png diff --git a/docs/tutorials/supermega.png b/docs/tutorials/supermega.png Binary files differnew file mode 100644 index 00000000..d416f71f --- /dev/null +++ b/docs/tutorials/supermega.png diff --git a/docs/tutorials/transparent-dhcp.rst b/docs/tutorials/transparent-dhcp.rst new file mode 100644 index 00000000..ce285b63 --- /dev/null +++ b/docs/tutorials/transparent-dhcp.rst @@ -0,0 +1,89 @@ +.. _transparent-dhcp: + +Transparently proxify virtual machines +====================================== + +This walkthrough illustrates how to set up transparent proxying with mitmproxy. +We use VirtualBox VMs with an Ubuntu proxy machine in this example, +but the general *Internet <--> Proxy VM <--> (Virtual) Internal Network* setup can be applied to +other setups. + +1. Configure Proxy VM +--------------------- + +On the proxy machine, **eth0** is connected to the internet. **eth1** is connected to the internal +network that will be proxified and configured to use a static ip (192.168.3.1). + +VirtualBox configuration +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: transparent-dhcp/step1_vbox_eth0.png + +.. image:: transparent-dhcp/step1_vbox_eth1.png + +VM Network Configuration +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. image:: transparent-dhcp/step1_proxy.png + :align: center + +2. Configure DHCP and DNS +------------------------- + +We use dnsmasq to provide DHCP and DNS in our internal network. +Dnsmasq is a lightweight server designed to provide DNS (and optionally +DHCP and TFTP) services to a small-scale network. + +- Before we get to that, we need to fix some Ubuntu quirks: + **Ubuntu >12.04** runs an internal dnsmasq instance (listening on loopback only) by default + `[1] <https://www.stgraber.org/2012/02/24/dns-in-ubuntu-12-04/>`_. For our use case, this needs + to be disabled by changing ``dns=dnsmasq`` to ``#dns=dnsmasq`` in + **/etc/NetworkManager/NetworkManager.conf** and running + + >>> sudo restart network-manager + + afterwards. +- Now, dnsmasq can be be installed and configured: + + >>> sudo apt-get install dnsmasq + + Replace **/etc/dnsmasq.conf** with the following configuration: + + .. code-block:: none + + # Listen for DNS requests on the internal network + interface=eth1 + # Act as a DHCP server, assign IP addresses to clients + dhcp-range=192.168.3.10,192.168.3.100,96h + # Broadcast gateway and dns server information + dhcp-option=option:router,192.168.3.1 + dhcp-option=option:dns-server,192.168.3.1 + + Apply changes: + + >>> sudo service dnsmasq restart + + Your **proxied machine** in the internal virtual network should now receive an IP address via DHCP: + + .. image:: transparent-dhcp/step2_proxied_vm.png + +3. Redirect traffic to mitmproxy +------------------------------------------ + +To redirect traffic to mitmproxy, we need to add two iptables rules: + +.. code-block:: none + + iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 8080 + iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 443 -j REDIRECT --to-port 8080 + +4. Run mitmproxy +---------------- + +Finally, we can run mitmproxy in transparent mode with + +>>> mitmproxy -T + +The proxied machine cannot to leak any data outside of HTTP or DNS requests. +If required, you can now :ref:`install the mitmproxy certificates on the proxied machine +<certinstall>`. diff --git a/docs/tutorials/transparent-dhcp/step1_proxy.png b/docs/tutorials/transparent-dhcp/step1_proxy.png Binary files differnew file mode 100644 index 00000000..a0c94484 --- /dev/null +++ b/docs/tutorials/transparent-dhcp/step1_proxy.png diff --git a/docs/tutorials/transparent-dhcp/step1_vbox_eth0.png b/docs/tutorials/transparent-dhcp/step1_vbox_eth0.png Binary files differnew file mode 100644 index 00000000..4b7b4e9b --- /dev/null +++ b/docs/tutorials/transparent-dhcp/step1_vbox_eth0.png diff --git a/docs/tutorials/transparent-dhcp/step1_vbox_eth1.png b/docs/tutorials/transparent-dhcp/step1_vbox_eth1.png Binary files differnew file mode 100644 index 00000000..b994d4cb --- /dev/null +++ b/docs/tutorials/transparent-dhcp/step1_vbox_eth1.png diff --git a/docs/tutorials/transparent-dhcp/step2_proxied_vm.png b/docs/tutorials/transparent-dhcp/step2_proxied_vm.png Binary files differnew file mode 100644 index 00000000..2046cc57 --- /dev/null +++ b/docs/tutorials/transparent-dhcp/step2_proxied_vm.png |