|
|
import os |
|
|
import sys |
|
|
import threading |
|
|
import time |
|
|
from stem.process import launch_tor_with_config |
|
|
from websockify import WebSocketProxy |
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
from websockify.websocketproxy import ProxyRequestHandler |
|
|
except ImportError: |
|
|
|
|
|
|
|
|
ProxyRequestHandler = None |
|
|
|
|
|
|
|
|
TOR_SOCKS_PORT = 9050 |
|
|
WEBSOCKET_PORT = 7860 |
|
|
WEBSOCKET_LISTEN_HOST = '0.0.0.0' |
|
|
TOR_DATA_DIR = os.path.join(os.getcwd(), "tor_data") |
|
|
|
|
|
def print_status(msg): |
|
|
print(f"[*] {msg}") |
|
|
|
|
|
def start_tor(): |
|
|
""" |
|
|
Starts the Tor process. |
|
|
""" |
|
|
print_status("Starting Tor process...") |
|
|
if not os.path.exists(TOR_DATA_DIR): |
|
|
os.makedirs(TOR_DATA_DIR) |
|
|
|
|
|
try: |
|
|
config = { |
|
|
'SocksPort': str(TOR_SOCKS_PORT), |
|
|
'DataDirectory': TOR_DATA_DIR, |
|
|
} |
|
|
tor_process = launch_tor_with_config( |
|
|
config=config, |
|
|
init_msg_handler=lambda line: print(f" [Tor] {line}") if "Bootstrapped" in line else None, |
|
|
take_ownership=True, |
|
|
) |
|
|
print_status(f"Tor is running! SOCKS proxy at 127.0.0.1:{TOR_SOCKS_PORT}") |
|
|
return tor_process |
|
|
except Exception as e: |
|
|
print_status(f"Error starting Tor: {e}") |
|
|
sys.exit(1) |
|
|
|
|
|
def create_custom_handler(base_handler_class): |
|
|
""" |
|
|
Creates a custom handler class inheriting from the provided base. |
|
|
This allows us to serve "Hello World" on HTTP GET while keeping |
|
|
WebSocket functionality for the proxy. |
|
|
""" |
|
|
class HelloHandler(base_handler_class): |
|
|
def do_GET(self): |
|
|
|
|
|
if self.headers.get('Upgrade') and self.headers.get('Upgrade').lower() == 'websocket': |
|
|
|
|
|
super().do_GET() |
|
|
else: |
|
|
|
|
|
self.send_response(200) |
|
|
self.send_header("Content-type", "text/plain") |
|
|
self.end_headers() |
|
|
self.wfile.write(b"Hello World") |
|
|
|
|
|
return HelloHandler |
|
|
|
|
|
def start_websockify(): |
|
|
""" |
|
|
Starts the Websockify proxy with a Custom Handler. |
|
|
""" |
|
|
print_status(f"Starting Websockify on {WEBSOCKET_LISTEN_HOST}:{WEBSOCKET_PORT}...") |
|
|
|
|
|
|
|
|
proxy = WebSocketProxy( |
|
|
listen_host=WEBSOCKET_LISTEN_HOST, |
|
|
listen_port=WEBSOCKET_PORT, |
|
|
target_host='127.0.0.1', |
|
|
target_port=TOR_SOCKS_PORT |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
default_handler = proxy.RequestHandlerClass |
|
|
|
|
|
|
|
|
custom_handler = create_custom_handler(default_handler) |
|
|
|
|
|
|
|
|
proxy.RequestHandlerClass = custom_handler |
|
|
|
|
|
|
|
|
try: |
|
|
proxy.start_server() |
|
|
except OSError as e: |
|
|
print_status(f"Error starting Websockify: {e}") |
|
|
os._exit(1) |
|
|
|
|
|
def main(): |
|
|
tor_process = start_tor() |
|
|
|
|
|
ws_thread = threading.Thread(target=start_websockify) |
|
|
ws_thread.daemon = True |
|
|
ws_thread.start() |
|
|
|
|
|
print_status("Setup complete.") |
|
|
print_status(f"1. Proxy (WS): ws://<IP>:{WEBSOCKET_PORT}/") |
|
|
print_status(f"2. Check (HTTP): http://<IP>:{WEBSOCKET_PORT}/ -> Should say 'Hello World'") |
|
|
print_status("Press Ctrl+C to stop.") |
|
|
|
|
|
try: |
|
|
while True: |
|
|
time.sleep(1) |
|
|
except KeyboardInterrupt: |
|
|
print_status("Stopping...") |
|
|
tor_process.terminate() |
|
|
sys.exit(0) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |