Proxy_VPN.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. # -*- coding: utf-8 -*-
  2. import socket
  3. import threading
  4. import select
  5. import sys
  6. import time
  7. import itertools
  8. import os
  9. # --- CONFIGURACIÓN BASE ---
  10. LISTENING_PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8080
  11. SSH_HOST = '127.0.0.1'
  12. SSH_PORT = 22 # Compatible con Dropbear o OpenSSH local
  13. LOG_FILE = "/root/proxy.log"
  14. MAX_LOG_SIZE = 10 * 1024 * 1024 # 10MB
  15. # --- CONFIGURACIÓN DE SEGURIDAD AVANZADA ---
  16. MAX_CONNECTIONS = 1000
  17. CONNECTION_COOLDOWN = 0.5
  18. TIMEOUT = 60
  19. BUFLEN = 16384
  20. # --- FILTRADO DE ACCESO ---
  21. ALLOWED_IPS = []
  22. BLOCKED_HOSTS = ['ads.doubleclick.net', 'telemetry.microsoft.com']
  23. # --- SECCIÓN DE CUSTOM HEADERS (Inyectados en la respuesta 101) ---
  24. CUSTOM_HEADERS = {
  25. "Server": "nginx/1.21.0",
  26. "X-Forwarded-For": "127.0.0.1",
  27. "Content-Type": "text/html; charset=UTF-8",
  28. "Proxy-Connection": "keep-alive",
  29. "Cache-Control": "no-cache",
  30. "X-Real-IP": "127.0.0.1"
  31. }
  32. # --- MENSAJES ROTATIVOS (Status 101) ---
  33. MENSAJES = [
  34. "🚀 CONEXION ESTABLECIDA",
  35. "🛡️ SEGURIDAD ACTIVA",
  36. "🔋 OPTIMIZACION DROPBEAR",
  37. "🌐 ACCESO NETMOD OK",
  38. "Pfsense",
  39. "OPNsense",
  40. "VyOS",
  41. "Claro",
  42. "Windows Server",
  43. "BSD Free",
  44. "VyOS",
  45. "Altice",
  46. "Viva",
  47. "Google",
  48. "VyOS",
  49. "TNSR"
  50. ]
  51. mensaje_cycle = itertools.cycle(MENSAJES)
  52. cycle_lock = threading.Lock()
  53. # --- SISTEMA DE LOGS CON AUTO-LIMPIEZA ---
  54. def log(msg, addr=None):
  55. # Verificar tamaño del log y limpiar si excede el límite
  56. if os.path.exists(LOG_FILE) and os.path.getsize(LOG_FILE) > MAX_LOG_SIZE:
  57. with open(LOG_FILE, 'w') as f:
  58. f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] LOG REINICIADO (Límite 10MB alcanzado)\n")
  59. timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
  60. client_info = f" [{addr[0]}]" if addr else ""
  61. log_entry = f"[{timestamp}]{client_info} {msg}\n"
  62. # Escribir en archivo y consola
  63. try:
  64. with open(LOG_FILE, 'a') as f:
  65. f.write(log_entry)
  66. print(log_entry.strip())
  67. except Exception as e:
  68. print(f"Error escribiendo log: {e}")
  69. # --- GESTIÓN DE ESTADO ---
  70. active_connections = 0
  71. conn_lock = threading.Lock()
  72. ip_cooldowns = {}
  73. class ConnectionHandler(threading.Thread):
  74. def __init__(self, client_socket, addr):
  75. super().__init__(daemon=True)
  76. self.client = client_socket
  77. self.addr = addr
  78. self.target = None
  79. def build_http_response(self, status_msg):
  80. headers_str = "".join([f"{k}: {v}\r\n" for k, v in CUSTOM_HEADERS.items()])
  81. response = (
  82. f"HTTP/1.1 101 {status_msg}\r\n"
  83. f"{headers_str}"
  84. f"Connection: Upgrade\r\n"
  85. f"Upgrade: websocket\r\n\r\n"
  86. )
  87. return response.encode('utf-8')
  88. def run(self):
  89. global active_connections
  90. try:
  91. log("--- Nueva conexión recibida ---", self.addr)
  92. # 1. Validación de IP
  93. if ALLOWED_IPS and self.addr[0] not in ALLOWED_IPS:
  94. log("🚫 Conexión rechazada: IP no autorizada", self.addr)
  95. return
  96. # 2. Control de Rate-Limiting / Cooldown
  97. now = time.time()
  98. if self.addr[0] in ip_cooldowns and (now - ip_cooldowns[self.addr[0]]) < CONNECTION_COOLDOWN:
  99. log("⚠️ Conexión rechazada por rate-limiting", self.addr)
  100. return
  101. ip_cooldowns[self.addr[0]] = now
  102. # 3. Payload inicial
  103. self.client.settimeout(10)
  104. payload = self.client.recv(BUFLEN)
  105. if not payload:
  106. return
  107. # 4. Conexión al destino (Dropbear/SSH)
  108. with cycle_lock:
  109. current_status = next(mensaje_cycle)
  110. log(f"Intentando conectar a {SSH_HOST}:{SSH_PORT}...", self.addr)
  111. # Soporte IPv4/IPv6 para la conexión interna
  112. self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=TIMEOUT)
  113. log("Conexión exitosa al destino SSH", self.addr)
  114. # 5. Respuesta HTTP 101
  115. self.client.sendall(self.build_http_response(current_status))
  116. log(f"✅ Protocolo Upgrade: {current_status}", self.addr)
  117. # 6. Túnel bidireccional
  118. self.tunnel()
  119. except Exception as e:
  120. log(f"❌ Error: {str(e)}", self.addr)
  121. finally:
  122. with conn_lock:
  123. active_connections -= 1
  124. self.cleanup()
  125. def tunnel(self):
  126. self.client.settimeout(None)
  127. self.target.settimeout(None)
  128. sockets = [self.client, self.target]
  129. while True:
  130. readable, _, error = select.select(sockets, [], sockets, TIMEOUT)
  131. if error or not readable:
  132. break
  133. for s in readable:
  134. try:
  135. data = s.recv(BUFLEN)
  136. if not data:
  137. return
  138. dest = self.target if s is self.client else self.client
  139. dest.sendall(data)
  140. except:
  141. return
  142. def cleanup(self):
  143. for s in [self.client, self.target]:
  144. if s:
  145. try:
  146. s.close()
  147. except:
  148. pass
  149. def main():
  150. global active_connections
  151. # Configuración de Socket Dual (IPv4 e IPv6)
  152. try:
  153. if socket.has_dualstack_ipv6():
  154. server = socket.create_server(('::', LISTENING_PORT), family=socket.AF_INET6, dualstack_ipv6=True)
  155. else:
  156. server = socket.create_server(('0.0.0.0', LISTENING_PORT), family=socket.AF_INET)
  157. server.listen(200)
  158. log(f"🔥 Servidor Robusto Iniciado en Puerto {LISTENING_PORT} (Dual IPv4/IPv6)")
  159. log(f"🛡️ Logs: {LOG_FILE} (Autolimitado a 10MB)")
  160. while True:
  161. client, addr = server.accept()
  162. with conn_lock:
  163. if active_connections >= MAX_CONNECTIONS:
  164. log("⛔ Máximo de conexiones alcanzado.", addr)
  165. client.close()
  166. continue
  167. active_connections += 1
  168. ConnectionHandler(client, addr).start()
  169. except Exception as e:
  170. log(f"❌ Error crítico en servidor: {e}")
  171. finally:
  172. server.close()
  173. if __name__ == "__main__":
  174. main()