# -*- coding: utf-8 -*- import socket import threading import time import inspect import sys # Configuration TARGET_HOST = "zentao.sunyard.com.cn" TARGET_PORT = 9788 B_HOST = "localhost" B_PORT = 8080 def log_info(source, message): """Log info message with line number""" line_number = inspect.currentframe().f_back.f_lineno print("[%s] [INFO] [%s] (line %d) %s" % ( time.strftime("%Y-%m-%d %H:%M:%S"), source, line_number, message )) def log_error(source, message): """Log error message with line number""" line_number = inspect.currentframe().f_back.f_lineno print("[%s] [ERROR] [%s] (line %d) %s" % ( time.strftime("%Y-%m-%d %H:%M:%S"), source, line_number, message )) def modify_request_headers(request_data): """Modify request headers: replace Origin, Referer, Host; remove Connection headers""" lines = request_data.split(b"\r\n") new_lines = [] method = "" path = "" if lines: first_line = lines[0].decode('utf-8', errors='ignore') parts = first_line.split() if len(parts) >= 2: method = parts[0] path = parts[1] for line in lines: line_str = line.decode('utf-8', errors='ignore') if line_str.startswith("Origin:"): new_lines.append("Origin: http://%s:%d" % (TARGET_HOST, TARGET_PORT)) elif line_str.startswith("Referer:"): new_lines.append("Referer: http://%s:%d/" % (TARGET_HOST, TARGET_PORT)) elif line_str.startswith("Host:"): new_lines.append("Host: %s:%d" % (TARGET_HOST, TARGET_PORT)) elif line_str.lower().startswith("connection:"): continue elif line_str.lower().startswith("keep-alive:"): continue elif line_str.lower().startswith("proxy-connection:"): continue elif line_str.lower().startswith("x-forwarded-for:"): continue else: new_lines.append(line_str) return "\r\n".join(new_lines).encode('utf-8'), method, path def handle_request(b_socket, request_data): """Handle a single request from device B""" modified_data, method, path = modify_request_headers(request_data) body_size = 0 if b"\r\n\r\n" in modified_data: body_size = len(modified_data) - modified_data.find(b"\r\n\r\n") - 4 log_info("System", "Request: %s %s - Body: %d bytes" % (method, path, body_size)) target_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) target_sock.settimeout(30) try: target_sock.connect((TARGET_HOST, TARGET_PORT)) log_info("System", "Connected to target: %s:%d" % (TARGET_HOST, TARGET_PORT)) target_sock.sendall(modified_data) response = b"" while True: chunk = target_sock.recv(8192) if not chunk: break response += chunk if b"\r\n\r\n" in response: headers_end = response.find(b"\r\n\r\n") headers = response[:headers_end].decode('utf-8', errors='ignore') content_length = 0 for line in headers.split("\r\n"): if line.lower().startswith("content-length:"): content_length = int(line.split(":")[1].strip()) break body_start = headers_end + 4 if len(response) - body_start >= content_length: break b_socket.sendall(response) status_code = "500" if b"\r\n\r\n" in response: headers_end = response.find(b"\r\n\r\n") headers = response[:headers_end].decode('utf-8', errors='ignore') for line in headers.split("\r\n"): if line.startswith("HTTP/"): status_code = line.split()[1] break log_info("System", "Response: %s %s - Status: %s" % (method, path, status_code)) return True except socket.error as e: if e.errno == 111 or e.errno == 10061: log_error("System", "Cannot connect to target: %s:%d" % (TARGET_HOST, TARGET_PORT)) error_msg = b"HTTP/1.1 502 Bad Gateway\r\nContent-Type: text/plain\r\n\r\nCannot connect to target: %s:%d\r\n" % (TARGET_HOST.encode(), TARGET_PORT) b_socket.sendall(error_msg) return False else: log_error("System", "Socket error: %s" % str(e)) error_msg = b"HTTP/1.1 502 Bad Gateway\r\nContent-Type: text/plain\r\n\r\nSocket error\r\n" b_socket.sendall(error_msg) return False except socket.timeout: log_error("System", "Target connection timeout") error_msg = b"HTTP/1.1 504 Gateway Timeout\r\nContent-Type: text/plain\r\n\r\nConnection timeout\r\n" b_socket.sendall(error_msg) return False except Exception as e: log_error("System", "Error handling request: %s" % str(e)) return False finally: target_sock.close() def listen_for_requests(sock): """Listen for requests from device B""" sock.settimeout(300) while True: try: data = b"" while True: chunk = sock.recv(8192) if not chunk: log_info("System", "Connection closed by device B") return data += chunk if b"\r\n\r\n" in data: headers_end = data.find(b"\r\n\r\n") headers = data[:headers_end].decode('utf-8', errors='ignore') content_length = 0 for line in headers.split("\r\n"): if line.lower().startswith("content-length:"): content_length = int(line.split(":")[1].strip()) break body_start = headers_end + 4 if len(data) - body_start >= content_length: break t = threading.Thread(target=handle_request, args=(sock, data)) t.daemon = True t.start() except socket.timeout: log_info("System", "Connection idle timeout") return except Exception as e: log_error("System", "Connection error: %s" % str(e)) return def connect_to_b_device(b_host, b_port): """Connect to device B and handle requests""" while True: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(10) sock.connect((b_host, b_port)) response = sock.recv(1024) if not response or b"PROXY_CONNECTED" not in response: log_error("System", "Failed to receive connection confirmation") sock.close() time.sleep(3) continue sock.send(b"READY\r\n") log_info("System", "Successfully connected to device B: %s:%d" % (b_host, b_port)) listen_for_requests(sock) except socket.error as e: if e.errno == 111 or e.errno == 10061: log_info("System", "Device B not ready (%s:%d), retrying in 3 seconds..." % (b_host, b_port)) else: log_error("System", "Connection error: %s" % str(e)) time.sleep(3) except Exception as e: log_error("System", "Unexpected error: %s" % str(e)) time.sleep(3) def main(): print("=" * 60) print(" Proxy Client (Run on Computer A)") print("=" * 60) print("Target website:", TARGET_HOST, ":", TARGET_PORT) print("Device B address:", B_HOST, ":", B_PORT) print("=" * 60) try: connect_to_b_device(B_HOST, B_PORT) except KeyboardInterrupt: print("\nShutting down...") sys.exit(0) if __name__ == "__main__": main()