Пример #1
0
    def run(self):

        # Check certificate, the certificate will be used to warp https connections
	CertUtil.check_ca()

        # Start a stream server, wait for incoming http requests
	server = gevent.server.StreamServer((self.listen_ip, self.listen_port), self.paasproxy_handler)
	self.logger.info("proxy_client listen on: %s:%d" % (self.listen_ip, self.listen_port) )
	server.serve_forever()

	return
Пример #2
0
    def paasproxy_handler(self, sock, address):
	http = self.http_handler

	# Get user request url and parse it
	rfile = sock.makefile('rb', __bufsize__)
	try:
	    method, path, version, headers = http.parse_request(rfile)
	except (EOFError, socket.error) as e:
	    if e[0] in ('empty line', 10053, errno.EPIPE):
		return rfile.close()
	    raise

	# Change user-agent in header, if you need to fake browser 
	#headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36'
	remote_addr, remote_port = address

        # Socket and rfilt for CONNECT request
	__realsock = None
	__realrfile = None

	# For CONNECT request, establish the connection.
	if method == 'CONNECT':
	    host, _, port = path.rpartition(':')
	    port = int(port)

	    logging.info('%s:%s "CONNECT %s:%d HTTP/1.1" - -' % (address[0], address[1], host, port))

            # Get certificate from target host
	    keyfile, certfile = CertUtil.get_cert(host)

	    # Tell the user browser, the connection is established.
	    sock.sendall('HTTP/1.1 200 OK\r\n\r\n')

            # The response will be send by the socket that sent the CONNECT connect
	    __realsock = sock
	    __realrfile = rfile

	    try:
		# Wrap the connection with target host certificate
		sock = ssl.wrap_socket(__realsock, certfile=certfile, keyfile=keyfile, server_side=True)
	    except Exception as e:
		logging.exception('ssl.wrap_socket(__realsock=%r) failed: %s', __realsock, e)
	        __realrfile.close()
		__realsock.close()
		return

	    # Get user browser's next request
	    rfile = sock.makefile('rb', __bufsize__)
	    try:
		method, path, version, headers = http.parse_request(rfile)
	    except (EOFError, socket.error) as e:
		if e[0] in ('empty line', 10053, errno.EPIPE):
		    return rfile.close()
		raise

            # If the request uses CONNECT, it is a https request
            proto = "https"
        else:
            proto = "http"

	host = headers.get('Host', '')

        # If path is not complete, compose one.
	if path[0] == '/' and host:
	    path = proto + '://%s%s' % (host, path)

	try:
	    try:
	        # Wrap the user browser's request into a POST request, send the POST request to proxy_server
	        # Get the proxy_server's response, unwarp the content.
		content_length = int(headers.get('Content-Length', 0))
		payload = rfile.read(content_length) if content_length else ''
		response = self.paas_urlfetch(method, path, headers, payload, cfg.PROXY_SERVER)
		logging.info('%s:%s "%s %s HTTP/1.1" %s -', remote_addr, remote_port, method, path, response.status)

	    #except socket.error as e:
                # TODO: why ignore some exception? These exception will send the response back to user browser
		#if e.reason[0] not in (11004, 10051, 10060, 'timed out', 10054):
		    #raise

	    except Exception as e:
		logging.exception('socket error: %s', e)
		raise

            # Bad request, stop doing crlf injection
	    if response.app_status in (400, 405):
		http.crlf = 0

            # Send the result back to user browser
	    wfile = sock.makefile('wb', 0)

            # Format Set-Cookie field, TODO: why doing this?
	    if 'Set-Cookie' in response.msg:
		response.msg['Set-Cookie'] = re.sub(', ([^ =]+(?:=|$))', '\\r\\nSet-Cookie: \\1', response.msg['Set-Cookie'])

            # Write the response head to socket. Do not set transfer-encoding, TODO: why doing this?
	    wfile.write('HTTP/1.1 %s\r\n%s\r\n' % (response.status, ''.join('%s: %s\r\n' % (k.title(), v) for k, v in response.getheaders() if k != 'transfer-encoding')))

	    # Write the response payload to socket
	    while 1:
	        data = response.read(8192)
		if not data:
		    break
		wfile.write(data)

	    response.close()

	except socket.error as e:
	    # Connection closed before proxy return
	    if e[0] not in (10053, errno.EPIPE):
		raise

	finally:
	    rfile.close()
	    sock.close()
	    if __realrfile:
		__realrfile.close()
	    if __realsock:
		__realsock.close()

        return