diff options
author | Maximilian Hils <git@maximilianhils.com> | 2015-08-08 16:08:57 +0200 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2015-08-11 20:32:13 +0200 |
commit | 026330a3b014f24f095b839b29186036854de3bc (patch) | |
tree | c5770ef28332b61f56b5435136e8dcd95340ed1d /libmproxy/protocol2 | |
parent | 314e0f5839fcd4a1c35323f61938b207232de287 (diff) | |
download | mitmproxy-026330a3b014f24f095b839b29186036854de3bc.tar.gz mitmproxy-026330a3b014f24f095b839b29186036854de3bc.tar.bz2 mitmproxy-026330a3b014f24f095b839b29186036854de3bc.zip |
cleaner Exceptions, ssl -> tls, upstream proxy mode
Diffstat (limited to 'libmproxy/protocol2')
-rw-r--r-- | libmproxy/protocol2/__init__.py | 3 | ||||
-rw-r--r-- | libmproxy/protocol2/auto.py | 4 | ||||
-rw-r--r-- | libmproxy/protocol2/layer.py | 10 | ||||
-rw-r--r-- | libmproxy/protocol2/messages.py | 4 | ||||
-rw-r--r-- | libmproxy/protocol2/rawtcp.py | 8 | ||||
-rw-r--r-- | libmproxy/protocol2/reverse_proxy.py | 10 | ||||
-rw-r--r-- | libmproxy/protocol2/socks.py | 6 | ||||
-rw-r--r-- | libmproxy/protocol2/tls.py (renamed from libmproxy/protocol2/ssl.py) | 84 | ||||
-rw-r--r-- | libmproxy/protocol2/transparent_proxy.py | 24 | ||||
-rw-r--r-- | libmproxy/protocol2/upstream_proxy.py | 18 |
10 files changed, 112 insertions, 59 deletions
diff --git a/libmproxy/protocol2/__init__.py b/libmproxy/protocol2/__init__.py index 3f714f62..0d232b13 100644 --- a/libmproxy/protocol2/__init__.py +++ b/libmproxy/protocol2/__init__.py @@ -2,6 +2,7 @@ from __future__ import (absolute_import, print_function, division) from .layer import RootContext from .socks import Socks5IncomingLayer from .reverse_proxy import ReverseProxy +from .upstream_proxy import UpstreamProxy from .rawtcp import TcpLayer from .auto import AutoLayer -__all__ = ["Socks5IncomingLayer", "TcpLayer", "AutoLayer", "RootContext", "ReverseProxy"] +__all__ = ["Socks5IncomingLayer", "TcpLayer", "AutoLayer", "RootContext", "ReverseProxy", "UpstreamProxy"] diff --git a/libmproxy/protocol2/auto.py b/libmproxy/protocol2/auto.py index fc111758..4a930720 100644 --- a/libmproxy/protocol2/auto.py +++ b/libmproxy/protocol2/auto.py @@ -10,11 +10,11 @@ class AutoLayer(Layer): return # TLS ClientHello magic, see http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html#client-hello if d[0] == "\x16": - layer = SslLayer(self, True, True) + layer = TlsLayer(self, True, True) else: layer = TcpLayer(self) for m in layer(): yield m from .rawtcp import TcpLayer -from .ssl import SslLayer +from .tls import TlsLayer diff --git a/libmproxy/protocol2/layer.py b/libmproxy/protocol2/layer.py index c18be83c..8aede22e 100644 --- a/libmproxy/protocol2/layer.py +++ b/libmproxy/protocol2/layer.py @@ -35,9 +35,10 @@ from __future__ import (absolute_import, print_function, division) import Queue import threading from netlib import tcp -from ..proxy import ProxyError2, Log +from ..proxy import Log from ..proxy.connection import ServerConnection from .messages import Connect, Reconnect, ChangeServer +from ..exceptions import ProtocolException class RootContext(object): @@ -51,6 +52,9 @@ class RootContext(object): self.channel = channel # provides .ask() method to communicate with FlowMaster self.config = config # Proxy Configuration + def next_layer(self): + print(type(self)) + class _LayerCodeCompletion(object): """ @@ -149,7 +153,7 @@ class ServerConnectionMixin(object): try: self.server_conn.connect() except tcp.NetLibError as e: - raise ProxyError2("Server connection to '%s' failed: %s" % (self.server_address, e), e) + raise ProtocolException("Server connection to '%s' failed: %s" % (self.server_address, e), e) def yield_from_callback(fun): @@ -197,7 +201,7 @@ def yield_from_callback(fun): break elif isinstance(msg, Exception): # TODO: Include func name? - raise ProxyError2("Error in %s: %s" % (fun.__name__, repr(msg)), msg) + raise ProtocolException("Error in %s: %s" % (fun.__name__, repr(msg)), msg) else: yield msg yield_queue.put(None) diff --git a/libmproxy/protocol2/messages.py b/libmproxy/protocol2/messages.py index baf4312d..3f53fbd4 100644 --- a/libmproxy/protocol2/messages.py +++ b/libmproxy/protocol2/messages.py @@ -32,9 +32,9 @@ class ChangeServer(_Message): Change the upstream server. """ - def __init__(self, address, server_ssl, sni, depth=1): + def __init__(self, address, server_tls, sni, depth=1): self.address = address - self.server_ssl = server_ssl + self.server_tls = server_tls self.sni = sni # upstream proxy scenario: you may want to change either the final target or the upstream proxy. diff --git a/libmproxy/protocol2/rawtcp.py b/libmproxy/protocol2/rawtcp.py index 39e48e24..608a53e3 100644 --- a/libmproxy/protocol2/rawtcp.py +++ b/libmproxy/protocol2/rawtcp.py @@ -1,4 +1,6 @@ from __future__ import (absolute_import, print_function, division) +import OpenSSL +from ..exceptions import ProtocolException from ..protocol.tcp import TCPHandler from .layer import Layer from .messages import Connect @@ -8,7 +10,11 @@ class TcpLayer(Layer): def __call__(self): yield Connect() tcp_handler = TCPHandler(self) - tcp_handler.handle_messages() + try: + tcp_handler.handle_messages() + except OpenSSL.SSL.Error as e: + raise ProtocolException("SSL error: %s" % repr(e), e) + def establish_server_connection(self): pass diff --git a/libmproxy/protocol2/reverse_proxy.py b/libmproxy/protocol2/reverse_proxy.py index dfffd2f2..cb6d1d78 100644 --- a/libmproxy/protocol2/reverse_proxy.py +++ b/libmproxy/protocol2/reverse_proxy.py @@ -1,19 +1,19 @@ from __future__ import (absolute_import, print_function, division) from .layer import Layer, ServerConnectionMixin -from .ssl import SslLayer +from .tls import TlsLayer class ReverseProxy(Layer, ServerConnectionMixin): - def __init__(self, ctx, server_address, client_ssl, server_ssl): + def __init__(self, ctx, server_address, client_tls, server_tls): super(ReverseProxy, self).__init__(ctx) self.server_address = server_address - self.client_ssl = client_ssl - self.server_ssl = server_ssl + self._client_tls = client_tls + self._server_tls = server_tls def __call__(self): - layer = SslLayer(self, self.client_ssl, self.server_ssl) + layer = TlsLayer(self, self._client_tls, self._server_tls) for message in layer(): if not self._handle_server_message(message): yield message diff --git a/libmproxy/protocol2/socks.py b/libmproxy/protocol2/socks.py index 14564521..1222ef5c 100644 --- a/libmproxy/protocol2/socks.py +++ b/libmproxy/protocol2/socks.py @@ -1,10 +1,10 @@ from __future__ import (absolute_import, print_function, division) -from ..proxy import ProxyError, Socks5ProxyMode, ProxyError2 +from ..exceptions import ProtocolException +from ..proxy import ProxyError, Socks5ProxyMode from .layer import Layer, ServerConnectionMixin from .auto import AutoLayer - class Socks5IncomingLayer(Layer, ServerConnectionMixin): def __call__(self): try: @@ -12,7 +12,7 @@ class Socks5IncomingLayer(Layer, ServerConnectionMixin): address = s5mode.get_upstream_server(self.client_conn)[2:] except ProxyError as e: # TODO: Unmonkeypatch - raise ProxyError2(str(e), e) + raise ProtocolException(str(e), e) self.server_address = address diff --git a/libmproxy/protocol2/ssl.py b/libmproxy/protocol2/tls.py index a744a979..2362b2b2 100644 --- a/libmproxy/protocol2/ssl.py +++ b/libmproxy/protocol2/tls.py @@ -2,17 +2,17 @@ from __future__ import (absolute_import, print_function, division) import traceback from netlib import tcp -from ..proxy import ProxyError2 +from ..exceptions import ProtocolException from .layer import Layer, yield_from_callback from .messages import Connect, Reconnect, ChangeServer from .auto import AutoLayer -class SslLayer(Layer): - def __init__(self, ctx, client_ssl, server_ssl): - super(SslLayer, self).__init__(ctx) - self._client_ssl = client_ssl - self._server_ssl = server_ssl +class TlsLayer(Layer): + def __init__(self, ctx, client_tls, server_tls): + super(TlsLayer, self).__init__(ctx) + self._client_tls = client_tls + self._server_tls = server_tls self._connected = False self.client_sni = None self._sni_from_server_change = None @@ -41,33 +41,34 @@ class SslLayer(Layer): https://www.openssl.org/docs/ssl/SSL_CTX_set_cert_cb.html - The original mitmproxy issue is https://github.com/mitmproxy/mitmproxy/issues/427 """ - client_ssl_requires_server_cert = ( - self._client_ssl and self._server_ssl and not self.config.no_upstream_cert + client_tls_requires_server_cert = ( + self._client_tls and self._server_tls and not self.config.no_upstream_cert ) - lazy_server_ssl = ( - self._server_ssl and not client_ssl_requires_server_cert + lazy_server_tls = ( + self._server_tls and not client_tls_requires_server_cert ) - if client_ssl_requires_server_cert: - for m in self._establish_ssl_with_client_and_server(): + if client_tls_requires_server_cert: + for m in self._establish_tls_with_client_and_server(): yield m - elif self.client_ssl: - for m in self._establish_ssl_with_client(): + elif self._client_tls: + for m in self._establish_tls_with_client(): yield m + self.next_layer() layer = AutoLayer(self) for message in layer(): if message != Connect or not self._connected: yield message if message == Connect: - if lazy_server_ssl: - self._establish_ssl_with_server() + if lazy_server_tls: + self._establish_tls_with_server() if message == ChangeServer and message.depth == 1: - self.server_ssl = message.server_ssl + self._server_tls = message.server_tls self._sni_from_server_change = message.sni if message == Reconnect or message == ChangeServer: - if self.server_ssl: - self._establish_ssl_with_server() + if self._server_tls: + self._establish_tls_with_server() @property def sni_for_upstream_connection(self): @@ -76,7 +77,7 @@ class SslLayer(Layer): else: return self._sni_from_server_change or self.client_sni - def _establish_ssl_with_client_and_server(self): + def _establish_tls_with_client_and_server(self): """ This function deals with the problem that the server may require a SNI value from the client. """ @@ -86,14 +87,14 @@ class SslLayer(Layer): self._connected = True server_err = None try: - self._establish_ssl_with_server() - except ProxyError2 as e: + self._establish_tls_with_server() + except ProtocolException as e: server_err = e - for message in self._establish_ssl_with_client(): + for message in self._establish_tls_with_client(): if message == Reconnect: yield message - self._establish_ssl_with_server() + self._establish_tls_with_server() else: raise RuntimeError("Unexpected Message: %s" % message) @@ -102,7 +103,7 @@ class SslLayer(Layer): def handle_sni(self, connection): """ - This callback gets called during the SSL handshake with the client. + This callback gets called during the TLS handshake with the client. The client has just sent the Sever Name Indication (SNI). """ try: @@ -115,7 +116,7 @@ class SslLayer(Layer): if old_upstream_sni != self.sni_for_upstream_connection: # Perform reconnect - if self.server_ssl: + if self._server_tls: self.yield_from_callback(Reconnect()) if self.client_sni: @@ -136,8 +137,8 @@ class SslLayer(Layer): self.log("Error in handle_sni:\r\n" + traceback.format_exc(), "error") @yield_from_callback - def _establish_ssl_with_client(self): - self.log("Establish SSL with client", "debug") + def _establish_tls_with_client(self): + self.log("Establish TLS with client", "debug") cert, key, chain_file = self.find_cert() try: self.client_conn.convert_to_ssl( @@ -150,10 +151,10 @@ class SslLayer(Layer): chain_file=chain_file ) except tcp.NetLibError as e: - raise ProxyError2(repr(e), e) + raise ProtocolException(repr(e), e) - def _establish_ssl_with_server(self): - self.log("Establish SSL with server", "debug") + def _establish_tls_with_server(self): + self.log("Establish TLS with server", "debug") try: self.server_conn.establish_ssl( self.config.clientcerts, @@ -165,30 +166,29 @@ class SslLayer(Layer): ca_pemfile=self.config.openssl_trusted_ca_server, cipher_list=self.config.ciphers_server, ) - ssl_cert_err = self.server_conn.ssl_verification_error - if ssl_cert_err is not None: + tls_cert_err = self.server_conn.ssl_verification_error + if tls_cert_err is not None: self.log( - "SSL verification failed for upstream server at depth %s with error: %s" % - (ssl_cert_err['depth'], ssl_cert_err['errno']), + "TLS verification failed for upstream server at depth %s with error: %s" % + (tls_cert_err['depth'], tls_cert_err['errno']), "error") self.log("Ignoring server verification error, continuing with connection", "error") except tcp.NetLibInvalidCertificateError as e: - ssl_cert_err = self.server_conn.ssl_verification_error + tls_cert_err = self.server_conn.ssl_verification_error self.log( - "SSL verification failed for upstream server at depth %s with error: %s" % - (ssl_cert_err['depth'], ssl_cert_err['errno']), + "TLS verification failed for upstream server at depth %s with error: %s" % + (tls_cert_err['depth'], tls_cert_err['errno']), "error") self.log("Aborting connection attempt", "error") - raise ProxyError2(repr(e), e) + raise ProtocolException(repr(e), e) except tcp.NetLibError as e: - raise ProxyError2(repr(e), e) + raise ProtocolException(repr(e), e) def find_cert(self): host = self.server_conn.address.host - # TODO: Better use an OrderedSet here sans = set() # Incorporate upstream certificate - if self.server_conn.ssl_established and (not self.config.no_upstream_cert): + if self.server_conn.tls_established and (not self.config.no_upstream_cert): upstream_cert = self.server_conn.cert sans.update(upstream_cert.altnames) if upstream_cert.cn: diff --git a/libmproxy/protocol2/transparent_proxy.py b/libmproxy/protocol2/transparent_proxy.py new file mode 100644 index 00000000..078954c2 --- /dev/null +++ b/libmproxy/protocol2/transparent_proxy.py @@ -0,0 +1,24 @@ +from __future__ import (absolute_import, print_function, division) + +from ..exceptions import ProtocolException +from .. import platform +from .layer import Layer, ServerConnectionMixin +from .auto import AutoLayer + + +class TransparentProxy(Layer, ServerConnectionMixin): + + def __init__(self, ctx): + super(TransparentProxy, self).__init__(ctx) + self.resolver = platform.resolver() + + def __call__(self): + try: + self.server_address = self.resolver.original_addr(self.client_conn.connection) + except Exception as e: + raise ProtocolException("Transparent mode failure: %s" % repr(e), e) + + layer = AutoLayer(self) + for message in layer(): + if not self._handle_server_message(message): + yield message diff --git a/libmproxy/protocol2/upstream_proxy.py b/libmproxy/protocol2/upstream_proxy.py new file mode 100644 index 00000000..bd920309 --- /dev/null +++ b/libmproxy/protocol2/upstream_proxy.py @@ -0,0 +1,18 @@ +from __future__ import (absolute_import, print_function, division) + +from .layer import Layer, ServerConnectionMixin +#from .http import HttpLayer + + +class UpstreamProxy(Layer, ServerConnectionMixin): + + def __init__(self, ctx, server_address): + super(UpstreamProxy, self).__init__(ctx) + self.server_address = server_address + + def __call__(self): + #layer = HttpLayer(self) + layer = None + for message in layer(): + if not self._handle_server_message(message): + yield message |