diff options
-rw-r--r-- | mitmproxy/options.py | 103 | ||||
-rw-r--r-- | mitmproxy/proxy/config.py | 12 | ||||
-rw-r--r-- | mitmproxy/proxy/protocol/http_replay.py | 4 | ||||
-rw-r--r-- | mitmproxy/proxy/protocol/tls.py | 2 | ||||
-rw-r--r-- | mitmproxy/tools/cmdline.py | 152 | ||||
-rw-r--r-- | test/mitmproxy/proxy/test_server.py | 8 | ||||
-rw-r--r-- | test/mitmproxy/test_proxy.py | 4 | ||||
-rw-r--r-- | test/mitmproxy/tools/test_cmdline.py | 4 |
8 files changed, 126 insertions, 163 deletions
diff --git a/mitmproxy/options.py b/mitmproxy/options.py index 58907ef3..ec270076 100644 --- a/mitmproxy/options.py +++ b/mitmproxy/options.py @@ -27,7 +27,14 @@ class Options(optmanager.OptManager): "onboarding", True, bool, "Toggle the mitmproxy onboarding app." ) - self.add_option("onboarding_host", APP_HOST, str) + self.add_option( + "onboarding_host", APP_HOST, str, + """ + Domain to serve the onboarding app from. For transparent mode, use + an IP when a DNS entry for the app domain is not present. Default: + %s + """ % APP_HOST + ) self.add_option( "onboarding_port", APP_PORT, int, help="Port to serve the onboarding app from." @@ -64,7 +71,10 @@ class Options(optmanager.OptManager): self.add_option( "refresh_server_playback", True, bool, ) - self.add_option("rfile", None, Optional[str]) + self.add_option( + "rfile", None, Optional[str], + "Read flows from file." + ) self.add_option("scripts", [], Sequence[str]) self.add_option( "showhost", False, bool, @@ -75,8 +85,14 @@ class Options(optmanager.OptManager): self.add_option("server_replay_use_headers", [], Sequence[str]) self.add_option("setheaders", [], Sequence[Union[Tuple[str, str, str], str]]) self.add_option("server_replay", [], Sequence[str]) - self.add_option("stickycookie", None, Optional[str]) - self.add_option("stickyauth", None, Optional[str]) + self.add_option( + "stickycookie", None, Optional[str], + "Set sticky cookie filter. Matched against requests." + ) + self.add_option( + "stickyauth", None, Optional[str], + "Set sticky auth filter. Matched against requests." + ) self.add_option( "stream_large_bodies", None, Optional[str], """ @@ -109,8 +125,17 @@ class Options(optmanager.OptManager): "auth_nonanonymous", False, bool, "Allow access to any user long as a credentials are specified." ) - self.add_option("auth_singleuser", None, Optional[str]) - self.add_option("auth_htpasswd", None, Optional[str]) + self.add_option( + "auth_singleuser", None, Optional[str], + """ + Allows access to a a single user, specified in the form + username:password. + """ + ) + self.add_option( + "auth_htpasswd", None, Optional[str], + "Allow access to users specified in an Apache htpasswd file." + ) self.add_option( "add_upstream_certs_to_client_chain", False, bool, "Add all certificates of the upstream server to the certificate chain " @@ -121,18 +146,36 @@ class Options(optmanager.OptManager): "Byte size limit of HTTP request and response bodies." " Understands k/m/g suffixes, i.e. 3m for 3 megabytes." ) - self.add_option("cadir", CA_DIR, str) + self.add_option( + "cadir", CA_DIR, str, + "Location of the default mitmproxy CA files. (%s)" % CA_DIR + ) self.add_option("certs", [], Sequence[Tuple[str, str]]) - self.add_option("ciphers_client", DEFAULT_CLIENT_CIPHERS, str) - self.add_option("ciphers_server", None, Optional[str]) - self.add_option("clientcerts", None, Optional[str]) + self.add_option( + "ciphers_client", DEFAULT_CLIENT_CIPHERS, str, + "Set supported ciphers for client connections. (OpenSSL Syntax)" + ) + self.add_option( + "ciphers_server", None, Optional[str], + "Set supported ciphers for server connections. (OpenSSL Syntax)" + ) + self.add_option( + "client_certs", None, Optional[str], + "Client certificate file or directory." + ) self.add_option("ignore_hosts", [], Sequence[str]) - self.add_option("listen_host", "", str) + self.add_option( + "listen_host", "", str, + "Address to bind proxy to (defaults to all interfaces)" + ) self.add_option( "listen_port", LISTEN_PORT, int, "Proxy service port." ) - self.add_option("upstream_bind_address", "", str) + self.add_option( + "upstream_bind_address", "", str, + "Address to bind upstream requests to (defaults to none)" + ) self.add_option("mode", "regular", str) self.add_option( "upstream_cert", True, bool, @@ -172,23 +215,39 @@ class Options(optmanager.OptManager): "Combine with --upstream-bind-address to spoof a fixed source address." ) self.add_option("upstream_server", None, Optional[str]) - self.add_option("upstream_auth", None, Optional[str]) + self.add_option( + "upstream_auth", None, Optional[str], + """ + Add HTTP Basic authentcation to upstream proxy and reverse proxy + requests. Format: username:password + """ + ) self.add_option("ssl_version_client", "secure", str) self.add_option("ssl_version_server", "secure", str) self.add_option( "ssl_insecure", False, bool, "Do not verify upstream server SSL/TLS certificates." ) - self.add_option("ssl_verify_upstream_trusted_cadir", None, Optional[str]) - self.add_option("ssl_verify_upstream_trusted_ca", None, Optional[str]) + self.add_option( + "ssl_verify_upstream_trusted_cadir", None, Optional[str], + "Path to a directory of trusted CA certificates for upstream " + "server verification prepared using the c_rehash tool." + ) + self.add_option( + "ssl_verify_upstream_trusted_ca", None, Optional[str], + "Path to a PEM formatted trusted CA certificate." + ) self.add_option("tcp_hosts", [], Sequence[str]) - self.add_option("intercept", None, Optional[str]) + self.add_option( + "intercept", None, Optional[str], + "Intercept filter expression." + ) # Console options self.add_option( "console_eventlog", False, bool, - help="Show event log." + "Show event log." ) self.add_option( "console_focus_follow", False, bool, @@ -208,7 +267,10 @@ class Options(optmanager.OptManager): "console_order_reversed", False, bool, ) - self.add_option("filter", None, Optional[str]) + self.add_option( + "filter", None, Optional[str], + "Filter view expression." + ) # Web options self.add_option( @@ -223,7 +285,10 @@ class Options(optmanager.OptManager): "web_port", 8081, int, "Mitmweb port." ) - self.add_option("web_iface", "127.0.0.1", str) + self.add_option( + "web_iface", "127.0.0.1", str, + "Mitmweb interface." + ) # Dump options self.add_option("filtstr", None, Optional[str]) diff --git a/mitmproxy/proxy/config.py b/mitmproxy/proxy/config.py index ea2f7c7f..778fd306 100644 --- a/mitmproxy/proxy/config.py +++ b/mitmproxy/proxy/config.py @@ -59,7 +59,7 @@ class ProxyConfig: self.check_ignore = None self.check_tcp = None self.certstore = None - self.clientcerts = None + self.client_certs = None self.openssl_verification_mode_server = None self.configure(options, set(options.keys())) options.changed.connect(self.configure) @@ -96,14 +96,14 @@ class ProxyConfig: CONF_BASENAME ) - if options.clientcerts: - clientcerts = os.path.expanduser(options.clientcerts) - if not os.path.exists(clientcerts): + if options.client_certs: + client_certs = os.path.expanduser(options.client_certs) + if not os.path.exists(client_certs): raise exceptions.OptionsError( "Client certificate path does not exist: %s" % - options.clientcerts + options.client_certs ) - self.clientcerts = clientcerts + self.client_certs = client_certs for spec, cert in options.certs: cert = os.path.expanduser(cert) diff --git a/mitmproxy/proxy/protocol/http_replay.py b/mitmproxy/proxy/protocol/http_replay.py index c47f2e8f..161816e7 100644 --- a/mitmproxy/proxy/protocol/http_replay.py +++ b/mitmproxy/proxy/protocol/http_replay.py @@ -61,7 +61,7 @@ class RequestReplayThread(basethread.BaseThread): if resp.status_code != 200: raise exceptions.ReplayException("Upstream server refuses CONNECT request") server.establish_ssl( - self.config.clientcerts, + self.config.client_certs, sni=self.f.server_conn.sni ) r.first_line_format = "relative" @@ -76,7 +76,7 @@ class RequestReplayThread(basethread.BaseThread): server.connect() if r.scheme == "https": server.establish_ssl( - self.config.clientcerts, + self.config.client_certs, sni=self.f.server_conn.sni ) r.first_line_format = "relative" diff --git a/mitmproxy/proxy/protocol/tls.py b/mitmproxy/proxy/protocol/tls.py index 103d96cc..acc0c6e3 100644 --- a/mitmproxy/proxy/protocol/tls.py +++ b/mitmproxy/proxy/protocol/tls.py @@ -527,7 +527,7 @@ class TlsLayer(base.Layer): ciphers_server = ':'.join(ciphers_server) self.server_conn.establish_ssl( - self.config.clientcerts, + self.config.client_certs, self.server_sni, method=self.config.openssl_method_server, options=self.config.openssl_options_server, diff --git a/mitmproxy/tools/cmdline.py b/mitmproxy/tools/cmdline.py index def2ae31..fc584869 100644 --- a/mitmproxy/tools/cmdline.py +++ b/mitmproxy/tools/cmdline.py @@ -17,13 +17,6 @@ class ParseException(Exception): def get_common_options(args): - stickycookie, stickyauth = None, None - if args.stickycookie_filt: - stickycookie = args.stickycookie_filt - - if args.stickyauth_filt: - stickyauth = args.stickyauth_filt - if args.streamfile and args.streamfile[0] == args.rfile: if args.streamfile[1] == "wb": raise exceptions.OptionsError( @@ -101,8 +94,8 @@ def get_common_options(args): keep_host_header=args.keep_host_header, server_replay=args.server_replay, scripts=args.scripts, - stickycookie=stickycookie, - stickyauth=stickyauth, + stickycookie=args.stickycookie, + stickyauth=args.stickyauth, stream_large_bodies=args.stream_large_bodies, showhost=args.showhost, streamfile=args.streamfile[0] if args.streamfile else None, @@ -123,9 +116,9 @@ def get_common_options(args): certs = certs, ciphers_client = args.ciphers_client, ciphers_server = args.ciphers_server, - clientcerts = args.clientcerts, + client_certs = args.client_certs, ignore_hosts = args.ignore_hosts, - listen_host = args.listen_addr, + listen_host = args.listen_host, listen_port = args.listen_port, upstream_bind_address = args.upstream_bind_address, mode = mode, @@ -161,22 +154,14 @@ def basic_options(parser, opts): version=version.VERSION ) opts.make_parser(parser, "anticache") - parser.add_argument( - "--cadir", - action="store", type=str, dest="cadir", - help="Location of the default mitmproxy CA files. (%s)" % options.CA_DIR - ) + opts.make_parser(parser, "cadir") opts.make_parser(parser, "showhost") parser.add_argument( "-q", "--quiet", action="store_true", dest="quiet", help="Quiet." ) - parser.add_argument( - "-r", "--read-flows", - action="store", dest="rfile", - help="Read flows from file." - ) + opts.make_parser(parser, "rfile") parser.add_argument( "-s", "--script", action="append", type=str, dest="scripts", @@ -186,18 +171,8 @@ def basic_options(parser, opts): passed multiple times. """ ) - parser.add_argument( - "-t", "--stickycookie", - action="store", - dest="stickycookie_filt", - metavar="FILTER", - help="Set sticky cookie filter. Matched against requests." - ) - parser.add_argument( - "-u", "--stickyauth", - action="store", dest="stickyauth_filt", metavar="FILTER", - help="Set sticky auth filter. Matched against requests." - ) + opts.make_parser(parser, "stickycookie", metavar="FILTER") + opts.make_parser(parser, "stickyauth", metavar="FILTER") parser.add_argument( "-v", "--verbose", action="store_const", dest="verbose", const=3, @@ -254,11 +229,7 @@ def proxy_modes(parser, opts): def proxy_options(parser, opts): group = parser.add_argument_group("Proxy Options") - group.add_argument( - "-b", "--bind-address", - action="store", type=str, dest="listen_addr", - help="Address to bind proxy to (defaults to all interfaces)" - ) + opts.make_parser(group, "listen_host") group.add_argument( "-I", "--ignore", action="append", type=str, dest="ignore_hosts", @@ -292,24 +263,10 @@ def proxy_options(parser, opts): websocket = group.add_mutually_exclusive_group() opts.make_parser(websocket, "websocket") - parser.add_argument( - "--upstream-auth", - action="store", dest="upstream_auth", - type=str, - help=""" - Add HTTP Basic authentcation to upstream proxy and reverse proxy - requests. Format: username:password - """ - ) - + opts.make_parser(group, "upstream_auth", metavar="USER:PASS") opts.make_parser(group, "rawtcp") - opts.make_parser(group, "spoof_source_address") - group.add_argument( - "--upstream-bind-address", - action="store", type=str, dest="upstream_bind_address", - help="Address to bind upstream requests to (defaults to none)" - ) + opts.make_parser(group, "upstream_bind_address", metavar="ADDR") opts.make_parser(group, "keep_host_header") @@ -328,35 +285,14 @@ def proxy_ssl_options(parser, opts): 'in the PEM, it is used, else the default key in the conf dir is used. ' 'The PEM file should contain the full certificate chain, with the leaf certificate ' 'as the first entry. Can be passed multiple times.') - group.add_argument( - "--ciphers-client", action="store", - type=str, dest="ciphers_client", - help="Set supported ciphers for client connections. (OpenSSL Syntax)" - ) - group.add_argument( - "--ciphers-server", action="store", - type=str, dest="ciphers_server", - help="Set supported ciphers for server connections. (OpenSSL Syntax)" - ) - group.add_argument( - "--client-certs", action="store", - type=str, dest="clientcerts", - help="Client certificate file or directory." - ) + opts.make_parser(group, "ciphers_server", metavar="CIPHERS") + opts.make_parser(group, "ciphers_client", metavar="CIPHERS") + opts.make_parser(group, "client_certs") opts.make_parser(group, "upstream_cert") opts.make_parser(group, "add_upstream_certs_to_client_chain") opts.make_parser(group, "ssl_insecure") - group.add_argument( - "--upstream-trusted-cadir", action="store", - dest="ssl_verify_upstream_trusted_cadir", - help="Path to a directory of trusted CA certificates for upstream " - "server verification prepared using the c_rehash tool." - ) - group.add_argument( - "--upstream-trusted-ca", action="store", - dest="ssl_verify_upstream_trusted_ca", - help="Path to a PEM formatted trusted CA certificate." - ) + opts.make_parser(group, "ssl_verify_upstream_trusted_cadir", metavar="PATH") + opts.make_parser(group, "ssl_verify_upstream_trusted_ca", metavar="PATH") group.add_argument( "--ssl-version-client", dest="ssl_version_client", action="store", @@ -375,16 +311,8 @@ def proxy_ssl_options(parser, opts): def onboarding_app(parser, opts): group = parser.add_argument_group("Onboarding App") - opts.make_parser(parser, "onboarding") - group.add_argument( - "--onboarding-host", - action="store", dest="onboarding_host", - help=""" - Domain to serve the onboarding app from. For transparent mode, use - an IP when a DNS entry for the app domain is not present. Default: - %s - """ % options.APP_HOST - ) + opts.make_parser(group, "onboarding") + opts.make_parser(group, "onboarding_host", metavar="HOST") opts.make_parser(group, "onboarding_port", metavar="PORT") @@ -488,21 +416,8 @@ def proxy_authentication(parser, opts): """ ).add_mutually_exclusive_group() opts.make_parser(group, "auth_nonanonymous") - group.add_argument( - "--singleuser", - action="store", dest="auth_singleuser", type=str, - metavar="USER", - help=""" - Allows access to a a single user, specified in the form - username:password. - """ - ) - group.add_argument( - "--htpasswd", - action="store", dest="auth_htpasswd", type=str, - metavar="PATH", - help="Allow access to users specified in an Apache htpasswd file." - ) + opts.make_parser(group, "auth_singleuser", metavar="USER:PASS") + opts.make_parser(group, "auth_htpasswd", metavar="PATH") def common_options(parser, opts): @@ -553,16 +468,8 @@ def mitmproxy(opts): "Filters", "See help in mitmproxy for filter expression syntax." ) - group.add_argument( - "-i", "--intercept", action="store", - type=str, dest="intercept", - help="Intercept filter expression." - ) - group.add_argument( - "-f", "--filter", action="store", - type=str, dest="filter", - help="Filter view expression." - ) + opts.make_parser(group, "intercept", metavar="FILTER") + opts.make_parser(group, "filter", metavar="FILTER") return parser @@ -588,13 +495,8 @@ def mitmweb(opts): group = parser.add_argument_group("Mitmweb") opts.make_parser(group, "web_open_browser") - opts.make_parser(parser, "web_port", metavar="PORT") - group.add_argument( - "--web-iface", - action="store", dest="web_iface", - metavar="IFACE", - help="Mitmweb interface." - ) + opts.make_parser(group, "web_port", metavar="PORT") + opts.make_parser(group, "web_iface", metavar="INTERFACE") opts.make_parser(group, "web_debug") common_options(parser, opts) @@ -602,9 +504,5 @@ def mitmweb(opts): "Filters", "See help in mitmproxy for filter expression syntax." ) - group.add_argument( - "-i", "--intercept", action="store", - type=str, dest="intercept", - help="Intercept filter expression." - ) + opts.make_parser(group, "intercept", metavar="FILTER") return parser diff --git a/test/mitmproxy/proxy/test_server.py b/test/mitmproxy/proxy/test_server.py index eb40dd14..bcfecf6f 100644 --- a/test/mitmproxy/proxy/test_server.py +++ b/test/mitmproxy/proxy/test_server.py @@ -342,22 +342,22 @@ class TestHTTPS(tservers.HTTPProxyTest, CommonMixin, TcpMixin): def test_clientcert_file(self): try: - self.config.clientcerts = os.path.join( + self.config.client_certs = os.path.join( tutils.test_data.path("mitmproxy/data/clientcert"), "client.pem") f = self.pathod("304") assert f.status_code == 304 assert self.server.last_log()["request"]["clientcert"]["keyinfo"] finally: - self.config.clientcerts = None + self.config.client_certs = None def test_clientcert_dir(self): try: - self.config.clientcerts = tutils.test_data.path("mitmproxy/data/clientcert") + self.config.client_certs = tutils.test_data.path("mitmproxy/data/clientcert") f = self.pathod("304") assert f.status_code == 304 assert self.server.last_log()["request"]["clientcert"]["keyinfo"] finally: - self.config.clientcerts = None + self.config.client_certs = None def test_error_post_connect(self): p = self.pathoc() diff --git a/test/mitmproxy/test_proxy.py b/test/mitmproxy/test_proxy.py index 6e360875..5dd4a9e3 100644 --- a/test/mitmproxy/test_proxy.py +++ b/test/mitmproxy/test_proxy.py @@ -96,12 +96,12 @@ class TestProcessProxyOptions: def test_upstream_trusted_cadir(self): expected_dir = "/path/to/a/ca/dir" - p = self.assert_noerr("--upstream-trusted-cadir", expected_dir) + p = self.assert_noerr("--ssl-verify-upstream-trusted-cadir", expected_dir) assert p.options.ssl_verify_upstream_trusted_cadir == expected_dir def test_upstream_trusted_ca(self): expected_file = "/path/to/a/cert/file" - p = self.assert_noerr("--upstream-trusted-ca", expected_file) + p = self.assert_noerr("--ssl-verify-upstream-trusted-ca", expected_file) assert p.options.ssl_verify_upstream_trusted_ca == expected_file diff --git a/test/mitmproxy/tools/test_cmdline.py b/test/mitmproxy/tools/test_cmdline.py index b9f9d00d..bae68f83 100644 --- a/test/mitmproxy/tools/test_cmdline.py +++ b/test/mitmproxy/tools/test_cmdline.py @@ -11,8 +11,8 @@ def test_common(): assert cmdline.get_common_options(args) - args.stickycookie_filt = "foo" - args.stickyauth_filt = "foo" + args.stickycookie = "foo" + args.stickyauth = "foo" v = cmdline.get_common_options(args) assert v["stickycookie"] == "foo" assert v["stickyauth"] == "foo" |