aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2015-08-08 16:08:57 +0200
committerMaximilian Hils <git@maximilianhils.com>2015-08-11 20:32:13 +0200
commit026330a3b014f24f095b839b29186036854de3bc (patch)
treec5770ef28332b61f56b5435136e8dcd95340ed1d
parent314e0f5839fcd4a1c35323f61938b207232de287 (diff)
downloadmitmproxy-026330a3b014f24f095b839b29186036854de3bc.tar.gz
mitmproxy-026330a3b014f24f095b839b29186036854de3bc.tar.bz2
mitmproxy-026330a3b014f24f095b839b29186036854de3bc.zip
cleaner Exceptions, ssl -> tls, upstream proxy mode
-rw-r--r--libmproxy/exceptions.py22
-rw-r--r--libmproxy/protocol2/__init__.py3
-rw-r--r--libmproxy/protocol2/auto.py4
-rw-r--r--libmproxy/protocol2/layer.py10
-rw-r--r--libmproxy/protocol2/messages.py4
-rw-r--r--libmproxy/protocol2/rawtcp.py8
-rw-r--r--libmproxy/protocol2/reverse_proxy.py10
-rw-r--r--libmproxy/protocol2/socks.py6
-rw-r--r--libmproxy/protocol2/tls.py (renamed from libmproxy/protocol2/ssl.py)84
-rw-r--r--libmproxy/protocol2/transparent_proxy.py24
-rw-r--r--libmproxy/protocol2/upstream_proxy.py18
-rw-r--r--libmproxy/proxy/connection.py8
-rw-r--r--libmproxy/proxy/primitives.py6
-rw-r--r--libmproxy/proxy/server.py6
14 files changed, 145 insertions, 68 deletions
diff --git a/libmproxy/exceptions.py b/libmproxy/exceptions.py
new file mode 100644
index 00000000..4d98c024
--- /dev/null
+++ b/libmproxy/exceptions.py
@@ -0,0 +1,22 @@
+from __future__ import (absolute_import, print_function, division)
+
+
+class ProxyException(Exception):
+ """
+ Base class for all exceptions thrown by libmproxy.
+ """
+ def __init__(self, message, cause=None):
+ """
+ :param message: Error Message
+ :param cause: Exception object that caused this exception to be thrown.
+ """
+ super(ProxyException, self).__init__(message)
+ self.cause = cause
+
+
+class ProtocolException(ProxyException):
+ pass
+
+
+class ServerException(ProxyException):
+ pass \ No newline at end of file
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
diff --git a/libmproxy/proxy/connection.py b/libmproxy/proxy/connection.py
index 9e03157a..49210e47 100644
--- a/libmproxy/proxy/connection.py
+++ b/libmproxy/proxy/connection.py
@@ -32,6 +32,10 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
port=self.address.port
)
+ @property
+ def tls_established(self):
+ return self.ssl_established
+
_stateobject_attributes = dict(
ssl_established=bool,
timestamp_start=float,
@@ -112,6 +116,10 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
port=self.address.port
)
+ @property
+ def tls_established(self):
+ return self.ssl_established
+
_stateobject_attributes = dict(
state=list,
timestamp_start=float,
diff --git a/libmproxy/proxy/primitives.py b/libmproxy/proxy/primitives.py
index fd4eb882..a9f31181 100644
--- a/libmproxy/proxy/primitives.py
+++ b/libmproxy/proxy/primitives.py
@@ -2,12 +2,6 @@ from __future__ import absolute_import
from netlib import socks, tcp
-class ProxyError2(Exception):
- def __init__(self, message, cause=None):
- super(ProxyError2, self).__init__(message)
- self.cause = cause
-
-
class ProxyError(Exception):
def __init__(self, code, message, headers=None):
super(ProxyError, self).__init__(message)
diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py
index 32d596ad..c107cbed 100644
--- a/libmproxy/proxy/server.py
+++ b/libmproxy/proxy/server.py
@@ -7,7 +7,7 @@ from netlib import tcp
from ..protocol.handle import protocol_handler
from .. import protocol2
-from .primitives import ProxyServerError, Log, ProxyError, ProxyError2
+from .primitives import ProxyServerError, Log, ProxyError
from .connection import ClientConnection, ServerConnection
@@ -79,12 +79,12 @@ class ConnectionHandler2:
self.config,
self.channel
)
- root_layer = protocol2.ReverseProxy(root_context, ("localhost", 5000), True, True)
+ root_layer = protocol2.Socks5IncomingLayer(root_context)
try:
for message in root_layer():
print("Root layer receveived: %s" % message)
- except ProxyError2 as e:
+ except protocol2.ProtocolException as e:
self.log(e, "info")
except Exception:
self.log(traceback.format_exc(), "error")