Beispiel #1
0
def check_appid_exists(appid):
    request_params = gae_params_dict[appid]
    if isinstance(request_params, gae_params):
        http_util = http_gws
    else:
        if not hasattr(request_params, 'hostname'):
            _, (iporname, _) = get_connect_action(request_params.ssl,
                                                  request_params.host)
            request_params.hostname = set_dns(request_params.host, iporname)
        http_util = http_nor
    connection_cache_key = '%s:%d' % (request_params.hostname,
                                      request_params.port)
    for _ in range(3):
        err = None
        response = None
        try:
            sock = http_util.create_ssl_connection(
                (request_params.host, request_params.port),
                request_params.hostname, connection_cache_key)
            sock.sendall(b'HEAD / HTTP/1.1\r\n'
                         b'Host: %s\r\n'
                         b'Connection: Close\r\n\r\n' % host.encode())
            response = HTTPResponse(sock, method='HEAD')
            response.begin()
        except:
            err = True
        finally:
            if response:
                response.close()
                if err is None:
                    exists = response.status in (200, 503)
                    if exists:
                        http_util.ssl_connection_cache[
                            connection_cache_key].append((time(), sock))
                    return exists
Beispiel #2
0
    def __init__(self, request, proxy_socket):

        HttpTransfer.__init__(self)

        self.request = request

        h = HTTPResponse(proxy_socket)
        h.begin()
        # HTTPResponse会将所有chunk拼接到一起,因此会直接得到所有内容,所以不能有Transfer-Encoding
        del h.msg['Transfer-Encoding']
        del h.msg['Content-Length']

        self.response_version = self.version_dict[h.version]
        self.status = h.status
        self.reason = h.reason
        self.set_headers(h.msg)
        self.decoding = None
        self.language = self.system = self.webserver = None

        try:
            data = h.read()
            body_data = self._decode_content_body(
                data, self.get_header('Content-Encoding'))
        except http.client.IncompleteRead:
            body_data = b''
        except zlib.error:
            body_data = b''
        except _socket.timeout:
            body_data = b''
        self.set_body_data(body_data)
        self._text()  # 尝试将文本进行解码

        h.close()
        proxy_socket.close()
Beispiel #3
0
def check_appid_exists(appid):
    request_params, http_util, connection_cache_key = _get_request_params(
        appid)
    for _ in range(3):
        err = None
        response = None
        try:
            sock = http_util.create_ssl_connection(
                (request_params.host, request_params.port),
                request_params.hostname, connection_cache_key)
            sock.sendall(b'HEAD / HTTP/1.1\r\n'
                         b'Host: %s\r\n'
                         b'Connection: Close\r\n\r\n' % host.encode())
            response = HTTPResponse(sock, method='HEAD')
            response.begin()
        except:
            err = True
        finally:
            if response:
                response.close()
                if err is None:
                    exists = response.status in (200, 503)
                    if exists:
                        http_util.ssl_connection_cache[
                            connection_cache_key].append((time(), sock))
                    return exists
Beispiel #4
0
    def do_COMMAND(self):
        log.info(f"{self.command} {self.path}")
        try:
            # Connect to destination
            self._connect_to_host()
        except Exception as e:
            self.send_error(500, str(e))
            return

        # The request that got sent to the website: self
        # Browser <--> [Proxy <--> Website]
        content_length = int(self.headers.get("Content-Length", 0))
        request_body = self.rfile.read(content_length)

        # Build request which will be sent to the client
        # [Browser <--> Proxy] <--> Website
        client_request = (
            # Add "GET / HTTP/1.1..." to the request"
            b" ".join([
                to_bytes(self.command),
                to_bytes(self.path),
                to_bytes(self.request_version),
            ]) + CRLF
            # Add Headers to the request (Host:..., User-Agent:...)
            + self.headers.as_bytes() + CRLF + request_body)

        # Send it down the pipe!
        self.server.send(to_bytes(client_request))

        # Parse response
        h = HTTPResponse(self.server.conn)
        h.begin()

        # Get rid of hop-by-hop headers
        orig_response = h
        self.filter_headers(h.msg)

        # Time to relay the message across
        # read response body
        response_body = h.read()
        res = (
            # HTTP/1.1  OK
            b" ".join([
                to_bytes(self.request_version),
                to_bytes(h.status),
                to_bytes(h.reason),
            ])
            # Content-Type, Content-Length, Server...
            + CRLF + h.msg.as_bytes() + CRLF + response_body)

        # Let's close off the remote end
        h.close()
        self.server.close()

        # Relay the message
        self.client.send(res)

        self.print_info(self, request_body, orig_response, response_body)
    def read_response(self, sock):
        response = HTTPResponse(sock)

        response.begin()
        content = response.read()
        status_code = response.status
        reason = response.reason
        headers = dict(response.getheaders())
        response.close()

        return FakeResponse(status_code, reason, headers, content)
