Exemplo n.º 1
0
    def request(self, f, kill_miss=False):
        ''' return whether the request is killed '''
        _, netloc, _, _, _, _ = urllib.parse.urlparse(f.request.url)

        # some websites use certificate pinning to prevent Man-In-Middle attach.
        # this means our cache fails so we should avoid making requests to them.
        if netloc in IGNORE_DOMAINS:
            f.response = make_error_response(404, 'ignore requested domain')
            return True

        # reject https connect requests since we don't support them.
        if f.request.data.method == 'CONNECT':
            f.reply.kill()
            return True

        rflows = self.get(f)

        if rflows:
            rflow = rflows[-1]
            response = rflow.response.copy()
            response.is_replay = True
            if self.options.refresh_server_playback:
                response.refresh()
            f.response = response
            if not self.flowmap and not self.options.keepserving:
                self.final_flow = f
                self.stop = True
        elif kill_miss:
            logger.warn("server_playback: killed non-replay request {}".format(
                f.request))
            f.response = make_error_response(404, 'ignore requested domain')
            return True
        return False
Exemplo n.º 2
0
    def handle(self):
        self.log("clientconnect", "info")

        root_layer = None
        try:
            root_layer = self._create_root_layer()
            root_layer = self.channel.ask("clientconnect", root_layer)
            root_layer()
        except exceptions.Kill:
            self.log("Connection killed", "info")
        except exceptions.ProtocolException as e:
            if isinstance(e, exceptions.ClientHandshakeException):
                self.log(
                    "Client Handshake failed. "
                    "The client {} may not trust the proxy's certificate for {}."
                    .format(self.client_conn.address[0], e.server), "warn")
                self.log(repr(e), "debug")
                # ReCon / Mon(IoT)r Modification
                source_ip = self.client_conn.address[0]
                if source_ip[:7] == '::ffff:':
                    source_ip = source_ip[7:]
                dest = e.server
                if dest[0] == '(':
                    dest = dest[2:]
                    dest = dest[:dest.index("'")]
                try:
                    command = ctx.options.mitm_exception + " addauto " + source_ip + " " + dest
                    self.log("Adding MITM exception: " + command, "info")
                    subprocess.call(command, shell=True)
                except AttributeError as e2:
                    pass
            elif isinstance(e, exceptions.InvalidServerCertificate):
                self.log(str(e), "warn")
                self.log(
                    "Invalid certificate, closing connection. Pass --insecure to disable validation.",
                    "warn")
            else:
                self.log(str(e), "warn")

                self.log(repr(e), "debug")
            # If an error propagates to the topmost level,
            # we send an HTTP error response, which is both
            # understandable by HTTP clients and humans.
            try:
                error_response = http.make_error_response(502, repr(e))
                self.client_conn.send(http1.assemble_response(error_response))
            except exceptions.TcpException:
                pass
        except Exception:
            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)

        self.log("clientdisconnect", "info")
        if root_layer is not None:
            self.channel.tell("clientdisconnect", root_layer)
        self.client_conn.finish()
Exemplo n.º 3
0
 def request(self, flow: HTTPFlow):
     if flow.request.host == 'dummy-upstream':
         flow.error = Error('No upstream is configured.')
         flow.response = make_error_response(
             400,
             'No upstream is configured.',
         )
Exemplo n.º 4
0
 def send_error_response(self, code, message, headers=None):
     try:
         response = http.make_error_response(code, message, headers)
         self.send_response(response)
     except (exceptions.NetlibException, h2.exceptions.H2Error,
             exceptions.Http2ProtocolException):
         self.log(traceback.format_exc(), "debug")
Exemplo n.º 5
0
 def send_error_response(self, code, message, headers=None) -> None:
     try:
         response = http.make_error_response(code, message, headers)
         self.send_response(response)
     except (exceptions.NetlibException, h2.exceptions.H2Error,
             exceptions.Http2ProtocolException):
         self.log(f"Failed to send error response to client: {message}",
                  "debug")
Exemplo n.º 6
0
 def authenticate(self, request):
     if self.config.authenticator:
         if not self.config.authenticator.authenticate(request.headers):
             if self.mode == "transparent":
                 self.send_response(http.make_error_response(
                     401,
                     "Authentication Required",
                     mitmproxy.net.http.Headers(**self.config.authenticator.auth_challenge_headers())
                 ))
             else:
                 self.send_response(http.make_error_response(
                     407,
                     "Proxy Authentication Required",
                     mitmproxy.net.http.Headers(**self.config.authenticator.auth_challenge_headers())
                 ))
             return False
     return True
