diff options
Diffstat (limited to 'libmproxy/protocol2')
-rw-r--r-- | libmproxy/protocol2/__init__.py | 7 | ||||
-rw-r--r-- | libmproxy/protocol2/reverse_proxy.py | 5 | ||||
-rw-r--r-- | libmproxy/protocol2/root_context.py | 10 | ||||
-rw-r--r-- | libmproxy/protocol2/socks_proxy.py | 2 | ||||
-rw-r--r-- | libmproxy/protocol2/tls.py | 38 |
5 files changed, 42 insertions, 20 deletions
diff --git a/libmproxy/protocol2/__init__.py b/libmproxy/protocol2/__init__.py index d5dafaae..61b9a77e 100644 --- a/libmproxy/protocol2/__init__.py +++ b/libmproxy/protocol2/__init__.py @@ -3,8 +3,11 @@ from .root_context import RootContext from .socks_proxy import Socks5Proxy from .reverse_proxy import ReverseProxy from .http_proxy import HttpProxy, HttpUpstreamProxy -from .rawtcp import RawTcpLayer +from .transparent_proxy import TransparentProxy +from .http import make_error_response __all__ = [ - "Socks5Proxy", "RawTcpLayer", "RootContext", "ReverseProxy", "HttpProxy", "HttpUpstreamProxy" + "RootContext", + "Socks5Proxy", "ReverseProxy", "HttpProxy", "HttpUpstreamProxy", "TransparentProxy", + "make_error_response" ] diff --git a/libmproxy/protocol2/reverse_proxy.py b/libmproxy/protocol2/reverse_proxy.py index 9d5a4beb..76163c71 100644 --- a/libmproxy/protocol2/reverse_proxy.py +++ b/libmproxy/protocol2/reverse_proxy.py @@ -12,10 +12,7 @@ class ReverseProxy(Layer, ServerConnectionMixin): self._server_tls = server_tls def __call__(self): - if self._client_tls or self._server_tls: - layer = TlsLayer(self, self._client_tls, self._server_tls) - else: - layer = self.ctx.next_layer(self) + layer = TlsLayer(self, self._client_tls, self._server_tls) try: layer() diff --git a/libmproxy/protocol2/root_context.py b/libmproxy/protocol2/root_context.py index 78d48453..af0e7a37 100644 --- a/libmproxy/protocol2/root_context.py +++ b/libmproxy/protocol2/root_context.py @@ -4,7 +4,7 @@ from netlib.http.http1 import HTTP1Protocol from netlib.http.http2 import HTTP2Protocol from .rawtcp import RawTcpLayer -from .tls import TlsLayer +from .tls import TlsLayer, is_tls_record_magic from .http import Http1Layer, Http2Layer @@ -38,13 +38,7 @@ class RootContext(object): # TLS ClientHello magic, works for SSLv3, TLSv1.0, TLSv1.1, TLSv1.2 # http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html#client-hello d = top_layer.client_conn.rfile.peek(3) - is_tls_client_hello = ( - len(d) == 3 and - d[0] == '\x16' and - d[1] == '\x03' and - d[2] in ('\x00', '\x01', '\x02', '\x03') - ) - if is_tls_client_hello: + if is_tls_record_magic(d): return TlsLayer(top_layer, True, True) # 3. Check for --tcp diff --git a/libmproxy/protocol2/socks_proxy.py b/libmproxy/protocol2/socks_proxy.py index 18b363d5..91935d24 100644 --- a/libmproxy/protocol2/socks_proxy.py +++ b/libmproxy/protocol2/socks_proxy.py @@ -8,7 +8,7 @@ from .layer import Layer, ServerConnectionMixin class Socks5Proxy(Layer, ServerConnectionMixin): def __call__(self): try: - s5mode = Socks5ProxyMode(self.config.ssl_ports) + s5mode = Socks5ProxyMode([]) address = s5mode.get_upstream_server(self.client_conn)[2:] except ProxyError as e: # TODO: Unmonkeypatch diff --git a/libmproxy/protocol2/tls.py b/libmproxy/protocol2/tls.py index b1b80034..850bf5dc 100644 --- a/libmproxy/protocol2/tls.py +++ b/libmproxy/protocol2/tls.py @@ -11,6 +11,21 @@ from ..exceptions import ProtocolException from .layer import Layer +def is_tls_record_magic(d): + """ + Returns: + True, if the passed bytes start with the TLS record magic bytes. + False, otherwise. + """ + d = d[:3] + return ( + len(d) == 3 and + d[0] == '\x16' and + d[1] == '\x03' and + d[2] in ('\x00', '\x01', '\x02', '\x03') + ) + + class TlsLayer(Layer): def __init__(self, ctx, client_tls, server_tls): self.client_sni = None @@ -69,9 +84,13 @@ class TlsLayer(Layer): client_hello_size = 1 offset = 0 while len(client_hello) < client_hello_size: - record_header = self.client_conn.rfile.peek(offset+5)[offset:] + record_header = self.client_conn.rfile.peek(offset + 5)[offset:] + if not is_tls_record_magic(record_header) or len(record_header) != 5: + raise ProtocolException('Expected TLS record, got "%s" instead.' % record_header) record_size = struct.unpack("!H", record_header[3:])[0] + 5 - record_body = self.client_conn.rfile.peek(offset+record_size)[offset+5:] + record_body = self.client_conn.rfile.peek(offset + record_size)[offset + 5:] + if len(record_body) != record_size - 5: + raise ProtocolException("Unexpected EOF in TLS handshake: %s" % record_body) client_hello += record_body offset += record_size client_hello_size = struct.unpack("!I", '\x00' + client_hello[1:4])[0] + 4 @@ -81,7 +100,12 @@ class TlsLayer(Layer): """ Peek into the connection, read the initial client hello and parse it to obtain ALPN values. """ - raw_client_hello = self._get_client_hello()[4:] # exclude handshake header. + try: + raw_client_hello = self._get_client_hello()[4:] # exclude handshake header. + except ProtocolException as e: + self.log("Cannot parse Client Hello: %s" % repr(e), "error") + return + try: client_hello = ClientHello.parse(raw_client_hello) except ConstructError as e: @@ -97,7 +121,10 @@ class TlsLayer(Layer): elif extension.type == 0x10: self.client_alpn_protocols = list(extension.alpn_protocols) - self.log("Parsed Client Hello: sni=%s, alpn=%s" % (self.client_sni, self.client_alpn_protocols), "debug") + self.log( + "Parsed Client Hello: sni=%s, alpn=%s" % (self.client_sni, self.client_alpn_protocols), + "debug" + ) def connect(self): if not self.server_conn: @@ -226,7 +253,8 @@ class TlsLayer(Layer): host = self.server_conn.address.host sans = set() # Incorporate upstream certificate - if self.server_conn and self.server_conn.tls_established and (not self.config.no_upstream_cert): + if self.server_conn and 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: |