yosoyhendrix пре 2 дана
родитељ
комит
ef748c3723
1 измењених фајлова са 122 додато и 120 уклоњено
  1. 122 120
      Proxy_VPN.py

+ 122 - 120
Proxy_VPN.py

@@ -7,45 +7,58 @@ import sys
 import time
 import itertools
 import os
+import ssl
 
 # --- CONFIGURACIÓN BASE ---
-LISTENING_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8080
+LISTENING_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 443
 SSH_HOST = '127.0.0.1'
-SSH_PORT = 22  # Compatible con Dropbear (22 o 223) y OpenSSH
+SSH_PORT = 22  # Asegúrate de que este es tu puerto SSH/Dropbear
 LOG_FILE = "/root/proxy.log"
-MAX_LOG_SIZE = 10 * 1024 * 1024  # 10MB
+MAX_LOG_SIZE = 10 * 1024 * 1024
+
+# --- CONFIGURACIÓN SSL/TLS ---
+USE_SSL = True  
+CERT_FILE = "/root/cert.pem"
+KEY_FILE = "/root/key.pem"
 
 # --- CONFIGURACIÓN DE SEGURIDAD AVANZADA ---
-MAX_CONNECTIONS = 100
+MAX_CONNECTIONS = 150 # Ligeramente aumentado
 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  # Intentos de flood antes de banear la IP en memoria
-BAN_TIME = 3600       # Tiempo de baneo en segundos (3600s = 1 hora)
-banned_ips_memory = {} # Diccionario: guarda la IP y su tiempo de expiración
+AUTO_BAN_STRIKES = 3  
+BAN_TIME = 3600       
+banned_ips_memory = {} 
 ip_strikes = {}
+ALLOWED_IPS = [] 
 
-# --- SECCIÓN DE CUSTOM HEADERS (Inyectados en la respuesta) ---
+# --- RESPUESTA FAKE WEB (ANTI ACTIVE PROBING) ---
+FAKE_WEB_RESPONSE = (
+    b"HTTP/1.1 200 OK\r\n"
+    b"Server: nginx/1.21.0\r\n"
+    b"Content-Type: text/html; charset=UTF-8\r\n"
+    b"Connection: close\r\n\r\n"
+    b"<!DOCTYPE html>\n<html>\n<head><title>Bienvenido</title></head>\n"
+    b"<body style='text-align:center; padding:50px; font-family:sans-serif;'>\n"
+    b"<h1>Hola</h1>\n<p>Servicio en funcionamiento.</p>\n"
+    b"</body>\n</html>\n"
+)
+
+# --- CUSTOM HEADERS PARA VPN ---
 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-v3",
+    "X-Proxy-Agent": "Gemini-Ultra-Robust-v7-HA",
     "X-Forwarded-For-Proxy": "True"
 }
 