Exemplo n.º 7
0
    def auth_required_response(self, f):
        if f.mode == "regular":
            hdrname = 'Proxy-Authenticate'
        else:
            hdrname = 'WWW-Authenticate'

        headers = mitmproxy.net.http.Headers()
        headers[hdrname] = 'Basic realm="%s"' % REALM

        if f.mode == "transparent":
            return http.make_error_response(401, "Authentication Required",
                                            headers)
        else:
            return http.make_error_response(
                407,
                "Proxy Authentication Required",
                headers,
            )
Exemplo n.º 8
0
 def authenticate(self, request):
     if self.config.authenticator:
         if self.config.authenticator.authenticate(request.headers):
             self.config.authenticator.clean(request.headers)
         else:
             if self.mode == "transparent":
                 self.send_response(http.make_error_response(
                     401,
                     "Authentication Required",
                     mitmproxy.net.http.Headers(**self.config.authenticator.auth_challenge_headers())
                 ))
             else:
                 self.send_response(http.make_error_response(
                     407,
                     "Proxy Authentication Required",
                     mitmproxy.net.http.Headers(**self.config.authenticator.auth_challenge_headers())
                 ))
             return False
     return True
Exemplo n.º 9
0
 def request(self, flow: HTTPFlow):
     # Remove "vgs-client" header, that is sent by VGS-Collect.
     # This copies logic from proxy
     flow.request.headers.pop('vgs-client', None)
     if flow.request.host == 'dummy-upstream':
         flow.error = Error('No upstream is configured.')
         flow.response = make_error_response(
             400,
             'No upstream is configured.',
         )
Exemplo n.º 10
0
    def auth_required_response(self, f):
        if f.mode == "regular":
            hdrname = 'Proxy-Authenticate'
        else:
            hdrname = 'WWW-Authenticate'

        headers = mitmproxy.net.http.Headers()
        headers[hdrname] = 'Basic realm="%s"' % REALM

        if f.mode == "transparent":
            return http.make_error_response(
                401,
                "Authentication Required",
                headers
            )
        else:
            return http.make_error_response(
                407,
                "Proxy Authentication Required",
                headers,
            )
Exemplo n.º 11
0
def response(flow: http.HTTPFlow) -> None:
    if flow.request.path.split('?')[0] not in PATHS: return

    with CV[flow]:
        CV[flow].notify_all()
    with CV[flow]:
        if not CV[flow].wait(timeout=1.5):
            ctx.log.warn("<!> Wait timeout: response match error!")
            flow.response = http.make_error_response(
                500, "Wait timeout: response match error!")

    del CV[flow]
Exemplo n.º 12
0
    def handle(self):
        self.log("clientconnect", "info")

        root_layer = None
        try:
            root_layer = self._create_root_layer()
            root_layer = self.channel.ask("clientconnect", root_layer)
            root_layer()
        except exceptions.Kill:
            self.log("Connection killed", "info")
        except exceptions.ProtocolException as e:
            if isinstance(e, exceptions.ClientHandshakeException):
                selfc.SelfCShared.writeFailedSSLDomain(
                    str(e.server),
                    "2*** Client Handshake failed. The client may not trust the proxy's certificate",
                    self.client_conn.ip_address)
                self.log(
                    "Client Handshake failed. "
                    "The client may not trust the proxy's certificate for {}.".
                    format(e.server), "warn")
                self.log(repr(e), "debug")
            elif isinstance(e, exceptions.InvalidServerCertificate):
                self.log(str(e), "warn")
                self.log(
                    "Invalid certificate, closing connection. Pass --ssl-insecure to disable validation.",
                    "warn")
            else:
                self.log(str(e), "warn")

                self.log(repr(e), "debug")
            # If an error propagates to the topmost level,
            # we send an HTTP error response, which is both
            # understandable by HTTP clients and humans.
            try:
                error_response = http.make_error_response(502, repr(e))
                self.client_conn.send(http1.assemble_response(error_response))
            except exceptions.TcpException:
                pass
        except Exception:
            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)

        self.log("clientdisconnect", "info")
        if root_layer is not None:
            self.channel.tell("clientdisconnect", root_layer)
        self.client_conn.finish()
