fix bugs, make https work

This commit is contained in:
Maximilian Hils 2015-08-15 20:20:46 +02:00
parent 0dd243c5e4
commit 2a15479cdb
6 changed files with 37 additions and 41 deletions

View File

@ -4,7 +4,7 @@ from .. import version
from ..exceptions import InvalidCredentials, HttpException, ProtocolException
from .layer import Layer, ServerConnectionMixin
from libmproxy import utils
from .messages import ChangeServer, Connect, Reconnect, Kill
from .messages import SetServer, Connect, Reconnect, Kill
from libmproxy.protocol import KILL
from libmproxy.protocol.http import HTTPFlow
@ -71,19 +71,9 @@ class HttpLayer(Layer):
HTTP 1 Layer
"""
def __init__(self, ctx):
def __init__(self, ctx, mode):
super(HttpLayer, self).__init__(ctx)
# FIXME: Imports
from .http_proxy import HttpProxy, HttpUpstreamProxy
if any(isinstance(l, HttpProxy) for l in self.layers):
self.mode = "regular"
elif any(isinstance(l, HttpUpstreamProxy) for l in self.layers):
self.mode = "upstream"
else:
# also includes socks or reverse mode, which are handled similarly on this layer.
self.mode = "transparent"
self.mode = mode
def __call__(self):
while True:
@ -104,7 +94,7 @@ class HttpLayer(Layer):
# Regular Proxy Mode: Handle CONNECT
if self.mode == "regular" and request.form_in == "authority":
self.server_address = (request.host, request.port)
yield SetServer((request.host, request.port), False, None)
self.send_to_client(make_connect_response(request.httpversion))
layer = self.ctx.next_layer(self)
for message in layer():
@ -255,7 +245,7 @@ class HttpLayer(Layer):
else:
flow.request.host = self.ctx.server_address.host
flow.request.port = self.ctx.server_address.port
flow.request.scheme = self.server_conn.tls_established
flow.request.scheme = "https" if self.server_conn.tls_established else "http"
# TODO: Expose ChangeServer functionality to inline scripts somehow? (yield_from_callback?)
request_reply = self.channel.ask("request", flow)
@ -271,8 +261,8 @@ class HttpLayer(Layer):
tls = (flow.request.scheme == "https")
if self.mode == "regular" or self.mode == "transparent":
# If there's an existing connection that doesn't match our expectations, kill it.
if self.server_address != address or tls != self.server_address.ssl_established:
yield ChangeServer(address, tls, address.host)
if self.server_address != address or tls != self.server_conn.ssl_established:
yield SetServer(address, tls, address.host)
# Establish connection is neccessary.
if not self.server_conn:
yield Connect()

View File

@ -6,7 +6,7 @@ from .http import HttpLayer
class HttpProxy(Layer, ServerConnectionMixin):
def __call__(self):
layer = HttpLayer(self)
layer = HttpLayer(self, "regular")
for message in layer():
if not self._handle_server_message(message):
yield message
@ -18,7 +18,7 @@ class HttpUpstreamProxy(Layer, ServerConnectionMixin):
self.server_address = server_address
def __call__(self):
layer = HttpLayer(self)
layer = HttpLayer(self, "upstream")
for message in layer():
if not self._handle_server_message(message):
yield message

View File

@ -35,7 +35,7 @@ import threading
from netlib import tcp
from ..proxy import Log
from ..proxy.connection import ServerConnection
from .messages import Connect, Reconnect, ChangeServer, Kill
from .messages import Connect, Reconnect, SetServer, Kill
from ..exceptions import ProtocolException
@ -116,7 +116,7 @@ class ServerConnectionMixin(object):
elif message == Connect:
self._connect()
return True
elif message == ChangeServer and message.depth == 1:
elif message == SetServer and message.depth == 1:
if self.server_conn:
self._disconnect()
self.server_address = message.address

View File

@ -27,7 +27,7 @@ class Reconnect(_Message):
"""
class ChangeServer(_Message):
class SetServer(_Message):
"""
Change the upstream server.
"""

View File

@ -2,7 +2,7 @@ from __future__ import (absolute_import, print_function, division)
from .rawtcp import RawTcpLayer
from .tls import TlsLayer
from .http import HttpLayer
class RootContext(object):
"""
@ -38,10 +38,12 @@ class RootContext(object):
return
if is_tls_client_hello:
layer = TlsLayer(top_layer, True, True)
return TlsLayer(top_layer, True, True)
elif isinstance(top_layer, TlsLayer) and isinstance(top_layer.ctx, HttpLayer):
return HttpLayer(top_layer, "transparent")
else:
layer = RawTcpLayer(top_layer)
return layer
return RawTcpLayer(top_layer)
@property
def layers(self):

View File

@ -5,7 +5,7 @@ from netlib import tcp
from ..exceptions import ProtocolException
from .layer import Layer, yield_from_callback
from .messages import Connect, Reconnect, ChangeServer
from .messages import Connect, Reconnect, SetServer
class TlsLayer(Layer):
@ -13,7 +13,6 @@ class TlsLayer(Layer):
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
@ -44,9 +43,6 @@ class TlsLayer(Layer):
client_tls_requires_server_cert = (
self._client_tls and self._server_tls and not self.config.no_upstream_cert
)
lazy_server_tls = (
self._server_tls and not client_tls_requires_server_cert
)
if client_tls_requires_server_cert:
for m in self._establish_tls_with_client_and_server():
@ -56,18 +52,27 @@ class TlsLayer(Layer):
yield m
layer = self.ctx.next_layer(self)
for message in layer():
if message != Connect or not self._connected:
self.log("TlsLayer: %s" % message,"debug")
if not (message == Connect and self._connected):
yield message
if message == Connect:
if lazy_server_tls:
if message == Connect or message == Reconnect:
if self._server_tls and not self._server_tls_established:
self._establish_tls_with_server()
if message == ChangeServer and message.depth == 1:
self._server_tls = message.server_tls
if message == SetServer and message.depth == 1:
if message.server_tls is not None:
self._sni_from_server_change = message.sni
if message == Reconnect or message == ChangeServer:
if self._server_tls:
self._establish_tls_with_server()
self._server_tls = message.server_tls
@property
def _server_tls_established(self):
return self.server_conn and self.server_conn.tls_established
@property
def _connected(self):
return bool(self.server_conn)
@property
def sni_for_upstream_connection(self):
@ -83,7 +88,6 @@ class TlsLayer(Layer):
# First, try to connect to the server.
yield Connect()
self._connected = True
server_err = None
try:
self._establish_tls_with_server()