Proxy_VPN.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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 (22 o 223) y OpenSSH
  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 Y AUTO-BANEO ---
  21. ALLOWED_IPS = []
  22. BLOCKED_HOSTS = ['ads.doubleclick.net', 'telemetry.microsoft.com']
  23. AUTO_BAN_STRIKES = 3 # Intentos de flood antes de banear la IP en memoria
  24. BAN_TIME = 3600 # Tiempo de baneo en segundos (3600s = 1 hora)
  25. banned_ips_memory = {} # Diccionario: guarda la IP y su tiempo de expiración
  26. ip_strikes = {}
  27. # --- SECCIÓN DE CUSTOM HEADERS (Inyectados en la respuesta 101) ---
  28. CUSTOM_HEADERS = {
  29. "Server": "nginx/1.21.0",
  30. "X-Forwarded-For": "127.0.0.1",
  31. "Content-Type": "text/html; charset=UTF-8",
  32. "Proxy-Connection": "keep-alive",
  33. "Cache-Control": "no-cache"
  34. }
  35. # --- MENSAJES ROTATIVOS (Status 101) ---
  36. MENSAJES = [
  37. "🚀 CONEXION ESTABLECIDA",
  38. "🛡️ SEGURIDAD ACTIVA",
  39. "🔋 OPTIMIZACION SISTEMA",
  40. "🌐 ACCESO NETMOD OK"
  41. ]
  42. mensaje_cycle = itertools.cycle(MENSAJES)
  43. cycle_lock = threading.Lock()
  44. # --- SISTEMA DE LOGS CON AUTO-LIMPIEZA ---
  45. def log(msg, addr=None):
  46. try:
  47. if os.path.exists(LOG_FILE) and os.path.getsize(LOG_FILE) > MAX_LOG_SIZE:
  48. with open(LOG_FILE, 'w') as f:
  49. f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] LOG REINICIADO (Límite 10MB alcanzado)\n")
  50. timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
  51. client_info = f" [{addr[0]}]" if addr else ""
  52. log_entry = f"[{timestamp}]{client_info} {msg}\n"
  53. with open(LOG_FILE, 'a') as f:
  54. f.write(log_entry)
  55. print(log_entry.strip())
  56. except:
  57. pass
  58. # --- GESTIÓN DE ESTADO ---
  59. active_connections = 0
  60. conn_lock = threading.Lock()
  61. ip_cooldowns = {}
  62. class ConnectionHandler(threading.Thread):
  63. def __init__(self, client_socket, addr):
  64. super().__init__(daemon=True)
  65. self.client = client_socket
  66. self.addr = addr
  67. self.target = None
  68. self.tx_bytes = 0 # Bytes transmitidos (Subida)
  69. self.rx_bytes = 0 # Bytes recibidos (Bajada)
  70. def build_http_response(self, status_msg):
  71. headers_str = "".join([f"{k}: {v}\r\n" for k, v in CUSTOM_HEADERS.items()])
  72. response = (
  73. f"HTTP/1.1 101 {status_msg}\r\n"
  74. f"{headers_str}"
  75. f"Connection: Upgrade\r\n"
  76. f"Upgrade: websocket\r\n\r\n"
  77. )
  78. return response.encode('utf-8')
  79. def run(self):
  80. global active_connections
  81. client_ip = self.addr[0]
  82. try:
  83. # 1. Filtro de Auto-Baneo temporal (1 hora)
  84. if client_ip in banned_ips_memory:
  85. if time.time() > banned_ips_memory[client_ip]:
  86. # El tiempo de castigo terminó, perdonamos la IP
  87. del banned_ips_memory[client_ip]
  88. if client_ip in ip_strikes:
  89. del ip_strikes[client_ip]
  90. log(f"🔓 Baneo expirado. Acceso restaurado.", self.addr)
  91. else:
  92. return # Sigue baneado: Cierra silenciosamente
  93. # 2. Validación de Lista Blanca
  94. if ALLOWED_IPS and client_ip not in ALLOWED_IPS:
  95. log("🚫 Conexión rechazada: IP no autorizada", self.addr)
  96. return
  97. # 3. Control de Rate-Limiting e Inteligencia de Auto-Ban
  98. now = time.time()
  99. if client_ip in ip_cooldowns and (now - ip_cooldowns[client_ip]) < CONNECTION_COOLDOWN:
  100. # Si viola el cooldown, sumamos un strike
  101. ip_strikes[client_ip] = ip_strikes.get(client_ip, 0) + 1
  102. if ip_strikes[client_ip] >= AUTO_BAN_STRIKES:
  103. banned_ips_memory[client_ip] = time.time() + BAN_TIME
  104. log(f"⛔ IP Baneada en memoria por {BAN_TIME} segundos (Flood/Spam)", self.addr)
  105. return
  106. ip_cooldowns[client_ip] = now
  107. ip_strikes[client_ip] = 0 # Resetea strikes si conecta legalmente
  108. # 4. Leer payload inicial de Netmod (Absorción)
  109. self.client.settimeout(5)
  110. try:
  111. payload = self.client.recv(BUFLEN)
  112. if not payload: return
  113. # 💡 Modo Sigilo: Si un navegador intenta acceder (ej. GET / HTTP/1.1) y NO es Netmod.
  114. # Puedes quitar el comentario de las 3 líneas de abajo para activarlo si quieres que Netmod sea obligatorio.
  115. # if b"Upgrade: websocket" not in payload and b"HTTP/" in payload:
  116. # self.client.sendall(b"HTTP/1.1 400 Bad Request\r\nServer: nginx\r\n\r\n")
  117. # return
  118. except: return
  119. # 5. Conectar al destino (SSH/Dropbear)
  120. log(f"Intentando conectar a {SSH_HOST}:{SSH_PORT}...", self.addr)
  121. self.target = socket.create_connection((SSH_HOST, SSH_PORT), timeout=10)
  122. # 6. Elegir mensaje rotativo y responder al cliente
  123. with cycle_lock:
  124. current_status = next(mensaje_cycle)
  125. self.client.sendall(self.build_http_response(current_status))
  126. log(f"✅ Túnel activo: {current_status}", self.addr)
  127. # 7. Túnel bidireccional puro
  128. self.tunnel()
  129. except Exception as e:
  130. log(f"❌ Error: {e}", self.addr)
  131. finally:
  132. with conn_lock:
  133. active_connections -= 1
  134. self.cleanup()
  135. def tunnel(self):
  136. self.client.settimeout(None)
  137. self.target.settimeout(None)
  138. sockets = [self.client, self.target]
  139. while True:
  140. readable, _, error = select.select(sockets, [], sockets, 300)
  141. if error or not readable:
  142. break
  143. for s in readable:
  144. try:
  145. data = s.recv(BUFLEN)
  146. if not data:
  147. return
  148. if s is self.client:
  149. self.target.sendall(data)
  150. self.tx_bytes += len(data) # Sumar subida
  151. else:
  152. self.client.sendall(data)
  153. self.rx_bytes += len(data) # Sumar bajada
  154. except:
  155. return
  156. def cleanup(self):
  157. # Calcula el tráfico total al cerrar la conexión
  158. total_mb = (self.tx_bytes + self.rx_bytes) / (1024 * 1024)
  159. if total_mb > 0.01: # Solo registrar si hubo tráfico real (> 10KB)
  160. log(f"[*] Conexión finalizada. Tráfico consumido: {total_mb:.2f} MB", self.addr)
  161. for s in [self.client, self.target]:
  162. if s:
  163. try: s.close()
  164. except: pass
  165. def main():
  166. global active_connections
  167. # Intentamos socket dual (IPv6/IPv4)
  168. try:
  169. addr_info = socket.getaddrinfo(None, LISTENING_PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
  170. addr_info.sort(key=lambda x: x[0] == socket.AF_INET6, reverse=True)
  171. af, socktype, proto, canonname, sa = addr_info[0]
  172. server = socket.socket(af, socktype, proto)
  173. server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  174. if af == socket.AF_INET6:
  175. try: server.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
  176. except: pass
  177. server.bind(sa)
  178. server.listen(200)
  179. log(f"=====================================================")
  180. log(f"🔥 Servidor Robusto Iniciado en Puerto {LISTENING_PORT}")
  181. log(f"🎯 Destino Interno: {SSH_HOST}:{SSH_PORT}")
  182. log(f"🛡️ Logs limitados a 10MB en {LOG_FILE}")
  183. log(f"=====================================================")
  184. while True:
  185. client, addr = server.accept()
  186. with conn_lock:
  187. if active_connections >= MAX_CONNECTIONS:
  188. client.close()
  189. continue
  190. active_connections += 1
  191. ConnectionHandler(client, addr).start()
  192. except Exception as e:
  193. log(f"❌ Error crítico en servidor: {e}")
  194. finally:
  195. server.close()
  196. if __name__ == "__main__":
  197. main()