Exemplo n.º 13
0
def request(flow: http.HTTPFlow) -> None:
    if flow.request.path.split('?')[0] not in PATHS: return

    CV[flow] = threading.Condition()
    ts = []
    for h in HANDLERS:
        t = PVThread(target=h, args=(flow, ))
        t.daemon = True
        t.start()
    with CV[flow]:
        CV[flow].notify_all()
    with CV[flow]:
        if not CV[flow].wait(timeout=1.5):
            ctx.log.warn("<!> Wait timeout: request match error!")
            flow.response = http.make_error_response(
                500, "Wait timeout: request match error!")
Exemplo n.º 14
0
    def handle(self):
        self.log("clientconnect", "info")

        root_layer = None
        try:
            root_layer = self._create_root_layer()
            root_layer = self.channel.ask("clientconnect", root_layer)
            root_layer()
        except exceptions.Kill:
            self.log("Connection killed", "info")
        except exceptions.ProtocolException as e:
            if isinstance(e, exceptions.ClientHandshakeException):
                self.log(
                    "Client Handshake failed. "
                    "The client may not trust the proxy's certificate for {}.".format(e.server),
                    "warn"
                )
                self.log(repr(e), "debug")
            elif isinstance(e, exceptions.InvalidServerCertificate):
                self.log(str(e), "warn")
                self.log("Invalid certificate, closing connection. Pass --insecure to disable validation.", "warn")
            else:
                self.log(str(e), "warn")

                self.log(repr(e), "debug")
            # If an error propagates to the topmost level,
            # we send an HTTP error response, which is both
            # understandable by HTTP clients and humans.
            try:
                error_response = http.make_error_response(502, repr(e))
                self.client_conn.send(http1.assemble_response(error_response))
            except exceptions.TcpException:
                pass
        except Exception:
            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)

        self.log("clientdisconnect", "info")
        if root_layer is not None:
            self.channel.tell("clientdisconnect", root_layer)
        self.client_conn.finish()
Exemplo n.º 15
0
    def send(self, event: HttpEvent) -> layer.CommandGenerator[None]:
        assert event.stream_id == self.stream_id
        if isinstance(event, ResponseHeaders):
            self.response = response = event.response

            if response.is_http2:
                response = response.copy()
                # Convert to an HTTP/1 response.
                response.http_version = "HTTP/1.1"
                # not everyone supports empty reason phrases, so we better make up one.
                response.reason = status_codes.RESPONSES.get(
                    response.status_code, "")
                # Shall we set a Content-Length header here if there is none?
                # For now, let's try to modify as little as possible.

            raw = http1.assemble_response_head(response)
            yield commands.SendData(self.conn, raw)
        elif isinstance(event, ResponseData):
            assert self.response
            if "chunked" in self.response.headers.get("transfer-encoding",
                                                      "").lower():
                raw = b"%x\r\n%s\r\n" % (len(event.data), event.data)
            else:
                raw = event.data
            if raw:
                yield commands.SendData(self.conn, raw)
        elif isinstance(event, ResponseEndOfMessage):
            assert self.response
            if "chunked" in self.response.headers.get("transfer-encoding",
                                                      "").lower():
                yield commands.SendData(self.conn, b"0\r\n\r\n")
            yield from self.mark_done(response=True)
        elif isinstance(event, ResponseProtocolError):
            if not self.response:
                resp = http.make_error_response(event.code, event.message)
                raw = http1.assemble_response(resp)
                yield commands.SendData(self.conn, raw)
            yield commands.CloseConnection(self.conn)
        else:
            raise AssertionError(f"Unexpected event: {event}")
Exemplo n.º 16
0
 def send_error_response(self, code, message, headers=None):
     try:
         response = http.make_error_response(code, message, headers)
         self.send_response(response)
     except (exceptions.NetlibException, h2.exceptions.H2Error, exceptions.Http2ProtocolException):
         self.log(traceback.format_exc(), "debug")
Exemplo n.º 17
0
def test_make_error_response():
    resp = http.make_error_response(543, 'foobar', Headers())
    assert resp
Exemplo n.º 18
0
 def send_error_response(self, code, message, headers=None) -> None:
     try:
         response = http.make_error_response(code, message, headers)
         self.send_response(response)
     except (exceptions.NetlibException, h2.exceptions.H2Error, exceptions.Http2ProtocolException):
         self.log("Failed to send error response to client: {}".format(message), "debug")