-# --- MENSAJES ROTATIVOS (Status 101) ---
 MENSAJES = [
-    "🚀 CONEXION ESTABLECIDA",
-    "🛡️ SEGURIDAD ACTIVA",
-    "🔋 OPTIMIZACION SISTEMA",
-  	"Pfsense",
+    "🚀 CONEXION TLS ESTABLECIDA",
+    "🛡️ CIFRADO MILITAR ACTIVO",
+    "🔋 MODO SIGILO SSL OK",
+    "Pfsense",
     "OPNsense",
     "VyOS",
     "Claro",
@@ -57,32 +70,23 @@ MENSAJES = [
     "Google",
     "VyOS",
     "TNSR",
-    "🌐 ACCESO OK"
+    "🌐 BYPASS DE FIREWALL OK"
 ]
 mensaje_cycle = itertools.cycle(MENSAJES)
 cycle_lock = threading.Lock()
 
-# --- SISTEMA DE LOGS CON AUTO-LIMPIEZA ---
 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 (Límite 10MB alcanzado)\n")
-
+            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
+        with open(LOG_FILE, 'a') as f: f.write(log_entry)
+    except: pass
 
-# --- GESTIÓN DE ESTADO ---
 active_connections = 0
 conn_lock = threading.Lock()
-ip_cooldowns = {}
 
 class ConnectionHandler(threading.Thread):
     def __init__(self, client_socket, addr):
@@ -90,118 +94,90 @@ class ConnectionHandler(threading.Thread):
         self.client = client_socket
         self.addr = addr
         self.target = None
-        self.tx_bytes = 0 # Bytes transmitidos (Subida)
-        self.rx_bytes = 0 # Bytes recibidos (Bajada)
+        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')
+        return (f"HTTP/1.1 101 {status_msg}\r\n{headers_str}Connection: Upgrade\r\nUpgrade: websocket\r\n\r\n").encode('utf-8')
 
     def run(self):
         global active_connections
         client_ip = self.addr[0]
         
         try:
-            # 1. Filtro de Auto-Baneo temporal (1 hora)
             if client_ip in banned_ips_memory:
                 if time.time() > banned_ips_memory[client_ip]:
-                    # El tiempo de castigo terminó, perdonamos la 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 # Sigue baneado: Cierra silenciosamente
+                    if client_ip in ip_strikes: del ip_strikes[client_ip]
+                else: return
                 
-            # 2. Validación de Lista Blanca
-            if ALLOWED_IPS and client_ip not in ALLOWED_IPS:
-                log("🚫 Conexión rechazada: IP no autorizada", self.addr)
-                return
-
-            # 3. Control de Rate-Limiting e Inteligencia de Auto-Ban
             now = time.time()
-            if client_ip in ip_cooldowns and (now - ip_cooldowns[client_ip]) < CONNECTION_COOLDOWN:
-                # Si viola el cooldown, sumamos un strike
+            if client_ip in ip_strikes and (now - ip_strikes.get('last_time', 0)) < 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 en memoria por {BAN_TIME} segundos (Flood/Spam)", self.addr)
+                    log(f"⛔ IP Baneada por Flood/Escaneo: {client_ip}", self.addr)
                 return
                 
-            ip_cooldowns[client_ip] = now
-            ip_strikes[client_ip] = 0 # Resetea strikes si conecta legalmente
+            ip_strikes['last_time'] = now
+            ip_strikes[client_ip] = 0
 
-            # 4. Leer payload inicial
-            self.client.settimeout(5)
+            self.client.settimeout(2.0)
+            payload = b""
             try:
                 payload = self.client.recv(BUFLEN)
-                if not payload: return
-                
-                # 💡 Modo Sigilo: Si un navegador intenta acceder (ej. GET / HTTP/1.1) y NO es un inyector.
-                # Puedes quitar el comentario de las 3 lineas de abajo para activarlo si quieres que el Inyector sea obligatorio.
-                # if b"Upgrade: websocket" not in payload and b"HTTP/" in payload:
-                #     self.client.sendall(b"HTTP/1.1 400 Bad Request\r\nServer: nginx\r\n\r\n")
-                #     return
-            except: return
-
-            # 5. Conectar al destino (SSH/Dropbear)
-            log(f"Intentando conectar a {SSH_HOST}:{SSH_PORT}...", self.addr)
-            self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=10)
-            
-            # 6. Elegir mensaje rotativo y responder al cliente
-            with cycle_lock:
-                current_status = next(mensaje_cycle)
-            
-            self.client.sendall(self.build_http_response(current_status))
-            log(f"✅ Túnel activo: {current_status}", self.addr)
+            except socket.timeout:
+                pass # NetMod en silencio
+            except Exception:
+                return
 
-            # 7. Túnel bidireccional puro
+            try:
+                self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=10)
+            except Exception as e:
+                log(f"❌ Error interno destino SSH: {e}", self.addr)
+                return
+
+            if payload:
+                if payload.startswith(b"SSH-"):
+                    self.target.sendall(payload)
+                elif b"HTTP/" in payload and b"Upgrade: websocket" not in payload:
+                    log(f"🕵️ Escáner detectado. Respondiendo Fake Web.", self.addr)
+                    self.client.sendall(FAKE_WEB_RESPONSE)
+                    return 
+                else:
+                    with cycle_lock: current_status = next(mensaje_cycle)
+                    self.client.sendall(self.build_http_response(current_status))
+            
             self.tunnel()
 
