2121from OpenSSL import crypto
2222
2323from utils .filter import filter_process
24+ from utils .shortcuts import shortcuts_process
2425from utils .logger import configure_file_logger , configure_console_logger
2526
2627class ProxyServer :
@@ -33,7 +34,7 @@ class ProxyServer:
3334 # pylint: disable=too-many-locals
3435 def __init__ (self , host , port , debug , access_log , block_log ,
3536 html_403 , no_filter , filter_mode , no_logging_access , no_logging_block , ssl_inspect ,
36- blocked_sites , blocked_url , inspect_ca_cert , inspect_ca_key , inspect_certs_folder ):
37+ blocked_sites , blocked_url , shortcuts , inspect_ca_cert , inspect_ca_key , inspect_certs_folder ):
3738 """
3839 Initializes the ProxyServer instance with the provided configurations.
3940 """
@@ -46,11 +47,15 @@ def __init__(self, host, port, debug, access_log, block_log,
4647 self .no_logging_block = no_logging_block
4748 self .ssl_inspect = ssl_inspect
4849 self .filter_proc = None
49- self .queue = multiprocessing .Queue ()
50- self .result_queue = multiprocessing .Queue ()
50+ self .filter_queue = multiprocessing .Queue ()
51+ self .filter_result_queue = multiprocessing .Queue ()
52+ self .shortcuts_proc = None
53+ self .shortcuts_queue = multiprocessing .Queue ()
54+ self .shortcuts_result_queue = multiprocessing .Queue ()
5155 self .console_logger = configure_console_logger ()
5256 self .config_blocked_sites = blocked_sites
5357 self .config_blocked_url = blocked_url
58+ self .config_shortcuts = shortcuts
5459 self .config_inspect_cert = inspect_ca_cert
5560 self .config_inspect_key = inspect_ca_key
5661 self .config_inspect_certs_folder = inspect_certs_folder
@@ -79,6 +84,7 @@ def start(self):
7984 self .console_logger .debug ("[*] ssl_inspect = %s" , self .ssl_inspect )
8085 self .console_logger .debug ("[*] blocked_sites = %s" , self .config_blocked_sites )
8186 self .console_logger .debug ("[*] blocked_url = %s" , self .config_blocked_url )
87+ self .console_logger .debug ("[*] shortcuts = %s" , self .config_shortcuts )
8288 self .console_logger .debug ("[*] inspect_ca_cert = %s" , self .config_inspect_cert )
8389 self .console_logger .debug ("[*] inspect_ca_key = %s" , self .config_inspect_key )
8490 self .console_logger .debug (
@@ -116,14 +122,27 @@ def start(self):
116122 self .filter_proc = multiprocessing .Process (
117123 target = filter_process ,
118124 args = (
119- self .queue ,
120- self .result_queue ,
125+ self .filter_queue ,
126+ self .filter_result_queue ,
121127 self .filter_mode ,
122128 self .config_blocked_sites ,
123129 self .config_blocked_url
124130 )
125131 )
126132 self .filter_proc .start ()
133+ self .console_logger .debug ("[*] Starting the filter process..." )
134+
135+ if self .config_shortcuts and os .path .isfile (self .config_shortcuts ):
136+ self .shortcuts_proc = multiprocessing .Process (
137+ target = shortcuts_process ,
138+ args = (
139+ self .shortcuts_queue ,
140+ self .shortcuts_result_queue ,
141+ self .config_shortcuts
142+ )
143+ )
144+ self .shortcuts_proc .start ()
145+ self .console_logger .debug ("[*] Starting the shortcuts process..." )
127146
128147 server = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
129148 server .bind (self .host_port )
@@ -176,9 +195,28 @@ def handle_http_request(self, client_socket, request):
176195 first_line = request .decode (errors = 'ignore' ).split ("\n " )[0 ]
177196 url = first_line .split (" " )[1 ]
178197
198+ if self .config_shortcuts :
199+ domain , _ = self .parse_url (url )
200+ print (url )
201+ print (domain )
202+ self .shortcuts_queue .put (domain )
203+ shortcut_url = self .shortcuts_result_queue .get ()
204+ print (shortcut_url )
205+ if shortcut_url :
206+ response = (
207+ "HTTP/1.1 302 Found\r \n "
208+ "Location: {shortcut_url}\r \n "
209+ "Content-Length: 0\r \n "
210+ "\r \n "
211+ ).format (shortcut_url = shortcut_url )
212+
213+ client_socket .sendall (response .encode ())
214+ client_socket .close ()
215+ return
216+
179217 if not self .no_filter :
180- self .queue .put (url )
181- result = self .result_queue .get ()
218+ self .filter_queue .put (url )
219+ result = self .filter_result_queue .get ()
182220 if result [1 ] == "Blocked" :
183221 if not self .no_logging_block :
184222 self .block_logger .info (
@@ -218,16 +256,28 @@ def forward_request_to_server(self, client_socket, request, url):
218256 url (str): The target URL from the HTTP request.
219257 """
220258 server_host , server_port = self .parse_url (url )
221- server_socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
222- server_socket .connect ((server_host , server_port ))
223- server_socket .sendall (request )
224259
225- while True :
226- response = server_socket .recv (4096 )
227- if len (response ) > 0 :
228- client_socket .send (response )
229- else :
230- break
260+ try :
261+ server_socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
262+ server_socket .connect ((server_host , server_port ))
263+ server_socket .sendall (request )
264+
265+ while True :
266+ response = server_socket .recv (4096 )
267+ if len (response ) > 0 :
268+ client_socket .send (response )
269+ else :
270+ break
271+ except Exception as e :
272+ self .console_logger .error (f"Error connecting to the server { server_host } : { e } " )
273+ response = (
274+ f"HTTP/1.1 502 Bad Gateway\r \n "
275+ f"Content-Length: { len ('Bad Gateway' )} \r \n "
276+ f"\r \n "
277+ f"Bad Gateway"
278+ )
279+ client_socket .sendall (response .encode ())
280+ client_socket .close ()
231281
232282 def parse_url (self , url ):
233283 """
@@ -270,8 +320,8 @@ def handle_https_connection(self, client_socket, first_line):
270320 server_port = int (server_port )
271321
272322 if not self .no_filter :
273- self .queue .put (target )
274- result = self .result_queue .get ()
323+ self .filter_queue .put (target )
324+ result = self .filter_result_queue .get ()
275325 if result [1 ] == "Blocked" :
276326 if not self .no_logging_block :
277327 self .block_logger .info (
@@ -330,8 +380,8 @@ def handle_https_connection(self, client_socket, first_line):
330380 full_url = f"https://{ server_host } { path } "
331381
332382 if not self .no_filter :
333- self .queue .put (f"{ server_host } { path } " )
334- result = self .result_queue .get ()
383+ self .filter_queue .put (f"{ server_host } { path } " )
384+ result = self .filter_result_queue .get ()
335385 if result [1 ] == "Blocked" :
336386 if not self .no_logging_block :
337387 self .block_logger .info (
@@ -381,17 +431,28 @@ def handle_https_connection(self, client_socket, first_line):
381431 client_socket .close ()
382432
383433 else :
384- server_socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
385- server_socket .connect ((server_host , server_port ))
386- client_socket .sendall (b"HTTP/1.1 200 Connection Established\r \n \r \n " )
387- if not self .no_logging_access :
388- self .access_logger .info (
389- "%s - %s - %s" ,
390- client_socket .getpeername ()[0 ],
391- f"https://{ server_host } " ,
392- first_line
434+ try :
435+ server_socket = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
436+ server_socket .connect ((server_host , server_port ))
437+ client_socket .sendall (b"HTTP/1.1 200 Connection Established\r \n \r \n " )
438+ if not self .no_logging_access :
439+ self .access_logger .info (
440+ "%s - %s - %s" ,
441+ client_socket .getpeername ()[0 ],
442+ f"https://{ server_host } " ,
443+ first_line
444+ )
445+ self .transfer_data_between_sockets (client_socket , server_socket )
446+ except Exception as e :
447+ self .console_logger .error (f"Error connecting to the server { server_host } : { e } " )
448+ response = (
449+ f"HTTP/1.1 502 Bad Gateway\r \n "
450+ f"Content-Length: { len ('Bad Gateway' )} \r \n "
451+ f"\r \n "
452+ f"Bad Gateway"
393453 )
394- self .transfer_data_between_sockets (client_socket , server_socket )
454+ client_socket .sendall (response .encode ())
455+ client_socket .close ()
395456
396457 def transfer_data_between_sockets (self , client_socket , server_socket ):
397458 """
0 commit comments