mirror of
https://github.com/zhigang1992/mitmproxy.git
synced 2026-04-24 04:14:57 +08:00
wip commit
This commit is contained in:
@@ -18,5 +18,13 @@ class ProtocolException(ProxyException):
|
||||
pass
|
||||
|
||||
|
||||
class HttpException(ProtocolException):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidCredentials(HttpException):
|
||||
pass
|
||||
|
||||
|
||||
class ServerException(ProxyException):
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
from .layer import RootContext
|
||||
from .socks import Socks5IncomingLayer
|
||||
from .root_context import RootContext
|
||||
from .socks_proxy import Socks5Proxy
|
||||
from .reverse_proxy import ReverseProxy
|
||||
from .upstream_proxy import UpstreamProxy
|
||||
from .http_proxy import HttpProxy, HttpUpstreamProxy
|
||||
from .rawtcp import TcpLayer
|
||||
from .auto import AutoLayer
|
||||
__all__ = ["Socks5IncomingLayer", "TcpLayer", "AutoLayer", "RootContext", "ReverseProxy", "UpstreamProxy"]
|
||||
|
||||
__all__ = [
|
||||
"Socks5Proxy", "TcpLayer", "RootContext", "ReverseProxy", "HttpProxy", "HttpUpstreamProxy"
|
||||
]
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
from .layer import Layer
|
||||
|
||||
|
||||
class AutoLayer(Layer):
|
||||
def __call__(self):
|
||||
d = self.client_conn.rfile.peek(1)
|
||||
|
||||
if not d:
|
||||
return
|
||||
# TLS ClientHello magic, see http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html#client-hello
|
||||
if d[0] == "\x16":
|
||||
layer = TlsLayer(self, True, True)
|
||||
else:
|
||||
layer = TcpLayer(self)
|
||||
for m in layer():
|
||||
yield m
|
||||
|
||||
from .rawtcp import TcpLayer
|
||||
from .tls import TlsLayer
|
||||
90
libmproxy/protocol2/http.py
Normal file
90
libmproxy/protocol2/http.py
Normal file
@@ -0,0 +1,90 @@
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
|
||||
from .layer import Layer, ServerConnectionMixin
|
||||
from libmproxy import version
|
||||
from libmproxy.exceptions import InvalidCredentials
|
||||
from libmproxy.protocol.http import HTTPFlow
|
||||
from libmproxy.protocol.http_wrappers import HTTPResponse
|
||||
from libmproxy.protocol2.http_protocol_mock import HTTP1
|
||||
from netlib import tcp
|
||||
from netlib.http import status_codes
|
||||
from netlib import odict
|
||||
|
||||
|
||||
def send_http_error_response(status_code, message, headers=odict.ODictCaseless()):
|
||||
response = status_codes.RESPONSES.get(status_code, "Unknown")
|
||||
body = """
|
||||
<html>
|
||||
<head>
|
||||
<title>%d %s</title>
|
||||
</head>
|
||||
<body>%s</body>
|
||||
</html>
|
||||
""".strip() % (status_code, response, message)
|
||||
|
||||
headers["Server"] = [version.NAMEVERSION]
|
||||
headers["Connection"] = ["close"]
|
||||
headers["Content-Length"] = [len(body)]
|
||||
headers["Content-Type"] = ["text/html"]
|
||||
|
||||
resp = HTTPResponse(
|
||||
(1, 1), # if HTTP/2 is used, this value is ignored anyway
|
||||
status_code,
|
||||
response,
|
||||
headers,
|
||||
body,
|
||||
)
|
||||
|
||||
protocol = self.c.client_conn.protocol or http1.HTTP1Protocol(self.c.client_conn)
|
||||
self.c.client_conn.send(protocol.assemble(resp))
|
||||
|
||||
class HttpLayer(Layer, ServerConnectionMixin):
|
||||
"""
|
||||
HTTP 1 Layer
|
||||
"""
|
||||
|
||||
def __init__(self, ctx):
|
||||
super(HttpLayer, self).__init__(ctx)
|
||||
self.skip_authentication = False
|
||||
|
||||
def __call__(self):
|
||||
while True:
|
||||
flow = HTTPFlow(self.client_conn, self.server_conn)
|
||||
try:
|
||||
request = HTTP1.read_request(
|
||||
self.client_conn,
|
||||
body_size_limit=self.c.config.body_size_limit
|
||||
)
|
||||
except tcp.NetLibError:
|
||||
# don't throw an error for disconnects that happen
|
||||
# before/between requests.
|
||||
return
|
||||
|
||||
self.c.log("request", "debug", [repr(request)])
|
||||
|
||||
self.check_authentication(request)
|
||||
|
||||
if self.mode == "regular" and request.form_in == "authority":
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
|
||||
ret = self.process_request(flow, request)
|
||||
if ret is True:
|
||||
continue
|
||||
if ret is False:
|
||||
return
|
||||
|
||||
def check_authentication(self, request):
|
||||
if self.config.authenticator:
|
||||
if self.config.authenticator.authenticate(request.headers):
|
||||
self.config.authenticator.clean(request.headers)
|
||||
else:
|
||||
self.send_error()
|
||||
raise InvalidCredentials("Proxy Authentication Required")
|
||||
raise http.HttpAuthenticationError(
|
||||
self.c.config.authenticator.auth_challenge_headers())
|
||||
return request.headers
|
||||
|
||||
def send_error(self, code, message, headers):
|
||||
pass
|
||||
13
libmproxy/protocol2/http_protocol_mock.py
Normal file
13
libmproxy/protocol2/http_protocol_mock.py
Normal file
@@ -0,0 +1,13 @@
|
||||
"""
|
||||
Temporary mock to sort out API discrepancies
|
||||
"""
|
||||
from netlib.http.http1 import HTTP1Protocol
|
||||
|
||||
|
||||
class HTTP1(object):
|
||||
@staticmethod
|
||||
def read_request(connection, *args, **kwargs):
|
||||
"""
|
||||
:type connection: object
|
||||
"""
|
||||
return HTTP1Protocol(connection).read_request(*args, **kwargs)
|
||||
@@ -1,18 +1,23 @@
|
||||
from __future__ import (absolute_import, print_function, division)
|
||||
|
||||
from .layer import Layer, ServerConnectionMixin
|
||||
#from .http import HttpLayer
|
||||
from .http import HttpLayer
|
||||
|
||||
|
||||
class UpstreamProxy(Layer, ServerConnectionMixin):
|
||||
class HttpProxy(Layer):
|
||||
def __call__(self):
|
||||
layer = HttpLayer(self)
|
||||
for message in layer():
|
||||
yield message
|
||||
|
||||
|
||||
class HttpUpstreamProxy(Layer, ServerConnectionMixin):
|
||||
def __init__(self, ctx, server_address):
|
||||
super(UpstreamProxy, self).__init__(ctx)
|
||||
super(HttpUpstreamProxy, self).__init__(ctx)
|
||||
self.server_address = server_address
|
||||
|
||||
def __call__(self):
|
||||
#layer = HttpLayer(self)
|
||||
layer = None
|
||||
layer = HttpLayer(self)
|
||||
for message in layer():
|
||||
if not self._handle_server_message(message):
|
||||
yield message
|
||||
@@ -41,21 +41,6 @@ from .messages import Connect, Reconnect, ChangeServer
|
||||
from ..exceptions import ProtocolException
|
||||
|
||||
|
||||
class RootContext(object):
|
||||
"""
|
||||
The outmost context provided to the root layer.
|
||||
As a consequence, every layer has .client_conn, .channel and .config.
|
||||
"""
|
||||
|
||||
def __init__(self, client_conn, config, channel):
|
||||
self.client_conn = client_conn # Client Connection
|
||||
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):
|
||||
"""
|
||||
Dummy class that provides type hinting in PyCharm, which simplifies development a lot.
|
||||
@@ -208,4 +193,4 @@ def yield_from_callback(fun):
|
||||
|
||||
self.yield_from_callback = None
|
||||
|
||||
return wrapper
|
||||
return wrapper
|
||||
32
libmproxy/protocol2/root_context.py
Normal file
32
libmproxy/protocol2/root_context.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from .rawtcp import TcpLayer
|
||||
from .tls import TlsLayer
|
||||
|
||||
|
||||
class RootContext(object):
|
||||
"""
|
||||
The outmost context provided to the root layer.
|
||||
As a consequence, every layer has .client_conn, .channel, .next_layer() and .config.
|
||||
"""
|
||||
|
||||
def __init__(self, client_conn, config, channel):
|
||||
self.client_conn = client_conn # Client Connection
|
||||
self.channel = channel # provides .ask() method to communicate with FlowMaster
|
||||
self.config = config # Proxy Configuration
|
||||
|
||||
def next_layer(self, top_layer):
|
||||
"""
|
||||
This function determines the next layer in the protocol stack.
|
||||
:param top_layer: the current top layer
|
||||
:return: The next layer.
|
||||
"""
|
||||
|
||||
d = top_layer.client_conn.rfile.peek(1)
|
||||
|
||||
if not d:
|
||||
return
|
||||
# TLS ClientHello magic, see http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html#client-hello
|
||||
if d[0] == "\x16":
|
||||
layer = TlsLayer(top_layer, True, True)
|
||||
else:
|
||||
layer = TcpLayer(top_layer)
|
||||
return layer
|
||||
@@ -3,9 +3,9 @@ from __future__ import (absolute_import, print_function, division)
|
||||
from ..exceptions import ProtocolException
|
||||
from ..proxy import ProxyError, Socks5ProxyMode
|
||||
from .layer import Layer, ServerConnectionMixin
|
||||
from .auto import AutoLayer
|
||||
|
||||
class Socks5IncomingLayer(Layer, ServerConnectionMixin):
|
||||
|
||||
class Socks5Proxy(Layer, ServerConnectionMixin):
|
||||
def __call__(self):
|
||||
try:
|
||||
s5mode = Socks5ProxyMode(self.config.ssl_ports)
|
||||
@@ -16,7 +16,7 @@ class Socks5IncomingLayer(Layer, ServerConnectionMixin):
|
||||
|
||||
self.server_address = address
|
||||
|
||||
layer = AutoLayer(self)
|
||||
layer = self.ctx.next_layer(self)
|
||||
for message in layer():
|
||||
if not self._handle_server_message(message):
|
||||
yield message
|
||||
@@ -5,7 +5,6 @@ from netlib import tcp
|
||||
from ..exceptions import ProtocolException
|
||||
from .layer import Layer, yield_from_callback
|
||||
from .messages import Connect, Reconnect, ChangeServer
|
||||
from .auto import AutoLayer
|
||||
|
||||
|
||||
class TlsLayer(Layer):
|
||||
@@ -55,8 +54,7 @@ class TlsLayer(Layer):
|
||||
for m in self._establish_tls_with_client():
|
||||
yield m
|
||||
|
||||
self.next_layer()
|
||||
layer = AutoLayer(self)
|
||||
layer = self.ctx.next_layer(self)
|
||||
for message in layer():
|
||||
if message != Connect or not self._connected:
|
||||
yield message
|
||||
|
||||
@@ -3,7 +3,6 @@ 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):
|
||||
@@ -18,7 +17,7 @@ class TransparentProxy(Layer, ServerConnectionMixin):
|
||||
except Exception as e:
|
||||
raise ProtocolException("Transparent mode failure: %s" % repr(e), e)
|
||||
|
||||
layer = AutoLayer(self)
|
||||
layer = self.ctx.next_layer(self)
|
||||
for message in layer():
|
||||
if not self._handle_server_message(message):
|
||||
yield message
|
||||
|
||||
@@ -7,6 +7,7 @@ from netlib import tcp
|
||||
|
||||
from ..protocol.handle import protocol_handler
|
||||
from .. import protocol2
|
||||
from ..exceptions import ProtocolException
|
||||
from .primitives import ProxyServerError, Log, ProxyError
|
||||
from .connection import ClientConnection, ServerConnection
|
||||
|
||||
@@ -79,12 +80,12 @@ class ConnectionHandler2:
|
||||
self.config,
|
||||
self.channel
|
||||
)
|
||||
root_layer = protocol2.Socks5IncomingLayer(root_context)
|
||||
root_layer = protocol2.Socks5Proxy(root_context)
|
||||
|
||||
try:
|
||||
for message in root_layer():
|
||||
print("Root layer receveived: %s" % message)
|
||||
except protocol2.ProtocolException as e:
|
||||
except ProtocolException as e:
|
||||
self.log(e, "info")
|
||||
except Exception:
|
||||
self.log(traceback.format_exc(), "error")
|
||||
|
||||
Reference in New Issue
Block a user