Beispiel #6
0
		def close(self):
			# Consume any remaining data in the socket
			try:
				while select((self.fp._sock,), (), (), 0)[0]:
					if not self.fp._sock.recv(256):
						break
			
			except AttributeError:
				pass
			
			HTTPResponse.close(self)
			
			try: self._handler.free_connection(self._connection)
			except AttributeError: pass
Beispiel #7
0
        def close(self):
            # Consume any remaining data in the socket
            try:
                while select((self.fp._sock, ), (), (), 0)[0]:
                    if not self.fp._sock.recv(256):
                        break

            except AttributeError:
                pass

            HTTPResponse.close(self)

            try:
                self._handler.free_connection(self._connection)
            except AttributeError:
                pass
Beispiel #8
0
    def do_COMMAND(self):

        # Is this an SSL tunnel?
        if not self.is_connect:
            try:
                # Connect to destination
                self._connect_to_host()
            except Exception as e:
                self.send_error(500, str(e))
                return
            # Extract path

        # Build request
        req = '%s %s %s\r\n' % (self.command, self.path, self.request_version)

        # Add headers to the request
        req += '%s\r\n' % self.headers

        # Append message body if present to the request
        if 'Content-Length' in self.headers:
            req += self.rfile.read(int(self.headers['Content-Length']))

        # Send it down the pipe!
        self._proxy_sock.sendall(self.mitm_request(req))

        # Parse response
        h = HTTPResponse(self._proxy_sock)
        h.begin()

        # Get rid of the pesky header
        del h.msg['Transfer-Encoding']

        # Time to relay the message across
        res = '%s %s %s\r\n' % (self.request_version, h.status, h.reason)
        res += '%s\r\n' % h.msg
        res += h.read()

        # Let's close off the remote end
        h.close()
        self._proxy_sock.close()

        # Relay the message
        self.request.sendall(self.mitm_response(res))
Beispiel #9
0
def check_appid_exists(appid):
    host = '%s.appspot.com' % appid
    for _ in range(3):
        err = None
        response = None
        try:
            sock = http_gws.create_ssl_connection((host, 443), 'google_gae', 'google_gae|:443')
            sock.sendall(b'HEAD / HTTP/1.1\r\n'
                         b'Host: %s\r\n'
                         b'Connection: Close\r\n\r\n' % host.encode())
            response = HTTPResponse(sock, method='HEAD')
            response.begin()
        except:
            err = True
        finally:
            if response:
                response.close()
                if err is None:
                    exists = response.status in (200, 503)
                    if exists:
                        http_gws.ssl_connection_cache['google_gae|:443'].append((time(), sock))
                    return exists
Beispiel #10
0
    def __init__(self, request,proxy_socket):

        HttpTransfer.__init__(self)

        self.request = request

        h = HTTPResponse(proxy_socket)
        h.begin()
        ##HTTPResponse会将所有chunk拼接到一起,因此会直接得到所有内容,所以不能有Transfer-Encoding
        del h.msg['Transfer-Encoding']
        del h.msg['Content-Length']

        self.response_version =self.version_dict[h.version]
        self.status = h.status
        self.reason = h.reason
        self.set_headers(h.msg)

        body_data = self._decode_content_body(h.read(),self.get_header('Content-Encoding'))
        self.set_body_data(body_data)
        self._text()#尝试将文本进行解码

        h.close()
        proxy_socket.close()
