| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- # -*- coding: utf-8 -*-
- import socket
- import threading
- import select
- import sys
- import time
- import itertools
- import os
- import ssl
- # ==============================================================================
- # CONFIGURACIÓN DEL SISTEMA
- # ==============================================================================
- LISTENING_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 443
- SSH_HOST = '127.0.0.1'
- SSH_PORT = 22 # Cambiar a 223 si usas Dropbear modificado
- LOG_FILE = "/root/proxy.log"
- MAX_LOG_SIZE = 10 * 1024 * 1024 # 10MB antes de rotar
- # RUTAS DE CERTIFICADOS SSL (Deben existir en el servidor)
- CERT_FILE = "/root/cert.pem"
- KEY_FILE = "/root/key.pem"
- # ==============================================================================
- # PARÁMETROS DE RESILIENCIA Y SEGURIDAD
- # ==============================================================================
- MAX_CONNECTIONS = 200
- CONNECTION_COOLDOWN = 0.7
- BUFLEN = 16384
- TIMEOUT_HTTP = 3.0
- # SISTEMA DE AUTO-BANEO TEMPORAL
- AUTO_BAN_STRIKES = 3
- BAN_TIME = 3600 # 1 hora de baneo
- banned_ips = {}
- ip_strikes = {}
- # RESPUESTA WEB FALSA (Para engañar a escáneres como Shodan)
- FAKE_WEB = (
- b"HTTP/1.1 200 OK\r\n"
- b"Server: nginx/1.24.0\r\n"
- b"Content-Type: text/html; charset=UTF-8\r\n"
- b"Connection: close\r\n\r\n"
- b"<!DOCTYPE html><html><head><title>Welcome</title></head>"
- b"<body style='font-family:sans-serif;text-align:center;padding:50px;'>"
- b"<h1>404 Not Found</h1><p>The requested resource was not found.</p>"
- b"</body></html>"
- )
- # MENSAJES PARA LA INYECCIÓN HTTP (NetMod)
- MENSAJES = [
- "🚀 CONEXION TLS ESTABLECIDA",
- "🛡️ CIFRADO MILITAR ACTIVO",
- "🔋 MODO SIGILO SSL OK",
- "Pfsense",
- "OPNsense",
- "VyOS",
- "Claro",
- "Windows Server",
- "BSD Free",
- "VyOS",
- "Altice",
- "Viva",
- "Google",
- "VyOS",
- "TNSR",
- "🌐 BYPASS DE FIREWALL OK"
- ]
- mensaje_cycle = itertools.cycle(MENSAJES)
- cycle_lock = threading.Lock()
- # ==============================================================================
- # FUNCIONES DE SOPORTE
- # ==============================================================================
- def write_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("--- LOG REINICIADO ---\n")
-
- ts = time.strftime("%Y-%m-%d %H:%M:%S")
- ip_info = f" [{addr[0]}]" if addr else ""
- log_line = f"[{ts}]{ip_info} {msg}\n"
-
- with open(LOG_FILE, 'a') as f: f.write(log_line)
- print(log_line.strip())
- except: pass
- active_conn_count = 0
- conn_count_lock = threading.Lock()
- class ProxyHandler(threading.Thread):
- def __init__(self, client_socket, addr):
- super().__init__(daemon=True)
- self.client = client_socket
- self.addr = addr
- self.target = None
- def run(self):
- global active_conn_count
- client_ip = self.addr[0]
- try:
- # 1. Verificar Baneo
- if client_ip in banned_ips:
- if time.time() < banned_ips[client_ip]: return
- else: del banned_ips[client_ip]
- # 2. Leer Petición inicial
- self.client.settimeout(TIMEOUT_HTTP)
- try:
- data = self.client.recv(BUFLEN)
- except: data = b""
- # 3. Lógica de Detección de Protocolo
- if data:
- # Si es un navegador/escáner buscando web
- if b"HTTP/" in data and b"Upgrade: websocket" not in data:
- write_log("🕵️ Escáner detectado. Enviando Fake Web.", self.addr)
- self.client.sendall(FAKE_WEB)
- return
-
- # Si es tráfico SSH directo (sin inyector)
- if data.startswith(b"SSH-"):
- self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=5)
- self.target.sendall(data)
- else:
- # Es un Inyector (NetMod/NekoBox)
- with cycle_lock: current_msg = next(mensaje_cycle)
- resp = f"HTTP/1.1 101 {current_msg}\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\n"
- self.client.sendall(resp.encode('utf-8'))
- self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=5)
- else:
- # Conexión vacía (posible probe silencioso)
- self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=5)
- # 4. Iniciar Túnel
- self.bridge()
- except Exception as e:
- pass
- finally:
- with conn_count_lock: active_conn_count -= 1
- self.cleanup()
- def bridge(self):
- self.client.settimeout(None)
- self.target.settimeout(None)
- sockets = [self.client, self.target]
- while True:
- r, _, e = select.select(sockets, [], sockets, 300)
- if e or not r: break
- for s in r:
- try:
- data = s.recv(BUFLEN)
- if not data: return
- (self.target if s is self.client else self.client).sendall(data)
- except: return
- def cleanup(self):
- for s in [self.client, self.target]:
- if s:
- try: s.close()
- except: pass
- def main():
- global active_conn_count
-
- # Configuración de Contexto SSL Flexible (Compatible con NetMod)
- context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
- try:
- context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
- except Exception as e:
- print(f"Error cargando certificados: {e}")
- sys.exit(1)
- # Creación del Socket Servidor (Dual Stack IPv4/IPv6)
- try:
- server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- server.bind(('', LISTENING_PORT))
- server.listen(500)
-
- print(f"=====================================================")
- print(f"🚀 PROXY V7 RESILIENTE INICIADO - PUERTO {LISTENING_PORT}")
- print(f"🛡️ MOTOR ANTI-CRASH Y FAKE WEB ACTIVADOS")
- print(f"=====================================================")
- while True:
- try:
- raw_client, addr = server.accept()
-
- # 5. Envolver conexión en SSL
- try:
- client = context.wrap_socket(raw_client, server_side=True)
- except:
- raw_client.close()
- continue
- with conn_count_lock:
- if active_conn_count >= MAX_CONNECTIONS:
- client.close()
- continue
- active_conn_count += 1
-
- ProxyHandler(client, addr).start()
- except socket.error:
- time.sleep(0.05) # Pausa ante saturación de sockets
- continue
- except Exception:
- time.sleep(0.5)
- continue
- except Exception as e:
- print(f"Error crítico: {e}")
- finally:
- server.close()
- if __name__ == "__main__":
- main()
|