-        except Exception as e:
-            log(f"❌ Error: {e}", self.addr)
+        except Exception as e: pass
         finally:
-            with conn_lock:
-                active_connections -= 1
+            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
-            
+            if error or not readable: break
             for s in readable:
                 try:
                     data = s.recv(BUFLEN)
-                    if not data:
-                        return
-                    
+                    if not data: return
                     if s is self.client:
                         self.target.sendall(data)
-                        self.tx_bytes += len(data) # Sumar subida
+                        self.tx_bytes += len(data)
                     else:
                         self.client.sendall(data)
-                        self.rx_bytes += len(data) # Sumar bajada
-                except:
-                    return
+                        self.rx_bytes += len(data)
+                except: return
 
     def cleanup(self):
-        # Calcula el tráfico total al cerrar la conexión
         total_mb = (self.tx_bytes + self.rx_bytes) / (1024 * 1024)
-        if total_mb > 0.01: # Solo registrar si hubo tráfico real (> 10KB)
-            log(f"[*] Conexión finalizada. Tráfico consumido: {total_mb:.2f} MB", self.addr)
-            
+        if total_mb > 0.05: log(f"[*] Tráfico finalizado: {total_mb:.2f} MB", self.addr)
         for s in [self.client, self.target]:
             if s:
                 try: s.close()
@@ -209,41 +185,67 @@ class ConnectionHandler(threading.Thread):
 
 def main():
     global active_connections
-    
-    # Intentamos socket dual (IPv6/IPv4)
+    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)
+        except Exception as e:
+            print(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)
+        server.listen(500) # Aumentado el backlog para soportar ráfagas de bots
         
-        log(f"=====================================================")
-        log(f"🔥 Servidor Robusto Iniciado en Puerto {LISTENING_PORT}")
-        log(f"🎯 Destino Interno: {SSH_HOST}:{SSH_PORT}")
-        log(f"🛡️ Logs limitados a 10MB en {LOG_FILE}")
-        log(f"=====================================================")
+        print(f"=====================================================")
+        print(f"🔥 Servidor Robusto INMORTAL Iniciado - Puerto {LISTENING_PORT}")
+        print(f"🛡️ Motor SSL/TLS & Anti-Crash: ACTIVADO")
+        print(f"=====================================================")
 
+        # EL BUCLE PRINCIPAL AHORA ES BLINDADO
         while True:
-            client, addr = server.accept()
-            with conn_lock:
-                if active_connections >= MAX_CONNECTIONS:
-                    client.close()
-                    continue
-                active_connections += 1
-            ConnectionHandler(client, addr).start()
+            try:
+                client, addr = server.accept()
+                
+                if USE_SSL:
+                    try:
+                        client = ssl_context.wrap_socket(client, server_side=True)
+                    except Exception:
+                        # Si el bot manda basura en lugar de un handshake SSL, se cierra y se ignora silenciosamente.
+                        client.close()
+                        continue
+
+                with conn_lock:
+                    if active_connections >= MAX_CONNECTIONS:
+                        client.close()
+                        continue
+                    active_connections += 1
+                    
+                ConnectionHandler(client, addr).start()
+                
+            except socket.error as e:
+                # Si Linux se queda sin recursos por 1 segundo por un ataque DDoS, 
+                # esperamos 50ms y volvemos a intentarlo en lugar de apagar el script.
+                time.sleep(0.05)
+                continue
+            except Exception as e:
+                time.sleep(1)
+                continue
             
-    except Exception as e:
-        log(f"❌ Error crítico en servidor: {e}")
-    finally:
+    except Exception as e: 
+        print(f"Error fatal: {e}")
+    finally: 
         server.close()
 
 if __name__ == "__main__":