mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-26 10:16:27 +00:00
Improve the way we handle upstream errors
- Don't log a traceback for either HTTP or HTTPS DNS resolution or TCP connection errors. These are "ordinary" errors, not mitmproxy issues. - Ensure that the error handler is correctly called for SSL-related protocol errors.
This commit is contained in:
parent
9306e80e65
commit
afe34e8b28
@ -32,8 +32,8 @@ class MyMaster(flow.FlowMaster):
|
|||||||
print("error", f)
|
print("error", f)
|
||||||
|
|
||||||
@controller.handler
|
@controller.handler
|
||||||
def log(self, f):
|
def log(self, l):
|
||||||
print("log", f)
|
print("log", l.msg)
|
||||||
|
|
||||||
opts = options.Options(cadir="~/.mitmproxy/")
|
opts = options.Options(cadir="~/.mitmproxy/")
|
||||||
config = ProxyConfig(opts)
|
config = ProxyConfig(opts)
|
||||||
|
@ -142,39 +142,53 @@ class HttpLayer(base.Layer):
|
|||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
request = self.get_request_from_client()
|
request = self.get_request_from_client()
|
||||||
self.log("request", "debug", [repr(request)])
|
|
||||||
|
|
||||||
# Handle Proxy Authentication
|
|
||||||
# Proxy Authentication conceptually does not work in transparent mode.
|
|
||||||
# We catch this misconfiguration on startup. Here, we sort out requests
|
|
||||||
# after a successful CONNECT request (which do not need to be validated anymore)
|
|
||||||
if not (self.http_authenticated or self.authenticate(request)):
|
|
||||||
return
|
|
||||||
|
|
||||||
# Make sure that the incoming request matches our expectations
|
# Make sure that the incoming request matches our expectations
|
||||||
self.validate_request(request)
|
self.validate_request(request)
|
||||||
|
except netlib.exceptions.HttpReadDisconnect:
|
||||||
|
# don't throw an error for disconnects that happen before/between requests.
|
||||||
|
return
|
||||||
|
except netlib.exceptions.HttpException as e:
|
||||||
|
# We optimistically guess there might be an HTTP client on the
|
||||||
|
# other end
|
||||||
|
self.send_error_response(400, repr(e))
|
||||||
|
self.log(
|
||||||
|
"request",
|
||||||
|
"warn",
|
||||||
|
"HTTP protocol error in client request: %s" % e
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
self.log("request", "debug", [repr(request)])
|
||||||
|
|
||||||
|
# Handle Proxy Authentication
|
||||||
|
# Proxy Authentication conceptually does not work in transparent mode.
|
||||||
|
# We catch this misconfiguration on startup. Here, we sort out requests
|
||||||
|
# after a successful CONNECT request (which do not need to be validated anymore)
|
||||||
|
if not (self.http_authenticated or self.authenticate(request)):
|
||||||
|
return
|
||||||
|
|
||||||
|
flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self)
|
||||||
|
flow.request = request
|
||||||
|
|
||||||
|
try:
|
||||||
# Regular Proxy Mode: Handle CONNECT
|
# Regular Proxy Mode: Handle CONNECT
|
||||||
if self.mode == "regular" and request.first_line_format == "authority":
|
if self.mode == "regular" and request.first_line_format == "authority":
|
||||||
self.handle_regular_mode_connect(request)
|
self.handle_regular_mode_connect(request)
|
||||||
return
|
return
|
||||||
except netlib.exceptions.HttpReadDisconnect:
|
except (exceptions.ProtocolException, netlib.exceptions.NetlibException) as e:
|
||||||
# don't throw an error for disconnects that happen before/between requests.
|
# HTTPS tasting means that ordinary errors like resolution and
|
||||||
|
# connection errors can happen here.
|
||||||
|
self.send_error_response(502, repr(e))
|
||||||
|
flow.error = models.Error(str(e))
|
||||||
|
self.channel.ask("error", flow)
|
||||||
return
|
return
|
||||||
except netlib.exceptions.NetlibException as e:
|
|
||||||
self.send_error_response(400, repr(e))
|
# set upstream auth
|
||||||
six.reraise(exceptions.ProtocolException, exceptions.ProtocolException(
|
if self.mode == "upstream" and self.config.upstream_auth is not None:
|
||||||
"Error in HTTP connection: %s" % repr(e)), sys.exc_info()[2])
|
flow.request.headers["Proxy-Authorization"] = self.config.upstream_auth
|
||||||
|
self.process_request_hook(flow)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
flow = models.HTTPFlow(self.client_conn, self.server_conn, live=self)
|
|
||||||
flow.request = request
|
|
||||||
|
|
||||||
# set upstream auth
|
|
||||||
if self.mode == "upstream" and self.config.upstream_auth is not None:
|
|
||||||
flow.request.headers["Proxy-Authorization"] = self.config.upstream_auth
|
|
||||||
self.process_request_hook(flow)
|
|
||||||
|
|
||||||
if not flow.response:
|
if not flow.response:
|
||||||
self.establish_server_connection(
|
self.establish_server_connection(
|
||||||
flow.request.host,
|
flow.request.host,
|
||||||
@ -209,11 +223,9 @@ class HttpLayer(base.Layer):
|
|||||||
|
|
||||||
except (exceptions.ProtocolException, netlib.exceptions.NetlibException) as e:
|
except (exceptions.ProtocolException, netlib.exceptions.NetlibException) as e:
|
||||||
self.send_error_response(502, repr(e))
|
self.send_error_response(502, repr(e))
|
||||||
|
|
||||||
if not flow.response:
|
if not flow.response:
|
||||||
flow.error = models.Error(str(e))
|
flow.error = models.Error(str(e))
|
||||||
self.channel.ask("error", flow)
|
self.channel.ask("error", flow)
|
||||||
self.log(traceback.format_exc(), "debug")
|
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
six.reraise(exceptions.ProtocolException, exceptions.ProtocolException(
|
six.reraise(exceptions.ProtocolException, exceptions.ProtocolException(
|
||||||
|
Loading…
Reference in New Issue
Block a user