diff options
Diffstat (limited to 'libmproxy/proxy/config.py')
-rw-r--r-- | libmproxy/proxy/config.py | 135 |
1 files changed, 77 insertions, 58 deletions
diff --git a/libmproxy/proxy/config.py b/libmproxy/proxy/config.py index dfde2958..b6d73314 100644 --- a/libmproxy/proxy/config.py +++ b/libmproxy/proxy/config.py @@ -4,7 +4,7 @@ import re from OpenSSL import SSL from netlib import http_auth, certutils, tcp from .. import utils, platform, version -from .primitives import RegularProxyMode, TransparentProxyMode, UpstreamProxyMode, ReverseProxyMode, Socks5ProxyMode +from .primitives import RegularProxyMode, SpoofMode, SSLSpoofMode, TransparentProxyMode, UpstreamProxyMode, ReverseProxyMode, Socks5ProxyMode TRANSPARENT_SSL_PORTS = [443, 8443] CONF_BASENAME = "mitmproxy" @@ -49,9 +49,10 @@ class ProxyConfig: ciphers_server=None, certs=[], certforward=False, - ssl_version_client="secure", - ssl_version_server="secure", - ssl_ports=TRANSPARENT_SSL_PORTS + ssl_version_client=tcp.SSL_DEFAULT_METHOD, + ssl_version_server=tcp.SSL_DEFAULT_METHOD, + ssl_ports=TRANSPARENT_SSL_PORTS, + spoofed_ssl_port=None, ): self.host = host self.port = port @@ -70,6 +71,10 @@ class ProxyConfig: self.mode = ReverseProxyMode(upstream_server) elif mode == "upstream": self.mode = UpstreamProxyMode(upstream_server) + elif mode == "spoof": + self.mode = SpoofMode() + elif mode == "sslspoof": + self.mode = SSLSpoofMode(spoofed_ssl_port) else: self.mode = RegularProxyMode() @@ -81,45 +86,37 @@ class ProxyConfig: self.check_tcp = HostMatcher(tcp_hosts) self.authenticator = authenticator self.cadir = os.path.expanduser(cadir) - self.certstore = certutils.CertStore.from_store(self.cadir, CONF_BASENAME) + self.certstore = certutils.CertStore.from_store( + self.cadir, + CONF_BASENAME) for spec, cert in certs: self.certstore.add_cert_file(spec, cert) self.certforward = certforward - self.openssl_method_client, self.openssl_options_client = version_to_openssl(ssl_version_client) - self.openssl_method_server, self.openssl_options_server = version_to_openssl(ssl_version_server) self.ssl_ports = ssl_ports + if isinstance(ssl_version_client, int): + self.openssl_method_client = ssl_version_client + else: + self.openssl_method_client = tcp.SSL_VERSIONS[ssl_version_client] + if isinstance(ssl_version_server, int): + self.openssl_method_server = ssl_version_server + else: + self.openssl_method_server = tcp.SSL_VERSIONS[ssl_version_server] -sslversion_choices = ("all", "secure", "SSLv2", "SSLv3", "TLSv1", "TLSv1_1", "TLSv1_2") - - -def version_to_openssl(version): - """ - Convert a reasonable SSL version specification into the format OpenSSL expects. - Don't ask... - https://bugs.launchpad.net/pyopenssl/+bug/1020632/comments/3 - """ - if version == "all": - return SSL.SSLv23_METHOD, None - elif version == "secure": - # SSLv23_METHOD + NO_SSLv2 + NO_SSLv3 == TLS 1.0+ - # TLSv1_METHOD would be TLS 1.0 only - return SSL.SSLv23_METHOD, (SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3) - elif version in sslversion_choices: - return getattr(SSL, "%s_METHOD" % version), None - else: - raise ValueError("Invalid SSL version: %s" % version) + self.openssl_options_client = tcp.SSL_DEFAULT_OPTIONS + self.openssl_options_server = tcp.SSL_DEFAULT_OPTIONS def process_proxy_options(parser, options): body_size_limit = utils.parse_size(options.body_size_limit) c = 0 - mode, upstream_server = None, None + mode, upstream_server, spoofed_ssl_port = None, None, None if options.transparent_proxy: c += 1 if not platform.resolver: - return parser.error("Transparent mode not supported on this platform.") + return parser.error( + "Transparent mode not supported on this platform.") mode = "transparent" if options.socks_proxy: c += 1 @@ -132,29 +129,41 @@ def process_proxy_options(parser, options): c += 1 mode = "upstream" upstream_server = options.upstream_proxy + if options.spoof_mode: + c += 1 + mode = "spoof" + if options.ssl_spoof_mode: + c += 1 + mode = "sslspoof" + spoofed_ssl_port = options.spoofed_ssl_port if c > 1: - return parser.error("Transparent, SOCKS5, reverse and upstream proxy mode " - "are mutually exclusive.") + return parser.error( + "Transparent, SOCKS5, reverse and upstream proxy mode " + "are mutually exclusive.") if options.clientcerts: options.clientcerts = os.path.expanduser(options.clientcerts) - if not os.path.exists(options.clientcerts) or not os.path.isdir(options.clientcerts): + if not os.path.exists( + options.clientcerts) or not os.path.isdir( + options.clientcerts): return parser.error( - "Client certificate directory does not exist or is not a directory: %s" % options.clientcerts - ) + "Client certificate directory does not exist or is not a directory: %s" % + options.clientcerts) if (options.auth_nonanonymous or options.auth_singleuser or options.auth_htpasswd): if options.auth_singleuser: if len(options.auth_singleuser.split(':')) != 2: - return parser.error("Invalid single-user specification. Please use the format username:password") + return parser.error( + "Invalid single-user specification. Please use the format username:password") username, password = options.auth_singleuser.split(':') password_manager = http_auth.PassManSingleUser(username, password) elif options.auth_nonanonymous: password_manager = http_auth.PassManNonAnon() elif options.auth_htpasswd: try: - password_manager = http_auth.PassManHtpasswd(options.auth_htpasswd) - except ValueError, v: + password_manager = http_auth.PassManHtpasswd( + options.auth_htpasswd) + except ValueError as v: return parser.error(v.message) authenticator = http_auth.BasicProxyAuth(password_manager, "mitmproxy") else: @@ -196,22 +205,26 @@ def process_proxy_options(parser, options): certforward=options.certforward, ssl_version_client=options.ssl_version_client, ssl_version_server=options.ssl_version_server, - ssl_ports=ssl_ports + ssl_ports=ssl_ports, + spoofed_ssl_port=spoofed_ssl_port ) def ssl_option_group(parser): group = parser.add_argument_group("SSL") group.add_argument( - "--cert", dest='certs', default=[], type=str, - metavar="SPEC", action="append", + "--cert", + dest='certs', + default=[], + type=str, + metavar="SPEC", + action="append", help='Add an SSL certificate. SPEC is of the form "[domain=]path". ' - 'The domain may include a wildcard, and is equal to "*" if not specified. ' - 'The file at path is a certificate in PEM format. If a private key is included 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.' - ) + 'The domain may include a wildcard, and is equal to "*" if not specified. ' + 'The file at path is a certificate in PEM format. If a private key is included 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( "--cert-forward", action="store_true", dest="certforward", default=False, @@ -238,22 +251,28 @@ def ssl_option_group(parser): help="Don't connect to upstream server to look up certificate details." ) group.add_argument( - "--ssl-port", action="append", type=int, dest="ssl_ports", default=list(TRANSPARENT_SSL_PORTS), + "--ssl-port", + action="append", + type=int, + dest="ssl_ports", + default=list(TRANSPARENT_SSL_PORTS), metavar="PORT", help="Can be passed multiple times. Specify destination ports which are assumed to be SSL. " - "Defaults to %s." % str(TRANSPARENT_SSL_PORTS) - ) + "Defaults to %s." % + str(TRANSPARENT_SSL_PORTS)) group.add_argument( - "--ssl-version-client", dest="ssl_version_client", - default="secure", action="store", - choices=sslversion_choices, - help="Set supported SSL/TLS version for client connections. " - "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure." + "--ssl-version-client", dest="ssl_version_client", type=str, default=tcp.SSL_DEFAULT_VERSION, + choices=tcp.SSL_VERSIONS.keys(), + help="""" + Use a specified protocol for client connections: + TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2, SSLv23. + Default to SSLv23.""" ) group.add_argument( - "--ssl-version-server", dest="ssl_version_server", - default="secure", action="store", - choices=sslversion_choices, - help="Set supported SSL/TLS version for server connections. " - "SSLv2, SSLv3 and 'all' are INSECURE. Defaults to secure." + "--ssl-version-server", dest="ssl_version_server", type=str, default=tcp.SSL_DEFAULT_VERSION, + choices=tcp.SSL_VERSIONS.keys(), + help="""" + Use a specified protocol for server connections: + TLSv1.2, TLSv1.1, TLSv1, SSLv3, SSLv2, SSLv23. + Default to SSLv23.""" ) |