import asyncio import json import socket import dns.resolver # To handle DNS resolution using custom DNS server from fastapi import FastAPI, WebSocket, WebSocketDisconnect from fastapi.responses import HTMLResponse import uvicorn app = FastAPI() # Function to resolve DNS with a custom DNS server (4.2.2.4) def resolve_with_custom_dns(domain: str, dns_server: str = "4.2.2.4"): try: resolver = dns.resolver.Resolver() resolver.nameservers = [dns_server] # Set the custom DNS server answers = resolver.resolve(domain) for answer in answers: print(f"Resolved {domain} to {answer.to_text()}") return [answer.to_text() for answer in answers] except Exception as e: print(f"[!] Error resolving {domain}: {e}") return None @app.get("/") async def root(): html_content = """ WebSocket Proxy Server

Proxy Server Node

This server is running and ready to accept WebSocket tunnel connections.

System Online
""" return HTMLResponse(content=html_content, status_code=200) @app.websocket("/ws") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() try: # 1. Receive the target destination from the proxy init_data = await websocket.receive_text() target = json.loads(init_data) host = target.get("host") port = target.get("port") # 2. Resolve DNS using custom DNS server (4.2.2.4) #print(f"[*] Resolving DNS for {host} using 4.2.2.4") resolved_ips = resolve_with_custom_dns(host, dns_server="4.2.2.4") if resolved_ips is None: await websocket.send_text(json.dumps({"status": "error", "message": "DNS resolution failed"})) await websocket.close() return # Pick the first resolved IP address ip = resolved_ips[0] #print(f"[*] Resolved {host} to {ip}") # 3. Open TCP connection to the resolved IP #print(f"[*] Connecting to remote {ip}:{port}") remote_reader, remote_writer = await asyncio.open_connection(ip, port) await websocket.send_text(json.dumps({"status": "success"})) # 4. Forwarding Loops async def ws_to_tcp(): try: while True: data = await websocket.receive_bytes() remote_writer.write(data) await remote_writer.drain() except Exception: pass finally: remote_writer.close() async def tcp_to_ws(): try: while True: data = await remote_reader.read(4096) if not data: break await websocket.send_bytes(data) except Exception: pass finally: await websocket.close() await asyncio.gather(ws_to_tcp(), tcp_to_ws()) except Exception as e: print(f"[!] Server Error: {e}") try: await websocket.send_text(json.dumps({"status": "error", "message": str(e)})) await websocket.close() except: pass if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=7860)