Beispiel #11
0
    def __init__(self, request, proxy_socket):

        HttpTransfer.__init__(self)

        self.request = request

        h = HTTPResponse(proxy_socket)
        h.begin()
        ##HTTPResponse会将所有chunk拼接到一起,因此会直接得到所有内容,所以不能有Transfer-Encoding
        del h.msg['Transfer-Encoding']
        del h.msg['Content-Length']

        self.response_version =self.version_dict[h.version]
        self.status = h.status
        self.reason = h.reason
        self.set_headers(h.msg)

        body_data = self._decode_content_body(h.read(), self.get_header('Content-Encoding'))
        self.set_body_data(body_data)
        self._text()#尝试将文本进行解码

        h.close()
        proxy_socket.close()
class HTTPResponseWrapper(object):
    """
        Class that adds some additional utilities to the build in HTTPResponse class. 
    """
    def __init__(self, oSock, sHttpVer):
        """
            :param oSock: Communication socket. 
            :param sHttpVer: Version of the http protocol we are using. 
        """
        self.oHTTPResponse = HTTPResponse(oSock)
        self.oHTTPResponse.begin()
        self.bBody = self.oHTTPResponse.read()
        self.bResponseLine = '{0} {1} {2}\r\n'.format(
            sHttpVer, self.oHTTPResponse.status,
            self.oHTTPResponse.reason).encode()
        self.bHeaders = self.oHTTPResponse.msg.as_bytes()
        self.sEncoding = self.oHTTPResponse.getheader('Content-Encoding')
        self.sContentType = self.oHTTPResponse.getheader('Content-Type')
        self.oHTTPResponse.close()

    def __bytes__(self):
        """
            :return: Raw bytes of the http response. 
        """
        return self.bResponseLine + self.bHeaders + self.bBody

    def getDecodedBody(self):
        """
            :return: Decoded content body of the http response.
        """
        # Only gzip encoding and html content types are supported at the moment.
        if self.sEncoding == CONTENT_ENCODINGS.GZIP and CONTENT_TYPES.HTML in self.sContentType:
            try:
                # Zlib lets us decompress the gzipped contents as stored bytes.
                return zlib.decompress(self.bBody, 16 + zlib.MAX_WBITS)
            except Exception as e:
                print("Error decompressing gzip contents {0}".format(str(e)))
Beispiel #13
0
    def do_POST(self):
        try:
            # Connect to destination
            self._connect_to_host()
        except Exception as e:
            self.send_error(500, str(e))
            return

        # The request that contains the request to the website is located
        # inside the POST request body from the stegoclient
        log.debug("Got stego-request from stegoclient")
        # io stream that represents the stego medium (i.e. image)
        req_body = io.BytesIO(
            self.rfile.read(int(self.headers.get("Content-Length", 0))))
        stego_message = stego.extract(medium=req_body)

        # Get Host and Port from the original request
        host, port = self._get_hostaddr_from_headers(stego_message)

        # establish connection to the website
        log.info(f"Connecting to {host}:{port}")
        self.server = Server(host=host, port=port)

        # Just relay the original request to the website
        log.debug("Relaying extracted request to website")
        self.server.send(stego_message)

        # Parse response from website
        h = HTTPResponse(self.server.conn)
        h.begin()

        # Get rid of hop-by-hop headers
        self.filter_headers(h.msg)

        # Build response from website
        log.debug("Building response from website")
        stego_resp = self._build_stego_response(self.request_version, h.status,
                                                h.reason, h.msg, h.read())

        # Build header to stegoclient
        header = Message()
        header.add_header("Host", f"{cfg.REMOTE_ADDR[0]}:{cfg.REMOTE_ADDR[1]}")
        header.add_header("Connection", "keep-alive")
        cover = self._get_cover_object()
        max_size = self._calc_max_size(cover)
        resp_len = len(stego_resp)

        if (max_size is not None and resp_len > max_size):
            log.debug(
                f"Can't fit response ({resp_len} bytes) into stego-response - "
                f"splitting into chunks of {max_size} bytes.")

            header.add_header("Transfer-Encoding", "chunked")
            resp_to_client = self._build_response_header(
                cfg.STEGO_HTTP_VERSION, h.status, h.reason, header)

            # Send headers to client
            log.debug("Sending chunked stego-response header to stegoclient")
            self.client.send(resp_to_client)

            start = time.time()
            chunk_count = 0
            for chunk in self._split_into_chunks(stego_resp, max_size):
                if isinstance(cover, Image.Image):
                    tmp_cover = cover.copy()
                else:
                    tmp_cover = cover

                # Send chunks
                log.debug(f"Sending chunk with size: {len(chunk)} bytes")
                self._write_chunks(stego.embed(cover=tmp_cover, message=chunk))
                chunk_count += 1

            end = time.time()
            # send "end of chunks" trailer
            self._write_end_of_chunks()
            log.debug(f"{chunk_count} chunks sent in {end - start:.2f}s.")
        else:
            # Encapsulate response inside response to stego client
            log.debug("Embedding response from website in stego-response")

            start = time.time()
            stego_medium = stego.embed(cover=cover, message=stego_resp)
            end = time.time()
            log.debug(
                f"Took {end - start:.2f}s to embed response in stego-response")

            header.add_header("Content-Length", str(len(stego_medium)))

            resp_to_client = self._build_response(cfg.STEGO_HTTP_VERSION,
                                                  h.status, h.reason, header,
                                                  stego_medium)

            # Relay the message
            log.debug("Relaying stego-response to stegoclient")
            self.client.send(resp_to_client)

        if isinstance(cover, Image.Image):
            cover.close()

        # Let's close off the remote end
        h.close()
        self.server.close()
