aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2015-08-30 01:21:58 +0200
committerMaximilian Hils <git@maximilianhils.com>2015-08-30 01:21:58 +0200
commitdd7f50d64bef38fa67b4cace91913d03691dde26 (patch)
treec183aa1f286ec191a094713d1f697f2fa54ab385 /libmproxy
parent100ea27c30d89b895a02a1b128edc5472ab84b3e (diff)
downloadmitmproxy-dd7f50d64bef38fa67b4cace91913d03691dde26.tar.gz
mitmproxy-dd7f50d64bef38fa67b4cace91913d03691dde26.tar.bz2
mitmproxy-dd7f50d64bef38fa67b4cace91913d03691dde26.zip
restructure code, remove cruft
Diffstat (limited to 'libmproxy')
-rw-r--r--libmproxy/exceptions.py4
-rw-r--r--libmproxy/flow.py2
-rw-r--r--libmproxy/protocol/http.py83
-rw-r--r--libmproxy/protocol2/http.py112
-rw-r--r--libmproxy/protocol2/http_proxy.py3
-rw-r--r--libmproxy/protocol2/http_replay.py95
-rw-r--r--libmproxy/protocol2/layer.py19
-rw-r--r--libmproxy/protocol2/messages.py46
-rw-r--r--libmproxy/protocol2/rawtcp.py13
-rw-r--r--libmproxy/protocol2/reverse_proxy.py5
-rw-r--r--libmproxy/protocol2/root_context.py5
-rw-r--r--libmproxy/protocol2/socks_proxy.py54
-rw-r--r--libmproxy/protocol2/tls.py22
-rw-r--r--libmproxy/protocol2/transparent_proxy.py3
-rw-r--r--libmproxy/proxy/__init__.py13
-rw-r--r--libmproxy/proxy/connection.py6
-rw-r--r--libmproxy/proxy/primitives.py179
-rw-r--r--libmproxy/proxy/server.py401
-rw-r--r--libmproxy/utils.py4
19 files changed, 240 insertions, 829 deletions
diff --git a/libmproxy/exceptions.py b/libmproxy/exceptions.py
index 3825c409..f34d9707 100644
--- a/libmproxy/exceptions.py
+++ b/libmproxy/exceptions.py
@@ -18,6 +18,10 @@ class ProtocolException(ProxyException):
pass
+class Socks5Exception(ProtocolException):
+ pass
+
+
class HttpException(ProtocolException):
pass
diff --git a/libmproxy/flow.py b/libmproxy/flow.py
index a2b807ba..dac607a0 100644
--- a/libmproxy/flow.py
+++ b/libmproxy/flow.py
@@ -8,7 +8,7 @@ import Cookie
import cookielib
import os
import re
-from libmproxy.protocol2.http import RequestReplayThread
+from libmproxy.protocol2.http_replay import RequestReplayThread
from netlib import odict, wsgi, tcp
from netlib.http.semantics import CONTENT_MISSING
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py
index 56d7d57f..a30437d1 100644
--- a/libmproxy/protocol/http.py
+++ b/libmproxy/protocol/http.py
@@ -695,85 +695,4 @@ class HTTPHandler(ProtocolHandler):
else:
raise http.HttpAuthenticationError(
self.c.config.authenticator.auth_challenge_headers())
- return request.headers
-
-
-class RequestReplayThread(threading.Thread):
- name = "RequestReplayThread"
-
- def __init__(self, config, flow, masterq, should_exit):
- """
- masterqueue can be a queue or None, if no scripthooks should be
- processed.
- """
- self.config, self.flow = config, flow
- if masterq:
- self.channel = controller.Channel(masterq, should_exit)
- else:
- self.channel = None
- super(RequestReplayThread, self).__init__()
-
- def run(self):
- r = self.flow.request
- form_out_backup = r.form_out
- try:
- self.flow.response = None
-
- # If we have a channel, run script hooks.
- if self.channel:
- request_reply = self.channel.ask("request", self.flow)
- if request_reply is None or request_reply == KILL:
- raise KillSignal()
- elif isinstance(request_reply, HTTPResponse):
- self.flow.response = request_reply
-
- if not self.flow.response:
- # In all modes, we directly connect to the server displayed
- if self.config.mode == "upstream":
- # FIXME
- server_address = self.config.mode.get_upstream_server(
- self.flow.client_conn
- )[2:]
- server = ServerConnection(server_address)
- server.connect()
- if r.scheme == "https":
- send_connect_request(server, r.host, r.port)
- server.establish_ssl(
- self.config.clientcerts,
- sni=self.flow.server_conn.sni
- )
- r.form_out = "relative"
- else:
- r.form_out = "absolute"
- else:
- server_address = (r.host, r.port)
- server = ServerConnection(server_address)
- server.connect()
- if r.scheme == "https":
- server.establish_ssl(
- self.config.clientcerts,
- sni=self.flow.server_conn.sni
- )
- r.form_out = "relative"
-
- server.send(self.flow.server_conn.protocol.assemble(r))
- self.flow.server_conn = server
- self.flow.response = HTTPResponse.from_protocol(
- self.flow.server_conn.protocol,
- r.method,
- body_size_limit=self.config.body_size_limit,
- )
- if self.channel:
- response_reply = self.channel.ask("response", self.flow)
- if response_reply is None or response_reply == KILL:
- raise KillSignal()
- except (proxy.ProxyError, http.HttpError, tcp.NetLibError) as v:
- self.flow.error = Error(repr(v))
- if self.channel:
- self.channel.ask("error", self.flow)
- except KillSignal:
- # KillSignal should only be raised if there's a channel in the
- # first place.
- self.channel.tell("log", proxy.Log("Connection killed", "info"))
- finally:
- r.form_out = form_out_backup
+ return request.headers \ No newline at end of file
diff --git a/libmproxy/protocol2/http.py b/libmproxy/protocol2/http.py
index a3f32926..a508ae8b 100644
--- a/libmproxy/protocol2/http.py
+++ b/libmproxy/protocol2/http.py
@@ -1,28 +1,20 @@
from __future__ import (absolute_import, print_function, division)
-from .. import version
-import threading
-from ..exceptions import InvalidCredentials, HttpException, ProtocolException
-from .layer import Layer
-from libmproxy import utils
-from libmproxy.controller import Channel
-from libmproxy.protocol2.layer import Kill
-from libmproxy.protocol import KILL, Error
-
-from libmproxy.protocol.http import HTTPFlow
-from libmproxy.protocol.http_wrappers import HTTPResponse, HTTPRequest
-from libmproxy.proxy import Log
-from libmproxy.proxy.connection import ServerConnection
from netlib import tcp
-from netlib.http import status_codes, http1, http2, HttpErrorConnClosed, HttpError
+from netlib.http import status_codes, http1, HttpErrorConnClosed, HttpError
from netlib.http.semantics import CONTENT_MISSING
from netlib import odict
from netlib.tcp import NetLibError, Address
from netlib.http.http1 import HTTP1Protocol
from netlib.http.http2 import HTTP2Protocol
-
-# TODO: The HTTP2 layer is missing multiplexing, which requires a major rewrite.
+from .. import version, utils
+from ..exceptions import InvalidCredentials, HttpException, ProtocolException
+from .layer import Layer
+from ..proxy import Kill
+from libmproxy.protocol import KILL, Error
+from libmproxy.protocol.http import HTTPFlow
+from libmproxy.protocol.http_wrappers import HTTPResponse, HTTPRequest
class _HttpLayer(Layer):
@@ -138,6 +130,7 @@ class Http1Layer(_StreamingHttpLayer):
layer()
+# TODO: The HTTP2 layer is missing multiplexing, which requires a major rewrite.
class Http2Layer(_HttpLayer):
def __init__(self, ctx, mode):
super(Http2Layer, self).__init__(ctx)
@@ -359,6 +352,9 @@ class HttpLayer(Layer):
return
except (HttpErrorConnClosed, NetLibError, HttpError, ProtocolException) as e:
+ if flow.request and not flow.response:
+ flow.error = Error(repr(e))
+ self.channel.ask("error", flow)
try:
self.send_response(make_error_response(
getattr(e, "code", 502),
@@ -590,87 +586,3 @@ class HttpLayer(Layer):
])
))
raise InvalidCredentials("Proxy Authentication Required")
-
-
-class RequestReplayThread(threading.Thread):
- name = "RequestReplayThread"
-
- def __init__(self, config, flow, masterq, should_exit):
- """
- masterqueue can be a queue or None, if no scripthooks should be
- processed.
- """
- self.config, self.flow = config, flow
- if masterq:
- self.channel = Channel(masterq, should_exit)
- else:
- self.channel = None
- super(RequestReplayThread, self).__init__()
-
- def run(self):
- r = self.flow.request
- form_out_backup = r.form_out
- try:
- self.flow.response = None
-
- # If we have a channel, run script hooks.
- if self.channel:
- request_reply = self.channel.ask("request", self.flow)
- if request_reply is None or request_reply == KILL:
- raise Kill()
- elif isinstance(request_reply, HTTPResponse):
- self.flow.response = request_reply
-
- if not self.flow.response:
- # In all modes, we directly connect to the server displayed
- if self.config.mode == "upstream":
- server_address = self.config.upstream_server.address
- server = ServerConnection(server_address)
- server.connect()
- protocol = HTTP1Protocol(server)
- if r.scheme == "https":
- connect_request = make_connect_request((r.host, r.port))
- server.send(protocol.assemble(connect_request))
- resp = protocol.read_response("CONNECT")
- if resp.code != 200:
- raise HttpError(502, "Upstream server refuses CONNECT request")
- server.establish_ssl(
- self.config.clientcerts,
- sni=self.flow.server_conn.sni
- )
- r.form_out = "relative"
- else:
- r.form_out = "absolute"
- else:
- server_address = (r.host, r.port)
- server = ServerConnection(server_address)
- server.connect()
- protocol = HTTP1Protocol(server)
- if r.scheme == "https":
- server.establish_ssl(
- self.config.clientcerts,
- sni=self.flow.server_conn.sni
- )
- r.form_out = "relative"
-
- server.send(protocol.assemble(r))
- self.flow.server_conn = server
- self.flow.response = HTTPResponse.from_protocol(
- protocol,
- r.method,
- body_size_limit=self.config.body_size_limit,
- )
- if self.channel:
- response_reply = self.channel.ask("response", self.flow)
- if response_reply is None or response_reply == KILL:
- raise Kill()
- except (HttpError, tcp.NetLibError) as v:
- self.flow.error = Error(repr(v))
- if self.channel:
- self.channel.ask("error", self.flow)
- except Kill:
- # KillSignal should only be raised if there's a channel in the
- # first place.
- self.channel.tell("log", Log("Connection killed", "info"))
- finally:
- r.form_out = form_out_backup
diff --git a/libmproxy/protocol2/http_proxy.py b/libmproxy/protocol2/http_proxy.py
index c24af6cf..b3389eb7 100644
--- a/libmproxy/protocol2/http_proxy.py
+++ b/libmproxy/protocol2/http_proxy.py
@@ -13,6 +13,7 @@ class HttpProxy(Layer, ServerConnectionMixin):
if self.server_conn:
self._disconnect()
+
class HttpUpstreamProxy(Layer, ServerConnectionMixin):
def __init__(self, ctx, server_address):
super(HttpUpstreamProxy, self).__init__(ctx, server_address=server_address)
@@ -23,4 +24,4 @@ class HttpUpstreamProxy(Layer, ServerConnectionMixin):
layer()
finally:
if self.server_conn:
- self._disconnect() \ No newline at end of file
+ self._disconnect()
diff --git a/libmproxy/protocol2/http_replay.py b/libmproxy/protocol2/http_replay.py
new file mode 100644
index 00000000..872ef9cd
--- /dev/null
+++ b/libmproxy/protocol2/http_replay.py
@@ -0,0 +1,95 @@
+import threading
+from netlib.http import HttpError
+from netlib.http.http1 import HTTP1Protocol
+from netlib.tcp import NetLibError
+
+from ..controller import Channel
+from ..protocol import KILL, Error
+from ..protocol.http_wrappers import HTTPResponse
+from ..proxy import Log, Kill
+from ..proxy.connection import ServerConnection
+from .http import make_connect_request
+
+
+class RequestReplayThread(threading.Thread):
+ name = "RequestReplayThread"
+
+ def __init__(self, config, flow, masterq, should_exit):
+ """
+ masterqueue can be a queue or None, if no scripthooks should be
+ processed.
+ """
+ self.config, self.flow = config, flow
+ if masterq:
+ self.channel = Channel(masterq, should_exit)
+ else:
+ self.channel = None
+ super(RequestReplayThread, self).__init__()
+
+ def run(self):
+ r = self.flow.request
+ form_out_backup = r.form_out
+ try:
+ self.flow.response = None
+
+ # If we have a channel, run script hooks.
+ if self.channel:
+ request_reply = self.channel.ask("request", self.flow)
+ if request_reply is None or request_reply == KILL:
+ raise Kill()
+ elif isinstance(request_reply, HTTPResponse):
+ self.flow.response = request_reply
+
+ if not self.flow.response:
+ # In all modes, we directly connect to the server displayed
+ if self.config.mode == "upstream":
+ server_address = self.config.upstream_server.address
+ server = ServerConnection(server_address)
+ server.connect()
+ protocol = HTTP1Protocol(server)
+ if r.scheme == "https":
+ connect_request = make_connect_request((r.host, r.port))
+ server.send(protocol.assemble(connect_request))
+ resp = protocol.read_response("CONNECT")
+ if resp.code != 200:
+ raise HttpError(502, "Upstream server refuses CONNECT request")
+ server.establish_ssl(
+ self.config.clientcerts,
+ sni=self.flow.server_conn.sni
+ )
+ r.form_out = "relative"
+ else:
+ r.form_out = "absolute"
+ else:
+ server_address = (r.host, r.port)
+ server = ServerConnection(server_address)
+ server.connect()
+ protocol = HTTP1Protocol(server)
+ if r.scheme == "https":
+ server.establish_ssl(
+ self.config.clientcerts,
+ sni=self.flow.server_conn.sni
+ )
+ r.form_out = "relative"
+
+ server.send(protocol.assemble(r))
+ self.flow.server_conn = server
+ self.flow.response = HTTPResponse.from_protocol(
+ protocol,
+ r.method,
+ body_size_limit=self.config.body_size_limit,
+ )
+ if self.channel:
+ response_reply = self.channel.ask("response", self.flow)
+ if response_reply is None or response_reply == KILL:
+ raise Kill()
+ except (HttpError, NetLibError) as v:
+ self.flow.error = Error(repr(v))
+ if self.channel:
+ self.channel.ask("error", self.flow)
+ except Kill:
+ # KillSignal should only be raised if there's a channel in the
+ # first place.
+ self.channel.tell("log", Log("Connection killed", "info"))
+ finally:
+ r.form_out = form_out_backup
diff --git a/libmproxy/protocol2/layer.py b/libmproxy/protocol2/layer.py
index f72320ff..2b47cc26 100644
--- a/libmproxy/protocol2/layer.py
+++ b/libmproxy/protocol2/layer.py
@@ -30,8 +30,6 @@ Further goals:
inline scripts shall have a chance to handle everything locally.
"""
from __future__ import (absolute_import, print_function, division)
-import Queue
-import threading
from netlib import tcp
from ..proxy import Log
from ..proxy.connection import ServerConnection
@@ -80,10 +78,8 @@ class Layer(_LayerCodeCompletion):
def log(self, msg, level, subs=()):
full_msg = [
- "%s:%s: %s" %
- (self.client_conn.address.host,
- self.client_conn.address.port,
- msg)]
+ "{}: {}".format(repr(self.client_conn.address), msg)
+ ]
for i in subs:
full_msg.append(" -> " + i)
full_msg = "\n".join(full_msg)
@@ -119,7 +115,7 @@ class ServerConnectionMixin(object):
self.log("Set new server address: " + repr(address), "debug")
self.server_conn.address = address
else:
- self.ctx.set_server(address, server_tls, sni, depth-1)
+ self.ctx.set_server(address, server_tls, sni, depth - 1)
def _disconnect(self):
"""
@@ -138,10 +134,5 @@ class ServerConnectionMixin(object):
try:
self.server_conn.connect()
except tcp.NetLibError as e:
- raise ProtocolException("Server connection to '%s' failed: %s" % (self.server_conn.address, e), e)
-
-
-class Kill(Exception):
- """
- Kill a connection.
- """ \ No newline at end of file
+ raise ProtocolException(
+ "Server connection to '%s' failed: %s" % (self.server_conn.address, e), e)
diff --git a/libmproxy/protocol2/messages.py b/libmproxy/protocol2/messages.py
deleted file mode 100644
index de049486..00000000
--- a/libmproxy/protocol2/messages.py
+++ /dev/null
@@ -1,46 +0,0 @@
-"""
-This module contains all valid messages layers can send to the underlying layers.
-"""
-from __future__ import (absolute_import, print_function, division)
-from netlib.tcp import Address
-
-
-class _Message(object):
- def __eq__(self, other):
- # Allow message == Connect checks.
- if isinstance(self, other):
- return True
- return self is other
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
-
-class Connect(_Message):
- """
- Connect to the server
- """
-
-
-class Reconnect(_Message):
- """
- Re-establish the server connection
- """
-
-
-class SetServer(_Message):
- """
- Change the upstream server.
- """
-
- def __init__(self, address, server_tls, sni, depth=1):
- self.address = Address.wrap(address)
- self.server_tls = server_tls
- self.sni = sni
-
- # upstream proxy scenario: you may want to change either the final target or the upstream proxy.
- # We can express this neatly as the "nth-server-providing-layer"
- # ServerConnection could get a `via` attribute.
- self.depth = depth
-
-
diff --git a/libmproxy/protocol2/rawtcp.py b/libmproxy/protocol2/rawtcp.py
index e8e3cf65..b10217f1 100644
--- a/libmproxy/protocol2/rawtcp.py
+++ b/libmproxy/protocol2/rawtcp.py
@@ -4,10 +4,9 @@ import select
from OpenSSL import SSL
-from ..exceptions import ProtocolException
from netlib.tcp import NetLibError
from netlib.utils import cleanBin
-from ..protocol.tcp import TCPHandler
+from ..exceptions import ProtocolException
from .layer import Layer
@@ -31,6 +30,7 @@ class RawTcpLayer(Layer):
while True:
r, _, _ = select.select(conns, [], [], 10)
for conn in r:
+ dst = server if conn == client else client
size = conn.recv_into(buf, self.chunk_size)
if not size:
@@ -41,22 +41,21 @@ class RawTcpLayer(Layer):
# Sockets will be cleaned up on a higher level.
return
else:
- conn.shutdown(socket.SHUT_WR)
+ dst.shutdown(socket.SHUT_WR)
if len(conns) == 0:
return
continue
- dst = server if conn == client else client
dst.sendall(buf[:size])
if self.logging:
# log messages are prepended with the client address,
# hence the "weird" direction string.
if dst == server:
- direction = "-> tcp -> {!r}".format(self.server_conn.address)
+ direction = "-> tcp -> {}".format(repr(self.server_conn.address))
else:
- direction = "<- tcp <- {!r}".format(self.server_conn.address)
+ direction = "<- tcp <- {}".format(repr(self.server_conn.address))
data = cleanBin(buf[:size].tobytes())
self.log(
"{}\r\n{}".format(direction, data),
@@ -64,4 +63,4 @@ class RawTcpLayer(Layer):
)
except (socket.error, NetLibError, SSL.Error) as e:
- raise ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e)), e) \ No newline at end of file
+ raise ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e)), e)
diff --git a/libmproxy/protocol2/reverse_proxy.py b/libmproxy/protocol2/reverse_proxy.py
index 76163c71..e959db86 100644
--- a/libmproxy/protocol2/reverse_proxy.py
+++ b/libmproxy/protocol2/reverse_proxy.py
@@ -5,17 +5,18 @@ from .tls import TlsLayer
class ReverseProxy(Layer, ServerConnectionMixin):
-
def __init__(self, ctx, server_address, client_tls, server_tls):
super(ReverseProxy, self).__init__(ctx, server_address=server_address)
self._client_tls = client_tls
self._server_tls = server_tls
def __call__(self):
+ # Always use a TLS layer here; if someone changes the scheme, there needs to be a
+ # TLS layer underneath.
layer = TlsLayer(self, self._client_tls, self._server_tls)
try:
layer()
finally:
if self.server_conn:
- self._disconnect() \ No newline at end of file
+ self._disconnect()
diff --git a/libmproxy/protocol2/root_context.py b/libmproxy/protocol2/root_context.py
index af0e7a37..4d69204f 100644
--- a/libmproxy/protocol2/root_context.py
+++ b/libmproxy/protocol2/root_context.py
@@ -32,7 +32,7 @@ class RootContext(object):
# 1. Check for --ignore.
if self.config.check_ignore(top_layer.server_conn.address):
- return RawTcpLayer(top_layer)
+ return RawTcpLayer(top_layer, logging=False)
# 2. Check for TLS
# TLS ClientHello magic, works for SSLv3, TLSv1.0, TLSv1.1, TLSv1.2
@@ -62,7 +62,8 @@ class RootContext(object):
# d = top_layer.client_conn.rfile.peek(3)
# is_ascii = (
# len(d) == 3 and
- # all(x in string.ascii_letters for x in d) # better be safe here and don't expect uppercase...
+ # # better be safe here and don't expect uppercase...
+ # all(x in string.ascii_letters for x in d)
# )
# # TODO: This could block if there are not enough bytes available?
# d = top_layer.client_conn.rfile.peek(len(HTTP2Protocol.CLIENT_CONNECTION_PREFACE))
diff --git a/libmproxy/protocol2/socks_proxy.py b/libmproxy/protocol2/socks_proxy.py
index 91935d24..525520e8 100644
--- a/libmproxy/protocol2/socks_proxy.py
+++ b/libmproxy/protocol2/socks_proxy.py
@@ -1,27 +1,59 @@
from __future__ import (absolute_import, print_function, division)
-from ..exceptions import ProtocolException
-from ..proxy import ProxyError, Socks5ProxyMode
+from netlib import socks
+from netlib.tcp import NetLibError
+from ..exceptions import Socks5Exception
from .layer import Layer, ServerConnectionMixin
class Socks5Proxy(Layer, ServerConnectionMixin):
def __call__(self):
try:
- s5mode = Socks5ProxyMode([])
- address = s5mode.get_upstream_server(self.client_conn)[2:]
- except ProxyError as e:
- # TODO: Unmonkeypatch
- raise ProtocolException(str(e), e)
+ # Parse Client Greeting
+ client_greet = socks.ClientGreeting.from_file(self.client_conn.rfile, fail_early=True)
+ client_greet.assert_socks5()
+ if socks.METHOD.NO_AUTHENTICATION_REQUIRED not in client_greet.methods:
+ raise socks.SocksError(
+ socks.METHOD.NO_ACCEPTABLE_METHODS,
+ "mitmproxy only supports SOCKS without authentication"
+ )
- self.server_conn.address = address
+ # Send Server Greeting
+ server_greet = socks.ServerGreeting(
+ socks.VERSION.SOCKS5,
+ socks.METHOD.NO_AUTHENTICATION_REQUIRED
+ )
+ server_greet.to_file(self.client_conn.wfile)
+ self.client_conn.wfile.flush()
- # TODO: Kill event
+ # Parse Connect Request
+ connect_request = socks.Message.from_file(self.client_conn.rfile)
+ connect_request.assert_socks5()
+ if connect_request.msg != socks.CMD.CONNECT:
+ raise socks.SocksError(
+ socks.REP.COMMAND_NOT_SUPPORTED,
+ "mitmproxy only supports SOCKS5 CONNECT."
+ )
- layer = self.ctx.next_layer(self)
+ # We always connect lazily, but we need to pretend to the client that we connected.
+ connect_reply = socks.Message(
+ socks.VERSION.SOCKS5,
+ socks.REP.SUCCEEDED,
+ connect_request.atyp,
+ # dummy value, we don't have an upstream connection yet.
+ connect_request.addr
+ )
+ connect_reply.to_file(self.client_conn.wfile)
+ self.client_conn.wfile.flush()
+
+ except (socks.SocksError, NetLibError) as e:
+ raise Socks5Exception("SOCKS5 mode failure: %s" % repr(e), e)
+ self.server_conn.address = connect_request.addr
+
+ layer = self.ctx.next_layer(self)
try:
layer()
finally:
if self.server_conn:
- self._disconnect() \ No newline at end of file
+ self._disconnect()
diff --git a/libmproxy/protocol2/tls.py b/libmproxy/protocol2/tls.py
index 850bf5dc..0c02b0ea 100644
--- a/libmproxy/protocol2/tls.py
+++ b/libmproxy/protocol2/tls.py
@@ -1,11 +1,11 @@
from __future__ import (absolute_import, print_function, division)
import struct
-from construct import ConstructError
-from netlib import tcp
-import netlib.http.http2
+from construct import ConstructError
+from netlib.tcp import NetLibError, NetLibInvalidCertificateError
+from netlib.http.http1 import HTTP1Protocol
from ..contrib.tls._constructs import ClientHello
from ..exceptions import ProtocolException
from .layer import Layer
@@ -161,7 +161,7 @@ class TlsLayer(Layer):
"""
# This gets triggered if we haven't established an upstream connection yet.
- default_alpn = netlib.http.http1.HTTP1Protocol.ALPN_PROTO_HTTP1
+ default_alpn = HTTP1Protocol.ALPN_PROTO_HTTP1
# alpn_preference = netlib.http.http2.HTTP2Protocol.ALPN_PROTO_H2
if self.alpn_for_client_connection in options:
@@ -203,7 +203,7 @@ class TlsLayer(Layer):
chain_file=chain_file,
alpn_select_callback=self.__alpn_select_callback,
)
- except tcp.NetLibError as e:
+ except NetLibError as e:
raise ProtocolException("Cannot establish TLS with client: %s" % repr(e), e)
def _establish_tls_with_server(self):
@@ -236,7 +236,7 @@ class TlsLayer(Layer):
(tls_cert_err['depth'], tls_cert_err['errno']),
"error")
self.log("Ignoring server verification error, continuing with connection", "error")
- except tcp.NetLibInvalidCertificateError as e:
+ except NetLibInvalidCertificateError as e:
tls_cert_err = self.server_conn.ssl_verification_error
self.log(
"TLS verification failed for upstream server at depth %s with error: %s" %
@@ -244,7 +244,7 @@ class TlsLayer(Layer):
"error")
self.log("Aborting connection attempt", "error")
raise ProtocolException("Cannot establish TLS with server: %s" % repr(e), e)
- except tcp.NetLibError as e:
+ except NetLibError as e:
raise ProtocolException("Cannot establish TLS with server: %s" % repr(e), e)
self.log("ALPN selected by server: %s" % self.alpn_for_client_connection, "debug")
@@ -253,8 +253,12 @@ 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):
+ use_upstream_cert = (
+ self.server_conn and
+ self.server_conn.tls_established and
+ (not self.config.no_upstream_cert)
+ )
+ if use_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
index 9263dbde..e6ebf115 100644
--- a/libmproxy/protocol2/transparent_proxy.py
+++ b/libmproxy/protocol2/transparent_proxy.py
@@ -6,7 +6,6 @@ from .layer import Layer, ServerConnectionMixin
class TransparentProxy(Layer, ServerConnectionMixin):
-
def __init__(self, ctx):
super(TransparentProxy, self).__init__(ctx)
self.resolver = platform.resolver()
@@ -22,4 +21,4 @@ class TransparentProxy(Layer, ServerConnectionMixin):
layer()
finally:
if self.server_conn:
- self._disconnect() \ No newline at end of file
+ self._disconnect()
diff --git a/libmproxy/proxy/__init__.py b/libmproxy/proxy/__init__.py
index 7d664707..709654cb 100644
--- a/libmproxy/proxy/__init__.py
+++ b/libmproxy/proxy/__init__.py
@@ -1,2 +1,11 @@
-from .primitives import *
-from .config import ProxyConfig, process_proxy_options \ No newline at end of file
+from __future__ import (absolute_import, print_function, division)
+
+from .primitives import Log, Kill
+from .config import ProxyConfig
+from .connection import ClientConnection, ServerConnection
+
+__all__ = [
+ "Log", "Kill",
+ "ProxyConfig",
+ "ClientConnection", "ServerConnection"
+] \ No newline at end of file
diff --git a/libmproxy/proxy/connection.py b/libmproxy/proxy/connection.py
index c329ed64..94f318f6 100644
--- a/libmproxy/proxy/connection.py
+++ b/libmproxy/proxy/connection.py
@@ -12,7 +12,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
# Eventually, this object is restored from state. We don't have a
# connection then.
if client_connection:
- tcp.BaseHandler.__init__(self, client_connection, address, server)
+ super(ClientConnection, self).__init__(client_connection, address, server)
else:
self.connection = None
self.server = None
@@ -80,11 +80,11 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
return f
def convert_to_ssl(self, *args, **kwargs):
- tcp.BaseHandler.convert_to_ssl(self, *args, **kwargs)
+ super(ClientConnection, self).convert_to_ssl(*args, **kwargs)
self.timestamp_ssl_setup = utils.timestamp()
def finish(self):
- tcp.BaseHandler.finish(self)
+ super(ClientConnection, self).finish()
self.timestamp_end = utils.timestamp()
diff --git a/libmproxy/proxy/primitives.py b/libmproxy/proxy/primitives.py
index a9f31181..2e440fe8 100644
--- a/libmproxy/proxy/primitives.py
+++ b/libmproxy/proxy/primitives.py
@@ -1,178 +1,15 @@
from __future__ import absolute_import
+import collections
from netlib import socks, tcp
-class ProxyError(Exception):
- def __init__(self, code, message, headers=None):
- super(ProxyError, self).__init__(message)
- self.code, self.headers = code, headers
-
-
-class ProxyServerError(Exception):
- pass
-
-
-class ProxyMode(object):
- http_form_in = None
- http_form_out = None
-
- def get_upstream_server(self, client_conn):
- """
- Returns the address of the server to connect to.
- Returns None if the address needs to be determined on the protocol level (regular proxy mode)
- """
- raise NotImplementedError() # pragma: nocover
-
- @property
- def name(self):
- return self.__class__.__name__.replace("ProxyMode", "").lower()
-
- def __str__(self):
- return self.name
-
- def __eq__(self, other):
- """
- Allow comparisions with "regular" etc.
- """
- if isinstance(other, ProxyMode):
- return self is other
- else:
- return self.name == other
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
-
-class RegularProxyMode(ProxyMode):
- http_form_in = "absolute"
- http_form_out = "relative"
-
- def get_upstream_server(self, client_conn):
- return None
-
-
-class SpoofMode(ProxyMode):
- http_form_in = "relative"
- http_form_out = "relative"
-
- def get_upstream_server(self, client_conn):
- return None
-
- @property
- def name(self):
- return "spoof"
-
-
-class SSLSpoofMode(ProxyMode):
- http_form_in = "relative"
- http_form_out = "relative"
-
- def __init__(self, sslport):
- self.sslport = sslport
-
- def get_upstream_server(self, client_conn):
- return None
-
- @property
- def name(self):
- return "sslspoof"
-
-
-class TransparentProxyMode(ProxyMode):
- http_form_in = "relative"
- http_form_out = "relative"
-
- def __init__(self, resolver, sslports):
- self.resolver = resolver
- self.sslports = sslports
-
- def get_upstream_server(self, client_conn):
- try:
- dst = self.resolver.original_addr(client_conn.connection)
- except Exception as e:
- raise ProxyError(502, "Transparent mode failure: %s" % str(e))
-
- if dst[1] in self.sslports:
- ssl = True
- else:
- ssl = False
- return [ssl, ssl] + list(dst)
-
-
-class Socks5ProxyMode(ProxyMode):
- http_form_in = "relative"
- http_form_out = "relative"
-
- def __init__(self, sslports):
- self.sslports = sslports
-
- def get_upstream_server(self, client_conn):
- try:
- # Parse Client Greeting
- client_greet = socks.ClientGreeting.from_file(client_conn.rfile, fail_early=True)
- client_greet.assert_socks5()
- if socks.METHOD.NO_AUTHENTICATION_REQUIRED not in client_greet.methods:
- raise socks.SocksError(
- socks.METHOD.NO_ACCEPTABLE_METHODS,
- "mitmproxy only supports SOCKS without authentication"
- )
-
- # Send Server Greeting
- server_greet = socks.ServerGreeting(
- socks.VERSION.SOCKS5,
- socks.METHOD.NO_AUTHENTICATION_REQUIRED
- )
- server_greet.to_file(client_conn.wfile)
- client_conn.wfile.flush()
-
- # Parse Connect Request
- connect_request = socks.Message.from_file(client_conn.rfile)
- connect_request.assert_socks5()
- if connect_request.msg != socks.CMD.CONNECT:
- raise socks.SocksError(
- socks.REP.COMMAND_NOT_SUPPORTED,
- "mitmproxy only supports SOCKS5 CONNECT."
- )
-
- # We do not connect here yet, as the clientconnect event has not
- # been handled yet.
-
- connect_reply = socks.Message(
- socks.VERSION.SOCKS5,
- socks.REP.SUCCEEDED,
- connect_request.atyp,
- # dummy value, we don't have an upstream connection yet.
- connect_request.addr
- )
- connect_reply.to_file(client_conn.wfile)
- client_conn.wfile.flush()
-
- ssl = bool(connect_request.addr.port in self.sslports)
- return ssl, ssl, connect_request.addr.host, connect_request.addr.port
-
- except (socks.SocksError, tcp.NetLibError) as e:
- raise ProxyError(502, "SOCKS5 mode failure: %s" % repr(e))
-
-
-class _ConstDestinationProxyMode(ProxyMode):
- def __init__(self, dst):
- self.dst = dst
-
- def get_upstream_server(self, client_conn):
- return self.dst
-
-
-class ReverseProxyMode(_ConstDestinationProxyMode):
- http_form_in = "relative"
- http_form_out = "relative"
-
-
-class UpstreamProxyMode(_ConstDestinationProxyMode):
- http_form_in = "absolute"
- http_form_out = "absolute"
-
-
-class Log:
+class Log(object):
def __init__(self, msg, level="info"):
self.msg = msg
self.level = level
+
+
+class Kill(Exception):
+ """
+ Kill a connection.
+ """ \ No newline at end of file
diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py
index 1fc4cbda..69784014 100644
--- a/libmproxy/proxy/server.py
+++ b/libmproxy/proxy/server.py
@@ -3,16 +3,14 @@ from __future__ import absolute_import, print_function
import traceback
import sys
import socket
-from libmproxy.protocol2.layer import Kill
from netlib import tcp
from netlib.http.http1 import HTTP1Protocol
from netlib.tcp import NetLibError
-from ..protocol.handle import protocol_handler
from .. import protocol2
-from ..exceptions import ProtocolException
-from .primitives import ProxyServerError, Log, ProxyError
-from .connection import ClientConnection, ServerConnection
+from ..exceptions import ProtocolException, ServerException
+from .primitives import Log, Kill
+from .connection import ClientConnection
class DummyServer:
@@ -38,9 +36,9 @@ class ProxyServer(tcp.TCPServer):
"""
self.config = config
try:
- tcp.TCPServer.__init__(self, (config.host, config.port))
- except socket.error as v:
- raise ProxyServerError('Error starting proxy server: ' + repr(v))
+ super(ProxyServer, self).__init__((config.host, config.port))
+ except socket.error as e:
+ raise ServerException('Error starting proxy server: ' + repr(e), e)
self.channel = None
def start_slave(self, klass, channel):
@@ -51,33 +49,28 @@ class ProxyServer(tcp.TCPServer):
self.channel = channel
def handle_client_connection(self, conn, client_address):
- h = ConnectionHandler2(
- self.config,
+ h = ConnectionHandler(
conn,
client_address,
- self,
- self.channel)
+ self.config,
+ self.channel
+ )
h.handle()
- h.finish()
-class ConnectionHandler2:
- # FIXME: parameter ordering
- # FIXME: remove server attribute
- def __init__(self, config, client_conn, client_address, server, channel):
+class ConnectionHandler(object):
+ def __init__(self, client_conn, client_address, config, channel):
self.config = config
"""@type: libmproxy.proxy.config.ProxyConfig"""
self.client_conn = ClientConnection(
client_conn,
client_address,
- server)
+ None)
"""@type: libmproxy.proxy.connection.ClientConnection"""
self.channel = channel
"""@type: libmproxy.controller.Channel"""
- def handle(self):
- self.log("clientconnect", "info")
-
+ def _create_root_layer(self):
root_context = protocol2.RootContext(
self.client_conn,
self.config,
@@ -86,33 +79,38 @@ class ConnectionHandler2:
mode = self.config.mode
if mode == "upstream":
- root_layer = protocol2.HttpUpstreamProxy(
+ return protocol2.HttpUpstreamProxy(
root_context,
self.config.upstream_server.address
)
elif mode == "transparent":
- root_layer = protocol2.TransparentProxy(root_context)
+ return protocol2.TransparentProxy(root_context)
elif mode == "reverse":
client_tls = self.config.upstream_server.scheme.startswith("https")
server_tls = self.config.upstream_server.scheme.endswith("https")
- root_layer = protocol2.ReverseProxy(
+ return protocol2.ReverseProxy(
root_context,
self.config.upstream_server.address,
client_tls,
server_tls
)
elif mode == "socks5":
- root_layer = protocol2.Socks5Proxy(root_context)
+ return protocol2.Socks5Proxy(root_context)
elif mode == "regular":
- root_layer = protocol2.HttpProxy(root_context)
+ return protocol2.HttpProxy(root_context)
elif callable(mode): # pragma: nocover
- root_layer = mode(root_context)
+ return mode(root_context)
else: # pragma: nocover
raise ValueError("Unknown proxy mode: %s" % mode)
+ def handle(self):
+ self.log("clientconnect", "info")
+
+ root_layer = self._create_root_layer()
+
try:
root_layer()
- except Kill as e:
+ except Kill:
self.log("Connection killed", "info")
except ProtocolException as e:
self.log(e, "info")
@@ -131,349 +129,8 @@ class ConnectionHandler2:
print("Please lodge a bug report at: https://github.com/mitmproxy/mitmproxy", file=sys.stderr)
self.log("clientdisconnect", "info")
-
- def finish(self):
- self.client_conn.finish()
-
- def log(self, msg, level, subs=()):
- # FIXME: Duplicate code
- full_msg = [
- "%s:%s: %s" %
- (self.client_conn.address.host,
- self.client_conn.address.port,
- msg)]
- for i in subs:
- full_msg.append(" -> " + i)
- full_msg = "\n".join(full_msg)
- self.channel.tell("log", Log(full_msg, level))
-
-
-class ConnectionHandler:
- def __init__(
- self,
- config,
- client_connection,
- client_address,
- server,
- channel):
- self.config = config
- """@type: libmproxy.proxy.config.ProxyConfig"""
- self.client_conn = ClientConnection(
- client_connection,
- client_address,
- server)
- """@type: libmproxy.proxy.connection.ClientConnection"""
- self.server_conn = None
- """@type: libmproxy.proxy.connection.ServerConnection"""
- self.channel = channel
- """@type: libmproxy.controller.Channel"""
-
- self.conntype = "http"
-
- def handle(self):
- try:
- self.log("clientconnect", "info")
-
- # Can we already identify the target server and connect to it?
- client_ssl, server_ssl = False, False
- conn_kwargs = dict()
- upstream_info = self.config.mode.get_upstream_server(
- self.client_conn)
- if upstream_info:
- self.set_server_address(upstream_info[2:])
- client_ssl, server_ssl = upstream_info[:2]
- if self.config.check_ignore(self.server_conn.address):
- self.log(
- "Ignore host: %s:%s" %
- self.server_conn.address(),
- "info")
- self.conntype = "tcp"
- conn_kwargs["log"] = False
- client_ssl, server_ssl = False, False
- else:
- # No upstream info from the metadata: upstream info in the
- # protocol (e.g. HTTP absolute-form)
- pass
-
- self.channel.ask("clientconnect", self)
-
- # Check for existing connection: If an inline script already established a
- # connection, do not apply client_ssl or server_ssl.
- if self.server_conn and not self.server_conn.connection:
- self.establish_server_connection()
- if client_ssl or server_ssl:
- self.establish_ssl(client=client_ssl, server=server_ssl)
-
- if self.config.check_tcp(self.server_conn.address):
- self.log(
- "Generic TCP mode for host: %s:%s" %
- self.server_conn.address(),
- "info")
- self.conntype = "tcp"
-
- elif not self.server_conn and self.config.mode == "sslspoof":
- port = self.config.mode.sslport
- self.set_server_address(("-", port))
- self.establish_ssl(client=True)
- host = self.client_conn.connection.get_servername()
- if host:
- self.set_server_address((host, port))
- self.establish_server_connection()
- self.establish_ssl(server=True, sni=host)
-
- # Delegate handling to the protocol handler
- protocol_handler(
- self.conntype)(
- self,
- **conn_kwargs).handle_messages()
-
- self.log("clientdisconnect", "info")
- self.channel.tell("clientdisconnect", self)
-
- except ProxyError as e:
- protocol_handler(self.conntype)(self, **conn_kwargs).handle_error(e)
- except Exception:
- import traceback
- import sys
-
- self.log(traceback.format_exc(), "error")
- print(traceback.format_exc(), file=sys.stderr)
- print("mitmproxy has crashed!", file=sys.stderr)
- print("Please lodge a bug report at: https://github.com/mitmproxy/mitmproxy", file=sys.stderr)
- finally:
- # Make sure that we close the server connection in any case.
- # The client connection is closed by the ProxyServer and does not
- # have be handled here.
- self.del_server_connection()
-
- def del_server_connection(self):
- """
- Deletes (and closes) an existing server connection.
- """
- if self.server_conn and self.server_conn.connection:
- self.server_conn.finish()
- self.server_conn.close()
- self.log(
- "serverdisconnect", "debug", [
- "%s:%s" %
- (self.server_conn.address.host, self.server_conn.address.port)])
- self.channel.tell("serverdisconnect", self)
- self.server_conn = None
-
- def set_server_address(self, addr):
- """
- Sets a new server address with the given priority.
- Does not re-establish either connection or SSL handshake.
- """
- address = tcp.Address.wrap(addr)
-
- # Don't reconnect to the same destination.
- if self.server_conn and self.server_conn.address == address:
- return
-
- if self.server_conn:
- self.del_server_connection()
-
- self.log(
- "Set new server address: %s:%s" %
- (address.host, address.port), "debug")
- self.server_conn = ServerConnection(address)
-
- def establish_server_connection(self, ask=True):
- """
- Establishes a new server connection.
- If there is already an existing server connection, the function returns immediately.
-
- By default, this function ".ask"s the proxy master. This is deadly if this function is already called from the
- master (e.g. via change_server), because this navigates us in a simple deadlock (the master is single-threaded).
- In these scenarios, ask=False can be passed to suppress the call to the master.
- """
- if self.server_conn.connection:
- return
- self.log(
- "serverconnect", "debug", [
- "%s:%s" %
- self.server_conn.address()[
- :2]])
- if ask:
- self.channel.ask("serverconnect", self)
- try:
- self.server_conn.connect()
- except tcp.NetLibError as v:
- raise ProxyError(502, v)
-
- def establish_ssl(self, client=False, server=False, sni=None):
- """
- Establishes SSL on the existing connection(s) to the server or the client,
- as specified by the parameters.
- """
-
- # Logging
- if client or server:
- subs = []
- if client:
- subs.append("with client")
- if server:
- subs.append("with server (sni: %s)" % sni)
- self.log("Establish SSL", "debug", subs)
-
- if server:
- if not self.server_conn or not self.server_conn.connection:
- raise ProxyError(502, "No server connection.")
- if self.server_conn.ssl_established:
- raise ProxyError(502, "SSL to Server already established.")
- try:
- self.server_conn.establish_ssl(
- self.config.clientcerts,
- sni,
- method=self.config.openssl_method_server,
- options=self.config.openssl_options_server,
- verify_options=self.config.openssl_verification_mode_server,
- ca_path=self.config.openssl_trusted_cadir_server,
- 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:
- self.log(
- "SSL verification failed for upstream server at depth %s with error: %s" %
- (ssl_cert_err['depth'], ssl_cert_err['errno']),
- "error")
- self.log("Ignoring server verification error, continuing with connection", "error")
- except tcp.NetLibError as v:
- e = ProxyError(502, repr(v))
- # Workaround for https://github.com/mitmproxy/mitmproxy/issues/427
- # The upstream server may reject connections without SNI, which means we need to
- # establish SSL with the client first, hope for a SNI (which triggers a reconnect which replaces the
- # ServerConnection object) and see whether that worked.
- if client and "handshake failure" in e.message:
- self.server_conn.may_require_sni = e
- else:
- ssl_cert_err = self.server_conn.ssl_verification_error
- if ssl_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']),
- "error")
- self.log("Aborting connection attempt", "error")
- raise e
- if client:
- if self.client_conn.ssl_established:
- raise ProxyError(502, "SSL to Client already established.")
- cert, key, chain_file = self.find_cert()
- try:
- self.client_conn.convert_to_ssl(
- cert, key,
- method=self.config.openssl_method_client,
- options=self.config.openssl_options_client,
- handle_sni=self.handle_sni,
- cipher_list=self.config.ciphers_client,
- dhparams=self.config.certstore.dhparams,
- chain_file=chain_file
- )
- except tcp.NetLibError as v:
- raise ProxyError(400, repr(v))
-
- # Workaround for #427 part 2
- if server and hasattr(self.server_conn, "may_require_sni"):
- raise self.server_conn.may_require_sni
-
- def server_reconnect(self, new_sni=False):
- address = self.server_conn.address
- had_ssl = self.server_conn.ssl_established
- state = self.server_conn.state
- sni = new_sni or self.server_conn.sni
- self.log("(server reconnect follows)", "debug")
- self.del_server_connection()
- self.set_server_address(address)
- self.establish_server_connection()
-
- for s in state:
- protocol_handler(s[0])(self).handle_server_reconnect(s[1])
- self.server_conn.state = state
-
- # Receiving new_sni where had_ssl is False is a weird case that happens when the workaround for
- # https://github.com/mitmproxy/mitmproxy/issues/427 is active. In this
- # case, we want to establish SSL as well.
- if had_ssl or new_sni:
- self.establish_ssl(server=True, sni=sni)
-
- def finish(self):
self.client_conn.finish()
- def log(self, msg, level, subs=()):
- full_msg = [
- "%s:%s: %s" %
- (self.client_conn.address.host,
- self.client_conn.address.port,
- msg)]
- for i in subs:
- full_msg.append(" -> " + i)
- full_msg = "\n".join(full_msg)
- self.channel.tell("log", Log(full_msg, level))
-
- def find_cert(self):
- host = self.server_conn.address.host
- sans = []
- if self.server_conn.ssl_established and (
- not self.config.no_upstream_cert):
- upstream_cert = self.server_conn.cert
- sans.extend(upstream_cert.altnames)
- if upstream_cert.cn:
- sans.append(host)
- host = upstream_cert.cn.decode("utf8").encode("idna")
- if self.server_conn.sni:
- sans.append(self.server_conn.sni)
- # for ssl spoof mode
- if hasattr(self.client_conn, "sni"):
- sans.append(self.client_conn.sni)
-
- ret = self.config.certstore.get_cert(host, sans)
- if not ret:
- raise ProxyError(502, "Unable to generate dummy cert.")
- return ret
-
- def handle_sni(self, connection):
- """
- This callback gets called during the SSL handshake with the client.
- The client has just sent the Sever Name Indication (SNI). We now connect upstream to
- figure out which certificate needs to be served.
- """
- try:
- sn = connection.get_servername()
- if not sn:
- return
- sni = sn.decode("utf8").encode("idna")
- # for ssl spoof mode
- self.client_conn.sni = sni
-
- if sni != self.server_conn.sni:
- self.log("SNI received: %s" % sni, "debug")
- # We should only re-establish upstream SSL if one of the following conditions is true:
- # - We established SSL with the server previously
- # - We initially wanted to establish SSL with the server,
- # but the server refused to negotiate without SNI.
- if self.server_conn.ssl_established or hasattr(
- self.server_conn,
- "may_require_sni"):
- # reconnect to upstream server with SNI
- self.server_reconnect(sni)
- # Now, change client context to reflect changed certificate:
- cert, key, chain_file = self.find_cert()
- new_context = self.client_conn.create_ssl_context(
- cert, key,
- method=self.config.openssl_method_client,
- options=self.config.openssl_options_client,
- cipher_list=self.config.ciphers_client,
- dhparams=self.config.certstore.dhparams,
- chain_file=chain_file
- )
- connection.set_context(new_context)
- # An unhandled exception in this method will core dump PyOpenSSL, so
- # make dang sure it doesn't happen.
- except: # pragma: no cover
- import traceback
- self.log(
- "Error in handle_sni:\r\n" +
- traceback.format_exc(),
- "error")
+ def log(self, msg, level):
+ msg = "{}: {}".format(repr(self.client_conn.address), msg)
+ self.channel.tell("log", Log(msg, level)) \ No newline at end of file
diff --git a/libmproxy/utils.py b/libmproxy/utils.py
index 3ac3cc01..a6ca55f7 100644
--- a/libmproxy/utils.py
+++ b/libmproxy/utils.py
@@ -1,14 +1,10 @@
from __future__ import absolute_import
import os
import datetime
-import urllib
import re
import time
-import functools
-import cgi
import json
-import netlib.utils
def timestamp():
"""