Просмотр исходного кода

Actualizar 'C/proxy_dual.c'

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /root/key.pem -out /root/cert.pem -subj "/C=US/ST=NY/L=New York/O=Cloudflare/CN=www.cloudflare.com"

gcc -O3 -o /root/proxy_dual proxy_dual.c -lssl -lcrypto -lpthread
yosoyhendrix 1 день назад
Родитель
Сommit
b9baba1cb3
1 измененных файлов с 22 добавлено и 17 удалено
  1. 22 17
      C/proxy_dual.c

+ 22 - 17
C/proxy_dual.c

@@ -1,7 +1,7 @@
 /*
  * =====================================================================================
  * PROXY VPN DUAL (TCP + TLS) - GRADO ENTERPRISE NATIVO EN C
- * Mejoras: Soporte DUAL-STACK (IPv4 e IPv6 simultáneo en el mismo puerto).
+ * Mejoras: Soporte DUAL-STACK (IPv4/IPv6) + Fix de Timeout OpenSSL para NetMod
  * Compilación: gcc -O3 -o proxy_dual proxy_dual.c -lssl -lcrypto -lpthread
  * =====================================================================================
  */
@@ -42,7 +42,6 @@ int active_connections = 0;
 pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;
 pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-// ESTRUCTURA MODIFICADA: Usamos sockaddr_storage para soportar tanto IPv4 como IPv6
 typedef struct {
     int client_fd;
     struct sockaddr_storage addr; 
@@ -75,20 +74,14 @@ SSL_CTX *create_ssl_context() {
     return ctx;
 }
 
-// CREACIÓN DE SOCKET DUAL-STACK
 int create_server_socket(int port) {
-    // 1. Crear socket IPv6 (AF_INET6)
     int s_sock = socket(AF_INET6, SOCK_STREAM, 0);
     if (s_sock < 0) return -1;
-
     int opt = 1;
     setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
-
-    // 2. MAGIA DUAL-STACK: Apagar la restricción de solo-IPv6
     int no = 0;
     setsockopt(s_sock, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
 
-    // 3. Bind a in6addr_any (Equivale a "::")
     struct sockaddr_in6 addr;
     memset(&addr, 0, sizeof(addr));
     addr.sin6_family = AF_INET6;
@@ -106,12 +99,11 @@ void *connection_handler(void *arg) {
     int is_tls = data->is_tls;
     SSL_CTX *ctx = data->ssl_ctx;
     
-    // EXTRAER IP (IPv4 o IPv6)
     char client_ip[INET6_ADDRSTRLEN];
     if (data->addr.ss_family == AF_INET) {
         struct sockaddr_in *s = (struct sockaddr_in *)&data->addr;
         inet_ntop(AF_INET, &s->sin_addr, client_ip, sizeof(client_ip));
-    } else { // AF_INET6
+    } else { 
         struct sockaddr_in6 *s = (struct sockaddr_in6 *)&data->addr;
         inet_ntop(AF_INET6, &s->sin6_addr, client_ip, sizeof(client_ip));
     }
@@ -130,11 +122,23 @@ void *connection_handler(void *arg) {
         }
     }
 
-    struct timeval tv = {3, 0};
-    setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
-    
+    // --- LA MAGIA QUE ARREGLA NETMOD ---
+    // En lugar de forzar a OpenSSL a leer con timeout, usamos select() para vigilar.
+    fd_set init_fds;
+    FD_ZERO(&init_fds);
+    FD_SET(client_sock, &init_fds);
+    struct timeval init_tv = {3, 0}; // 3 segundos de tolerancia
+
     char buffer[BUFLEN];
-    int bytes_read = is_tls ? SSL_read(ssl, buffer, sizeof(buffer)-1) : recv(client_sock, buffer, sizeof(buffer)-1, 0);
+    int bytes_read = 0;
+
+    // Vigila el socket. Si el cliente dice algo en menos de 3 seg, lo leemos.
+    if (select(client_sock + 1, &init_fds, NULL, NULL, &init_tv) > 0) {
+        if (is_tls) bytes_read = SSL_read(ssl, buffer, sizeof(buffer)-1);
+        else bytes_read = recv(client_sock, buffer, sizeof(buffer)-1, 0);
+    } 
+    // Si select da 0, significa que pasaron 3 seg en silencio. 
+    // bytes_read se queda en 0, y OpenSSL no se corrompe.
 
     int target_sock = -1;
     long tx_bytes = 0, rx_bytes = 0;
@@ -169,16 +173,17 @@ void *connection_handler(void *arg) {
             else send(client_sock, response, strlen(response), 0);
         }
     } else {
+        // Entró al Modo Silencioso (NetMod por TLS) sin dañar el estado de SSL
         struct sockaddr_in t_addr;
         target_sock = socket(AF_INET, SOCK_STREAM, 0);
         t_addr.sin_family = AF_INET;
         t_addr.sin_port = htons(SSH_PORT);
         inet_pton(AF_INET, SSH_HOST, &t_addr.sin_addr);
         if (connect(target_sock, (struct sockaddr *)&t_addr, sizeof(t_addr)) != 0) goto cleanup;
+        else write_log(client_ip, proto_name, "✅ Túnel Modo Silencioso");
     }
 
-    tv.tv_sec = 0;
-    setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
+    // El túnel bidireccional se mantiene intacto
     int max_fd = (client_sock > target_sock) ? client_sock : target_sock;
 
     while (1) {
@@ -224,7 +229,7 @@ int main(int argc, char **argv) {
 
     if (server_tcp < 0 || server_tls < 0) exit(1);
 
-    write_log(NULL, "SISTEMA", "🚀 PROXY DUAL ENTERPRISE INICIADO (Soporte IPv4 + IPv6)");
+    write_log(NULL, "SISTEMA", "🚀 PROXY DUAL ENTERPRISE INICIADO (Fix NetMod TLS)");
 
     int max_server_fd = (server_tcp > server_tls) ? server_tcp : server_tls;