Beispiel #14
0
    def _relay_response(self, debuglevel=0):
        resp = HTTPResponse(self.shadowsocks, method=self.command)

        resp.begin()

        # attempt to reuse the shadow socket
        self.close_connection = resp.will_close
        if self.close_connection:
            self.shadowsocks.close()
            self.shadowsocks = None

        if self.debuglevel > 0:  # pass
            print("[_relay_response] [%s] resp.will_close=%s" %
                  (self.requestline, resp.will_close))

        ver_str = self.protocol_version
        if resp.version == 10:
            ver_str = "HTTP/1.0"
        reply = "%s %s %s\r\n" % (ver_str, resp.code, resp.reason)
        if resp.headers:
            for hdr in resp.headers:
                val = resp.headers[hdr]
                reply += "%s: %s\r\n" % (hdr, val)
        reply += "%s: %s\r\n" % ("Z-Relayed-By", "Python Proxy Server 0.0.2")
        reply += "\r\n"
        reply = reply.encode("latin-1", "strict")

        # if debuglevel > 0: print("response header:", header)

        # self.request.send(header)

        # self.close_connection = True

        # Message body is omitted for cases described in:
        #  - RFC7230: 3.3. 1xx, 204(No Content), 304(Not Modified)
        #  - RFC7231: 6.3.6. 205(Reset Content)
        if (self.command == 'HEAD' or resp.code < HTTPStatus.OK or resp.code
                in (HTTPStatus.NO_CONTENT, HTTPStatus.RESET_CONTENT,
                    HTTPStatus.NOT_MODIFIED)):
            if resp.will_close:
                resp.close()
            if debuglevel > 0: print("reply:", reply)
            self.request.send(reply)
            return resp.code, reply

        resp_body = resp.read()
        if resp.chunked:
            resp_size = len(resp_body)
            reply += ("%x\r\n" % resp_size).encode("utf-8")
            reply += resp_body + b'\r\n'
            reply += b'0\r\n'
        elif len(resp_body) > 0:
            reply += resp_body

        reply += b'\r\n'
        self.request.send(reply)
        if debuglevel > 0: print("reply:", reply)

        if self.debuglevel > 0:
            print("[_relay_response]", resp.code, resp.reason,
                  self.requestline)

        if resp.will_close:
            resp.close()

        if resp.code == HTTPStatus.UNAUTHORIZED:
            self._blind_relay()

        return resp.code, reply