Pythonv1.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. # -*- coding: utf-8 -*-
  2. # ==============================================================================
  3. # PROXY MULTIFILAMENTADO DE ALTA DISPONIBILIDAD - VERSIÓN PYTHON 3
  4. #
  5. # CARACTERÍSTICAS PRINCIPALES:
  6. # 1. Rotación de Mensajes: Cada respuesta HTTP 101 varía cíclicamente.
  7. # 2. Soporte Dual Stack: Escucha en IPv4 (0.0.0.0) e IPv6 (::) simultáneamente.
  8. # 3. Thread-Safe: Uso de Locks para evitar colisiones entre hilos.
  9. # 4. Gestión de Logs: Rotación automática para evitar saturación de disco.
  10. # 5. Rate-Limiting: Protección básica contra ataques de inundación por IP.
  11. # ==============================================================================
  12. #screen -dmS badvpn2 /bin/badvpn-udpgw --listen-addr 127.0.0.1:7300 --max-clients 1000 --max-connections-for-client 100
  13. #screen -dmS pydic-80 python3 /root/Pythonv1.py 8080
  14. import socket
  15. import threading
  16. import select
  17. import sys
  18. import time
  19. import logging
  20. import logging.handlers
  21. import itertools
  22. # --- CONFIGURACIÓN DE RED ---
  23. IPV4_ADDR = '0.0.0.0'
  24. IPV6_ADDR = '::'
  25. LISTENING_PORT = int(sys.argv[1]) if sys.argv[1:] else 8080
  26. # --- CONFIGURACIÓN DE SEGURIDAD ---
  27. MAX_CONNECTIONS = 1000
  28. CONNECTION_COOLDOWN = 5 # Segundos entre conexiones de la misma IP
  29. TIMEOUT = 60 # Tiempo de espera para sockets
  30. BUFLEN = 16384 # 16KB de buffer para mayor velocidad
  31. # --- LISTA DE MENSAJES ROTATIVOS ---
  32. # Se enviarán en la línea de estado de la respuesta HTTP 101
  33. MENSAJES = [
  34. "Pfsense",
  35. "OPNsense",
  36. "VyOS",
  37. "Claro",
  38. "Windows Server",
  39. "BSD Free",
  40. "VyOS",
  41. "Altice",
  42. "Viva",
  43. "Google",
  44. "VyOS",
  45. "TNSR"
  46. ]
  47. # Inicialización del iterador cíclico y lock de seguridad
  48. mensaje_cycle = itertools.cycle(MENSAJES)
  49. cycle_lock = threading.Lock()
  50. # --- CONFIGURACIÓN DE LOGS ---
  51. LOG_FILE = 'proxy_server.log'
  52. def setup_logger():
  53. logger = logging.getLogger("ProxyLogger")
  54. logger.setLevel(logging.INFO)
  55. formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(message)s')
  56. # Rotación de logs: 5MB por archivo, máximo 3 backups
  57. handler = logging.handlers.RotatingFileHandler(LOG_FILE, maxBytes=5*1024*1024, backupCount=3)
  58. handler.setFormatter(formatter)
  59. # Salida a consola
  60. console = logging.StreamHandler()
  61. console.setFormatter(formatter)
  62. logger.addHandler(handler)
  63. logger.addHandler(console)
  64. return logger
  65. log = setup_logger()
  66. conn_limit = threading.Semaphore(MAX_CONNECTIONS)
  67. ip_history = {}
  68. ip_lock = threading.Lock()
  69. class ConnectionHandler(threading.Thread):
  70. def __init__(self, client_socket, addr):
  71. super().__init__(daemon=True)
  72. self.client = client_socket
  73. self.addr = addr
  74. self.target = None
  75. self.log_id = f"{addr[0]}:{addr[1]}"
  76. def finish(self):
  77. """Cierra todos los recursos de la conexión de forma segura."""
  78. for s in [self.client, self.target]:
  79. if s:
  80. try:
  81. s.close()
  82. except:
  83. pass
  84. conn_limit.release()
  85. def run(self):
  86. try:
  87. # 1. Leer petición inicial
  88. data = self.client.recv(BUFLEN)
  89. if not data:
  90. return
  91. # 2. Determinar destino (Header X-Real-Host o Default)
  92. headers = data.decode('latin-1', errors='ignore')
  93. target_info = self.extract_header(headers, 'X-Real-Host') or "127.0.0.1:22"
  94. # 3. Obtener mensaje rotativo de forma segura
  95. with cycle_lock:
  96. msg = next(mensaje_cycle)
  97. # 4. Intentar conectar al destino
  98. if not self.connect_to_target(target_info):
  99. return
  100. # 5. Enviar respuesta con el mensaje rotado
  101. resp = (f"HTTP/1.1 101 {msg}\r\n"
  102. f"Connection: Upgrade\r\n"
  103. f"Upgrade: websocket\r\n\r\n").encode('utf-8')
  104. self.client.sendall(resp)
  105. log.info(f"[{self.log_id}] Conectado a {target_info} | Mensaje: {msg}")
  106. # 6. Iniciar túnel bidireccional
  107. self.bridge()
  108. except Exception as e:
  109. log.error(f"[{self.log_id}] Error: {e}")
  110. finally:
  111. self.finish()
  112. def extract_header(self, text, header_name):
  113. for line in text.split('\r\n'):
  114. if line.lower().startswith(header_name.lower() + ":"):
  115. return line.split(':', 1)[1].strip()
  116. return None
  117. def connect_to_target(self, target_str):
  118. try:
  119. parts = target_str.split(':')
  120. host = parts[0]
  121. port = int(parts[1]) if len(parts) > 1 else 22
  122. # Soporte IPv4 e IPv6 automático
  123. infos = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM)
  124. for res in infos:
  125. af, socktype, proto, canonname, sa = res
  126. try:
  127. self.target = socket.socket(af, socktype, proto)
  128. self.target.settimeout(10)
  129. self.target.connect(sa)
  130. return True
  131. except:
  132. continue
  133. return False
  134. except:
  135. return False
  136. def bridge(self):
  137. """Mueve datos entre cliente y destino usando select."""
  138. sockets = [self.client, self.target]
  139. while True:
  140. readable, _, error = select.select(sockets, [], sockets, TIMEOUT)
  141. if error or not readable:
  142. break
  143. for s in readable:
  144. other = self.target if s is self.client else self.client
  145. try:
  146. chunk = s.recv(BUFLEN)
  147. if not chunk:
  148. return
  149. other.sendall(chunk)
  150. except:
  151. return
  152. def main():
  153. # Crear sockets de escucha
  154. listeners = []
  155. for addr_info in [(socket.AF_INET, IPV4_ADDR), (socket.AF_INET6, IPV6_ADDR)]:
  156. try:
  157. s = socket.socket(addr_info[0], socket.SOCK_STREAM)
  158. s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  159. if addr_info[0] == socket.AF_INET6:
  160. s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
  161. s.bind((addr_info[1], LISTENING_PORT))
  162. s.listen(128)
  163. listeners.append(s)
  164. log.info(f"Escuchando en {addr_info[1]}:{LISTENING_PORT}")
  165. except Exception as e:
  166. log.warning(f"No se pudo abrir socket en {addr_info[1]}: {e}")
  167. if not listeners:
  168. log.critical("No hay sockets disponibles. Saliendo.")
  169. return
  170. log.info("Servidor Proxy iniciado. Presiona Ctrl+C para salir.")
  171. try:
  172. while True:
  173. r, _, _ = select.select(listeners, [], [])
  174. for s in r:
  175. client, addr = s.accept()
  176. # Control de frecuencia por IP
  177. ip = addr[0]
  178. with ip_lock:
  179. now = time.time()
  180. last = ip_history.get(ip, 0)
  181. if now - last < CONNECTION_COOLDOWN:
  182. client.close()
  183. continue
  184. ip_history[ip] = now
  185. # Control de límite total
  186. if not conn_limit.acquire(blocking=False):
  187. log.warning(f"Límite de conexiones alcanzado ({MAX_CONNECTIONS})")
  188. client.close()
  189. continue
  190. # Iniciar manejador
  191. ConnectionHandler(client, addr).start()
  192. except KeyboardInterrupt:
  193. log.info("Cerrando servidor...")
  194. finally:
  195. for s in listeners:
  196. s.close()
  197. if __name__ == "__main__":
  198. main()