Przeglądaj źródła

Proxy VPN + SSL/TLS Integrado

Antes de ejecutar:
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /root/key.pem -out /root/cert.pem -subj "/C=US/ST=NY/L=New York/O=Cloudflare/CN=www.cloudflare.com"
yosoyhendrix 3 dni temu
rodzic
commit
91d7437e18
1 zmienionych plików z 233 dodań i 0 usunięć
  1. 233 0
      VPN.py

+ 233 - 0
VPN.py

@@ -0,0 +1,233 @@
+# -*- coding: utf-8 -*-
+
+import socket
+import threading
+import select
+import sys
+import time
+import itertools
+import os
+import ssl  # 🛡️ NUEVO: Motor criptográfico nativo
+
+# --- CONFIGURACIÓN BASE ---
+LISTENING_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 443 # Cambiado al 443 (Puerto Oficial HTTPS)
+SSH_HOST = '127.0.0.1'
+SSH_PORT = 22
+LOG_FILE = "/root/proxy.log"
+MAX_LOG_SIZE = 10 * 1024 * 1024
+
+# --- CONFIGURACIÓN SSL/TLS (STUNNEL EMBEBIDO) ---
+USE_SSL = True  # Cambia a False si quieres volver al modo texto plano
+CERT_FILE = "/root/cert.pem"
+KEY_FILE = "/root/key.pem"
+
+# --- CONFIGURACIÓN DE SEGURIDAD AVANZADA ---
+MAX_CONNECTIONS = 100
+CONNECTION_COOLDOWN = 0.7
+TIMEOUT = 60
+BUFLEN = 16384
+
+# --- FILTRADO DE ACCESO Y AUTO-BANEO ---
+ALLOWED_IPS = [] 
+BLOCKED_HOSTS = ['ads.doubleclick.net', 'telemetry.microsoft.com']
+AUTO_BAN_STRIKES = 3  
+BAN_TIME = 3600       
+banned_ips_memory = {} 
+ip_strikes = {}
+
+# --- CUSTOM HEADERS ---
+CUSTOM_HEADERS = {
+    "Server": "nginx/1.21.0",
+    "X-Forwarded-For": "127.0.0.1",
+    "Content-Type": "text/html; charset=UTF-8",
+    "Proxy-Connection": "keep-alive",
+    "Cache-Control": "no-cache",
+    "X-Proxy-Agent": "Gemini-Ultra-Robust-v4-TLS",
+    "X-Forwarded-For-Proxy": "True"
+}
+
+# --- MENSAJES ROTATIVOS ---
+MENSAJES = [
+    "🚀 CONEXION TLS ESTABLECIDA",
+    "🛡️ CIFRADO MILITAR ACTIVO",
+    "🔋 MODO SIGILO SSL OK",
+    "🌐 BYPASS DE FIREWALL OK"
+]
+mensaje_cycle = itertools.cycle(MENSAJES)
+cycle_lock = threading.Lock()
+
+def log(msg, addr=None):
+    try:
+        if os.path.exists(LOG_FILE) and os.path.getsize(LOG_FILE) > MAX_LOG_SIZE:
+            with open(LOG_FILE, 'w') as f:
+                f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] LOG REINICIADO\n")
+        timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
+        client_info = f" [{addr[0]}]" if addr else ""
+        log_entry = f"[{timestamp}]{client_info} {msg}\n"
+        with open(LOG_FILE, 'a') as f: f.write(log_entry)
+        print(log_entry.strip())
+    except: pass
+
+active_connections = 0
+conn_lock = threading.Lock()
+ip_cooldowns = {}
+
+class ConnectionHandler(threading.Thread):
+    def __init__(self, client_socket, addr):
+        super().__init__(daemon=True)
+        self.client = client_socket
+        self.addr = addr
+        self.target = None
+        self.tx_bytes = 0
+        self.rx_bytes = 0
+
+    def build_http_response(self, status_msg):
+        headers_str = "".join([f"{k}: {v}\r\n" for k, v in CUSTOM_HEADERS.items()])
+        response = (
+            f"HTTP/1.1 101 {status_msg}\r\n"
+            f"{headers_str}"
+            f"Connection: Upgrade\r\n"
+            f"Upgrade: websocket\r\n\r\n"
+        )
+        return response.encode('utf-8')
+
+    def run(self):
+        global active_connections
+        client_ip = self.addr[0]
+        
+        try:
+            if client_ip in banned_ips_memory:
+                if time.time() > banned_ips_memory[client_ip]:
+                    del banned_ips_memory[client_ip]
+                    if client_ip in ip_strikes: del ip_strikes[client_ip]
+                    log(f"🔓 Baneo expirado. Acceso restaurado.", self.addr)
+                else: return
+                
+            if ALLOWED_IPS and client_ip not in ALLOWED_IPS: return
+
+            now = time.time()
+            if client_ip in ip_cooldowns and (now - ip_cooldowns[client_ip]) < CONNECTION_COOLDOWN:
+                ip_strikes[client_ip] = ip_strikes.get(client_ip, 0) + 1
+                if ip_strikes[client_ip] >= AUTO_BAN_STRIKES:
+                    banned_ips_memory[client_ip] = time.time() + BAN_TIME
+                    log(f"⛔ IP Baneada (Flood/Spam)", self.addr)
+                return
+                
+            ip_cooldowns[client_ip] = now
+            ip_strikes[client_ip] = 0
+
+            self.client.settimeout(5)
+            try:
+                payload = self.client.recv(BUFLEN)
+                if not payload: return
+            except: return
+
+            log(f"Intentando conectar a {SSH_HOST}:{SSH_PORT}...", self.addr)
+            self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=10)
+            
+            with cycle_lock: current_status = next(mensaje_cycle)
+            
+            self.client.sendall(self.build_http_response(current_status))
+            log(f"✅ Túnel cifrado activo: {current_status}", self.addr)
+
+            self.tunnel()
+
+        except Exception as e: log(f"❌ Error: {e}", self.addr)
+        finally:
+            with conn_lock: active_connections -= 1
+            self.cleanup()
+
+    def tunnel(self):
+        self.client.settimeout(None)
+        self.target.settimeout(None)
+        sockets = [self.client, self.target]
+        while True:
+            readable, _, error = select.select(sockets, [], sockets, 300)
+            if error or not readable: break
+            for s in readable:
+                try:
+                    data = s.recv(BUFLEN)
+                    if not data: return
+                    if s is self.client:
+                        self.target.sendall(data)
+                        self.tx_bytes += len(data)
+                    else:
+                        self.client.sendall(data)
+                        self.rx_bytes += len(data)
+                except: return
+
+    def cleanup(self):
+        total_mb = (self.tx_bytes + self.rx_bytes) / (1024 * 1024)
+        if total_mb > 0.01: log(f"[*] Conexión finalizada. Tráfico consumido: {total_mb:.2f} MB", self.addr)
+        for s in [self.client, self.target]:
+            if s:
+                try: s.close()
+                except: pass
+
+def main():
+    global active_connections
+    
+    # 🛡️ PREPARAR EL MOTOR SSL/TLS
+    ssl_context = None
+    if USE_SSL:
+        try:
+            ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
+            ssl_context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
+            log(f"🔒 Motor SSL/TLS Inicializado correctamente.")
+        except Exception as e:
+            log(f"❌ Error crítico cargando certificados SSL: {e}")
+            sys.exit(1)
+
+    try:
+        addr_info = socket.getaddrinfo(None, LISTENING_PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
+        addr_info.sort(key=lambda x: x[0] == socket.AF_INET6, reverse=True)
+        af, socktype, proto, canonname, sa = addr_info[0]
+        
+        server = socket.socket(af, socktype, proto)
+        server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        if af == socket.AF_INET6:
+            try: server.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
+            except: pass
+
+        server.bind(sa)
+        server.listen(200)
+        
+        log(f"=====================================================")
+        estado_ssl = "ACTIVADO (Invisible a DPI)" if USE_SSL else "DESACTIVADO (Texto Plano)"
+        log(f"🔥 Servidor Robusto Iniciado en Puerto {LISTENING_PORT}")
+        log(f"🛡️ Modo Sigilo SSL/TLS: {estado_ssl}")
+        log(f"🎯 Destino Interno: {SSH_HOST}:{SSH_PORT}")
+        log(f"=====================================================")
+
+        while True:
+            client, addr = server.accept()
+            
+            # 🛡️ ENVOLVER LA CONEXIÓN EN TLS AL INSTANTE
+            if USE_SSL:
+                try:
+                    # server_side=True le dice al script que actúe como un servidor HTTPS
+                    client = ssl_context.wrap_socket(client, server_side=True)
+                except ssl.SSLError as e:
+                    # Si alguien intenta conectarse sin encriptar (escáneres), falla en silencio
+                    log(f"⚠️ Intento de conexión no encriptada rechazado: {addr[0]}")
+                    client.close()
+                    continue
+                except Exception as e:
+                    client.close()
+                    continue
+
+            with conn_lock:
+                if active_connections >= MAX_CONNECTIONS:
+                    client.close()
+                    continue
+                active_connections += 1
+                
+            ConnectionHandler(client, addr).start()
+            
+    except Exception as e: log(f"❌ Error crítico en servidor: {e}")
+    finally: server.close()
+
+if __name__ == "__main__":
+    main()
+
+