From 83606d3a97d544fe17d5529e651d672969a98314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Henrique?= Date: Thu, 16 Nov 2023 21:28:37 -0300 Subject: [PATCH] add trabalho5 --- trabalho5/proxy.py | 165 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 trabalho5/proxy.py diff --git a/trabalho5/proxy.py b/trabalho5/proxy.py new file mode 100644 index 0000000..540a314 --- /dev/null +++ b/trabalho5/proxy.py @@ -0,0 +1,165 @@ +import socket +import select +from threading import Thread +import time +import logging +import logging.handlers + +LOGGER_HOST = "localhost" +LOGGER_PORT = 514 + +CURRENT_THREADS = 0 +MAX_THREADS = 10 +BACKLOG = 50 + +class Logger: + _instance = None + def __init__(self): + self.logger = logging.getLogger('PythonProxy') + self.logger.setLevel(logging.DEBUG) + + handler = logging.handlers.SysLogHandler(address = (LOGGER_HOST, LOGGER_PORT)) + + self.logger.addHandler(handler) + + self.logger.debug('Initiating Proxy logger!') + + def log(self, message:str): + self.logger.debug(message) + print('INFO:', message) + + def critical(self, message:str): + self.logger.critical(message) + print('CRITICAL:', message) + + def __del__(self): + self.logger.close() + + @classmethod + def instance(self): + if self._instance is None: + self._instance = self() + return self._instance + + +class Server: + def __init__(self, host:str, port:int): + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.bind((host, port)) + self.sock.listen(BACKLOG) + print(f"Listening at: http://{host}:{port}") + + def thread_check(self): + global CURRENT_THREADS, MAX_THREADS + while True: + if CURRENT_THREADS >= MAX_THREADS: + time.sleep(1) + else: + return + + def start(self): + global CURRENT_THREADS + while True: + conn, client_addr = self.sock.accept() + self.thread_check() + + CURRENT_THREADS += 1 + thread = Thread(target = connectionHandle, args = (conn, client_addr, )) + CURRENT_THREADS -= 1 + thread.start() + + def __del__(self): + self.sock.close() + +def connectionHandle(client_socket, client_address): + # print(f"Connection received from {client_address[0]}:{client_address[1]}") + + request = client_socket.recv(16 * 1024) + logger = Logger.instance() + + if len(request) == 0: + client_socket.close() + return + + try: + raw_request = request.decode() + except UnicodeDecodeError: + print("UnicodeDecodeError") + client_socket.close() + return + + if "CONNECT" in raw_request: + client_socket.sendall(b"HTTP/1.1 200 Connection Established\r\n\r\n") + request = client_socket.recv(16 * 1024) + + request_url = raw_request.split(' ')[1] + request_host = "" + request_port = 443 if 'https' in request_url else 80 + + if request_url.startswith('http'): + request_host = request_url.split('/')[2] + else: + request_host = request_url.split('/')[0] + + if request_host.startswith('www'): + request_host = request_host[4:] + + if ':' in request_host: + request_port = int(request_host.split(':')[1]) + request_host = request_host.split(':')[0] + + # print(f"REQUEST [{client_address[0]}:{client_address[1]}] {raw_request}") + + if "monitorando" in request_url: + body = "403 Acesso não autorizado! " + client_socket.sendall(b"HTTP/1.1 403 Forbidden\r\n\r\n") + client_socket.sendall(body.encode()) + client_socket.close() + return + + # forward the request to the destination server + # print(f"Forwarding request to {request_host}:{request_port}") + destination_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + destination_socket.connect((request_host, request_port)) + destination_socket.sendall(request) + + # print(f"Waiting for response from {request_host}:{request_port}") + + while True: + triple = select.select([client_socket, destination_socket], [], [], 20)[0] + if not len(triple): + break + try: + if client_socket in triple: + data = client_socket.recv(16 * 1024) + if not data: + break + destination_socket.send(data) + if destination_socket in triple: + data = destination_socket.recv(16 * 1024) + if not data: + break + + try: + status_code = data.decode().split(' ')[1:] + status_code = ' '.join(status_code) + logger.log(f"REQUEST [{client_address[0]}:{client_address[1]}] to [{request_host}:{request_port}] - {status_code} ({len(data)} bytes)") + except UnicodeDecodeError: + pass + + client_socket.send(data) + except ConnectionAbortedError: + break + + # print(f"Closing connection with {request_host}:{request_port} and {client_address[0]}:{client_address[1]}") + + # close the sockets + destination_socket.close() + client_socket.close() + + # print("Connection closed") + + +if __name__ == '__main__': + ser = Server(host="0.0.0.0", port=8080) + ser.start()