Quantcast
Viewing all articles
Browse latest Browse all 1535

Python Proxy Server with TLS Failing: SSLContext Error with PROTOCOL_TLS_SERVER

I have written a Python-based proxy server that supports both HTTP and HTTPS. The goal is to redirect or block specific domains, for example, redirecting certain malicious websites to a secure page (like Google). I want to deploy the proxy in a secure environment using TLS.

Current Behavior

Error Message:

SSL error occurred: Cannot create a client socket with a PROTOCOL_TLS_SERVER context (_ssl.c:806). Closing connection gracefully.   If the SSL handshake fails, please make sure the self-signed certificate is properly installed in the client as a trusted authority.

The proxy correctly forwards HTTP connections and works without encryption.However, when connecting over HTTPS (port 443), the SSL handshake fails, resulting in this error.Minimal Reproducible Example

Here is my Python code:

import http.serverimport socketserverimport requestsimport socketimport selectimport sslimport urllib3from urllib.parse import urlparse, quote# Suppress InsecureRequestWarning warningsurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)# List of blocked domainsBLOCKED_DOMAINS = ["example.com","blocked.com","malicious-site.com"]# Certificate files for SSL connectionsCERT_FILE = "cert.pem"KEY_FILE = "key.pem"class ProxyHandler(http.server.BaseHTTPRequestHandler):    def do_CONNECT(self):        target_host, target_port = self.path.split(":")        target_port = int(target_port)        # Check if the domain should be blocked        if any(blocked_domain in target_host for blocked_domain in BLOCKED_DOMAINS):            print(f"CONNECT request to blocked domain: {target_host}. Redirecting to Google.")            target_host = "www.google.com"            target_port = 443        try:            # Establish connection to the target            context = None            if target_port == 443:                # SSL context for secure connection with custom certificate                context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)                context.minimum_version = ssl.TLSVersion.TLSv1_2                context.maximum_version = ssl.TLSVersion.TLSv1_3                context.check_hostname = False  # Disable to avoid hostname verification                context.verify_mode = ssl.CERT_NONE  # Disabled for local testing                context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)                # Specify secure cipher suites                context.set_ciphers('ECDHE+AESGCM:ECDHE+CHACHA20:ECDHE+SHA256:!aNULL:!MD5:!3DES')                      raw_sock = socket.create_connection((target_host, target_port))            if context:                # `server_hostname` must be set for `check_hostname` to work                conn = context.wrap_socket(raw_sock, server_hostname=target_host)            else:                conn = raw_sock            # Connection established successfully, send response to client            self.send_response(200, "Connection established")            self.end_headers()            # Data transfer between client and target server            client_socket = self.connection            sockets = [client_socket, conn]            while True:                readable, _, _ = select.select(sockets, [], sockets, 10)                if not readable:                    break                for sock in readable:                    other = conn if sock is client_socket else client_socket                    data = sock.recv(4096)                    if not data:                        break                    other.sendall(data)        except ssl.SSLError as ssl_error:            print(f"SSL error occurred: {ssl_error}. Closing connection gracefully. If the SSL handshake fails, please make sure the self-signed certificate is properly installed in the client as a trusted authority.")        except (ConnectionAbortedError, socket.error) as e:            print(f"Connection error during data transfer: {e}")        except Exception as e:            print(f"Failed to establish connection: {e}")            if not self.wfile.closed:                try:                    self.send_error(502, "Failed to establish connection")                except BrokenPipeError:                    print("Broken pipe when attempting to send error response.")        finally:            try:                if 'conn' in locals() and conn:                    conn.close()            except Exception as e:                print(f"Error while closing connection: {e}")if __name__ == "__main__":    port = 8080    with socketserver.ThreadingTCPServer(('', port), ProxyHandler) as httpd:        httpd.allow_reuse_address = True        print(f"Proxy server running on port {port} with HTTPS support")        httpd.serve_forever()

Possible Questions

Am I using the wrong SSL context (ssl.PROTOCOL_TLS_SERVER) in the context of a proxy? Should I use a different context instead?Could the issue be due to using a self-signed certificate? If so, how can I ensure the client accepts the certificate as trustworthy?Are additional configuration steps in the SSL context necessary to achieve a successful SSL handshake?Does the SSL context need to be configured differently because the proxy acts both on the server and client sides?

I've been trying to solve this problem all day, but I'm stuck. This project is very important to me because I want to create something that protects both children and adults from pornography. If anyone is willing to help, I would be really grateful! I'm determined to find a solution and appreciate any support.


Viewing all articles
Browse latest Browse all 1535

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>