Sfoglia il codice sorgente

Actualizar 'C/proxy_dual.c'

Proxy Dual (TCP+TLS) con Soporte IPv4/IPv6
yosoyhendrix 2 giorni fa
parent
commit
37221a4235
1 ha cambiato i file con 59 aggiunte e 156 eliminazioni
  1. 59 156
      C/proxy_dual.c

+ 59 - 156
C/proxy_dual.c

@@ -1,9 +1,8 @@
 /*
  * =====================================================================================
  * PROXY VPN DUAL (TCP + TLS) - GRADO ENTERPRISE NATIVO EN C
- * Integra V3 (Plaintext) y V6 (SSL/TLS) con Mensajes Rotativos Dinámicos.
+ * Mejoras: Soporte DUAL-STACK (IPv4 e IPv6 simultáneo en el mismo puerto).
  * Compilación: gcc -O3 -o proxy_dual proxy_dual.c -lssl -lcrypto -lpthread
- * Uso: ./proxy_dual [PUERTO_HTTP] [PUERTO_HTTPS] (Ej: ./proxy_dual 80 443)
  * =====================================================================================
  */
 
@@ -28,59 +27,29 @@
 #define BUFLEN 16384
 #define MAX_CONNECTIONS 500
 #define LOG_FILE "/root/proxy-dual.log"
-
 #define CERT_FILE "/root/cert.pem"
 #define KEY_FILE "/root/key.pem"
 
-// --- FAKE WEB RESPONSES ---
-const char *FAKE_WEB_TCP = 
-    "HTTP/1.1 400 Bad Request\r\n"
-    "Server: nginx/1.24.0\r\n"
-    "Content-Type: text/html\r\n"
-    "Connection: close\r\n\r\n"
-    "<html><body><center><h1>400 Bad Request</h1></center><hr><center>nginx/1.24.0</center></body></html>\r\n";
-
-const char *FAKE_WEB_TLS = 
-    "HTTP/1.1 400 Bad Request\r\n"
-    "Server: nginx/1.24.0\r\n"
-    "Content-Type: text/html\r\n"
-    "Connection: close\r\n\r\n"
-    "<html><body><center><h1>400 Bad Request</h1></center><hr><center>nginx/1.24.0</center></body></html>\r\n";
-
-// --- MENSAJES ROTATIVOS ---
-const char *MENSAJES[] = {
-    "🚀 CONEXION ESTABLECIDA", 
-    "🛡️ CIFRADO MILITAR ACTIVO", 
-    "🔋 MODO SIGILO OK",
-    "Pfsense", 
-    "OPNsense", 
-    "VyOS", 
-    "Claro", 
-    "Windows Server", 
-    "BSD Free", 
-    "Altice", 
-    "Viva", 
-    "Google", 
-    "TNSR", 
-    "🌐 BYPASS DE FIREWALL OK"
-};
+const char *FAKE_WEB_TCP = "HTTP/1.1 400 Bad Request\r\nServer: nginx/1.24.0\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<html><body><center><h1>400 Bad Request</h1></center><hr><center>nginx/1.24.0</center></body></html>\r\n";
+const char *FAKE_WEB_TLS = "HTTP/1.1 400 Bad Request\r\nServer: nginx/1.24.0\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<html><body><center><h1>400 Bad Request</h1></center><hr><center>nginx/1.24.0</center></body></html>\r\n";
+
+const char *MENSAJES[] = {"🚀 CONEXION ESTABLECIDA", "🛡️ CIFRADO MILITAR ACTIVO", "Pfsense", "OPNsense", "VyOS", "Claro", "Altice", "🌐 BYPASS OK"};
 #define NUM_MENSAJES (sizeof(MENSAJES) / sizeof(MENSAJES[0]))
 int mensaje_idx = 0;
 pthread_mutex_t msg_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-// --- ESTADO GLOBAL ---
 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_in addr;
-    int is_tls; // 1 = TLS (443), 0 = TCP (80)
+    struct sockaddr_storage addr; 
+    int is_tls; 
     SSL_CTX *ssl_ctx;
 } client_data_t;
 
-// --- FUNCIONES DE LOG Y CONTEXTO ---
 void write_log(const char *ip, const char *proto, const char *msg) {
     pthread_mutex_lock(&log_mutex);
     FILE *f = fopen(LOG_FILE, "a");
@@ -100,36 +69,52 @@ SSL_CTX *create_ssl_context() {
     SSL_load_error_strings();
     OpenSSL_add_ssl_algorithms();
     SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
-    if (!ctx) { perror("Error contexto SSL"); exit(1); }
-    if (SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM) <= 0 ||
-        SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM) <= 0) {
-        printf("⚠️ Sin certificados en %s. TLS fallará.\n", CERT_FILE);
-    }
+    if (!ctx) { exit(1); }
+    SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM);
+    SSL_CTX_use_PrivateKey_file(ctx, KEY_FILE, SSL_FILETYPE_PEM);
     return ctx;
 }
 
+// CREACIÓN DE SOCKET DUAL-STACK
 int create_server_socket(int port) {
-    int s_sock = socket(AF_INET, SOCK_STREAM, 0);
+    // 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));
-    struct sockaddr_in addr;
-    addr.sin_family = AF_INET;
-    addr.sin_addr.s_addr = INADDR_ANY;
-    addr.sin_port = htons(port);
+
+    // 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;
+    addr.sin6_addr = in6addr_any;
+    addr.sin6_port = htons(port);
+
     if (bind(s_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) return -1;
     listen(s_sock, 600);
     return s_sock;
 }
 
-// --- HILO TRABAJADOR (TCP o TLS) ---
 void *connection_handler(void *arg) {
     client_data_t *data = (client_data_t *)arg;
     int client_sock = data->client_fd;
     int is_tls = data->is_tls;
     SSL_CTX *ctx = data->ssl_ctx;
     
-    char client_ip[INET_ADDRSTRLEN];
-    inet_ntop(AF_INET, &(data->addr.sin_addr), client_ip, INET_ADDRSTRLEN);
+    // 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
+        struct sockaddr_in6 *s = (struct sockaddr_in6 *)&data->addr;
+        inet_ntop(AF_INET6, &s->sin6_addr, client_ip, sizeof(client_ip));
+    }
     free(data);
 
     const char *proto_name = is_tls ? "TLS" : "TCP";
@@ -149,65 +134,39 @@ void *connection_handler(void *arg) {
     setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
     
     char buffer[BUFLEN];
-    int bytes_read = 0;
-    if (is_tls) bytes_read = SSL_read(ssl, buffer, sizeof(buffer)-1);
-    else bytes_read = recv(client_sock, buffer, sizeof(buffer)-1, 0);
+    int bytes_read = is_tls ? SSL_read(ssl, buffer, sizeof(buffer)-1) : recv(client_sock, buffer, sizeof(buffer)-1, 0);
 
     int target_sock = -1;
     long tx_bytes = 0, rx_bytes = 0;
 
     if (bytes_read > 0) {
         buffer[bytes_read] = '\0';
-
         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) {
-            write_log(client_ip, proto_name, "❌ Error conectando a SSH");
-            goto cleanup;
-        }
+        if (connect(target_sock, (struct sockaddr *)&t_addr, sizeof(t_addr)) < 0) goto cleanup;
 
         if (strncmp(buffer, "SSH-", 4) == 0) {
-            write_log(client_ip, proto_name, "✅ Túnel SSH Directo");
             send(target_sock, buffer, bytes_read, 0);
         } else if (strstr(buffer, "HTTP/") != NULL && strstr(buffer, "Upgrade: websocket") == NULL) {
-            write_log(client_ip, proto_name, "🕵️ Escáner detectado. Enviando Fake Web.");
             if (is_tls) SSL_write(ssl, FAKE_WEB_TLS, strlen(FAKE_WEB_TLS));
             else send(client_sock, FAKE_WEB_TCP, strlen(FAKE_WEB_TCP), 0);
             goto cleanup;
         } else {
-            // --- CONSTRUCCIÓN DINÁMICA DE LA RESPUESTA HTTP 101 ---
             pthread_mutex_lock(&msg_mutex);
             const char *status_msg = MENSAJES[mensaje_idx];
             mensaje_idx = (mensaje_idx + 1) % NUM_MENSAJES;
             pthread_mutex_unlock(&msg_mutex);
 
             char response[1024];
-            if (is_tls) {
-                snprintf(response, sizeof(response),
-                    "HTTP/1.1 101 %s\r\n"
-                    "Server: nginx/1.21.0\r\n"
-                    "X-Proxy-Agent: Gemini-Ultra-Robust-V6-TLS\r\n"
-                    "Connection: Upgrade\r\n"
-                    "Upgrade: websocket\r\n\r\n", status_msg);
-            } else {
-                snprintf(response, sizeof(response),
-                    "HTTP/1.1 101 %s\r\n"
-                    "Server: nginx/1.24.0\r\n"
-                    "X-Proxy-Agent: Gemini-Ultra-Robust-V3-TCP\r\n"
-                    "Connection: Upgrade\r\n"
-                    "Upgrade: websocket\r\n\r\n", status_msg);
-            }
+            snprintf(response, sizeof(response),
+                "HTTP/1.1 101 %s\r\nServer: nginx/1.24.0\r\nX-Proxy-Agent: Gemini-Ultra-Dual\r\nConnection: Upgrade\r\nUpgrade: websocket\r\n\r\n", status_msg);
 
             if (is_tls) SSL_write(ssl, response, strlen(response));
             else send(client_sock, response, strlen(response), 0);
-
-            char log_msg[256];
-            snprintf(log_msg, sizeof(log_msg), "✅ Túnel WebSocket Inyectado: %s", status_msg);
-            write_log(client_ip, proto_name, log_msg);
         }
     } else {
         struct sockaddr_in t_addr;
@@ -215,9 +174,7 @@ void *connection_handler(void *arg) {
         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) {
-            write_log(client_ip, proto_name, "✅ Túnel Modo Silencioso");
-        } else goto cleanup;
+        if (connect(target_sock, (struct sockaddr *)&t_addr, sizeof(t_addr)) != 0) goto cleanup;
     }
 
     tv.tv_sec = 0;
@@ -225,13 +182,10 @@ void *connection_handler(void *arg) {
     int max_fd = (client_sock > target_sock) ? client_sock : target_sock;
 
     while (1) {
-        fd_set readfds;
-        FD_ZERO(&readfds);
-        FD_SET(client_sock, &readfds);
-        FD_SET(target_sock, &readfds);
+        fd_set readfds; FD_ZERO(&readfds); FD_SET(client_sock, &readfds); FD_SET(target_sock, &readfds);
         struct timeval select_tv = {300, 0};
-
         int pending = is_tls ? SSL_pending(ssl) : 0;
+        
         if (pending == 0) {
             if (select(max_fd + 1, &readfds, NULL, NULL, &select_tv) <= 0) break;
         }
@@ -242,7 +196,6 @@ void *connection_handler(void *arg) {
             send(target_sock, buffer, b, 0);
             rx_bytes += b;
         }
-
         if (FD_ISSET(target_sock, &readfds)) {
             int b = recv(target_sock, buffer, BUFLEN, 0);
             if (b <= 0) break;
@@ -252,105 +205,55 @@ void *connection_handler(void *arg) {
         }
     }
 
-cleanup: ; // <-- AQUÍ ESTÁ LA MAGIA QUE SOLUCIONA TU ERROR (El punto y coma vacío)
-    double total_mb = (double)(tx_bytes + rx_bytes) / (1024.0 * 1024.0);
-    if (total_mb > 0.05) {
-        char stat_msg[128];
-        snprintf(stat_msg, sizeof(stat_msg), "[*] Tráfico final: %.2f MB", total_mb);
-        write_log(client_ip, proto_name, stat_msg);
-    }
-
+cleanup:
     if (target_sock != -1) close(target_sock);
     if (is_tls) { SSL_shutdown(ssl); SSL_free(ssl); }
     close(client_sock);
-
     pthread_mutex_lock(&conn_mutex); active_connections--; pthread_mutex_unlock(&conn_mutex);
     pthread_exit(NULL);
 }
 
-// --- HILO MAESTRO ---
 int main(int argc, char **argv) {
-    int port_tcp = DEFAULT_PORT_TCP;
-    int port_tls = DEFAULT_PORT_TLS;
-
-    if (argc >= 3) {
-        port_tcp = atoi(argv[1]);
-        port_tls = atoi(argv[2]);
-    }
+    int port_tcp = DEFAULT_PORT_TCP, port_tls = DEFAULT_PORT_TLS;
+    if (argc >= 3) { port_tcp = atoi(argv[1]); port_tls = atoi(argv[2]); }
 
     signal(SIGPIPE, SIG_IGN); 
-
     SSL_CTX *ctx = create_ssl_context();
     int server_tcp = create_server_socket(port_tcp);
     int server_tls = create_server_socket(port_tls);
 
-    if (server_tcp < 0 || server_tls < 0) {
-        printf("Error iniciando sockets. ¿Tienes permisos root para puertos bajos?\n");
-        exit(1);
-    }
+    if (server_tcp < 0 || server_tls < 0) exit(1);
 
-    write_log(NULL, "SISTEMA", "=====================================================");
-    char msg[256];
-    write_log(NULL, "SISTEMA", "🚀 PROXY DUAL ENTERPRISE NATIVO INICIADO");
-    snprintf(msg, sizeof(msg), "🌐 TCP escuchando en puerto: %d", port_tcp);
-    write_log(NULL, "TCP", msg);
-    snprintf(msg, sizeof(msg), "🔒 TLS escuchando en puerto: %d", port_tls);
-    write_log(NULL, "TLS", msg);
-    write_log(NULL, "SISTEMA", "🛡️  Doble Fake Web | Mensajes Dinámicos | Multi-hilo");
-    write_log(NULL, "SISTEMA", "=====================================================");
+    write_log(NULL, "SISTEMA", "🚀 PROXY DUAL ENTERPRISE INICIADO (Soporte IPv4 + IPv6)");
 
     int max_server_fd = (server_tcp > server_tls) ? server_tcp : server_tls;
 
     while (1) {
-        fd_set master_fds;
-        FD_ZERO(&master_fds);
-        FD_SET(server_tcp, &master_fds);
-        FD_SET(server_tls, &master_fds);
-
+        fd_set master_fds; FD_ZERO(&master_fds); FD_SET(server_tcp, &master_fds); FD_SET(server_tls, &master_fds);
         if (select(max_server_fd + 1, &master_fds, NULL, NULL, NULL) < 0) continue;
 
-        int active_sock = -1;
-        int is_tls = 0;
-
-        if (FD_ISSET(server_tcp, &master_fds)) {
-            active_sock = server_tcp; is_tls = 0;
-        } else if (FD_ISSET(server_tls, &master_fds)) {
-            active_sock = server_tls; is_tls = 1;
-        }
+        int active_sock = -1, is_tls = 0;
+        if (FD_ISSET(server_tcp, &master_fds)) { active_sock = server_tcp; is_tls = 0; }
+        else if (FD_ISSET(server_tls, &master_fds)) { active_sock = server_tls; is_tls = 1; }
 
-        struct sockaddr_in c_addr;
+        struct sockaddr_storage c_addr;
         socklen_t c_len = sizeof(c_addr);
         int client_sock = accept(active_sock, (struct sockaddr *)&c_addr, &c_len);
         if (client_sock < 0) continue;
 
         pthread_mutex_lock(&conn_mutex);
-        if (active_connections >= MAX_CONNECTIONS) {
-            pthread_mutex_unlock(&conn_mutex);
-            close(client_sock); continue;
-        }
-        active_connections++;
-        pthread_mutex_unlock(&conn_mutex);
+        if (active_connections >= MAX_CONNECTIONS) { pthread_mutex_unlock(&conn_mutex); close(client_sock); continue; }
+        active_connections++; pthread_mutex_unlock(&conn_mutex);
 
         client_data_t *d = malloc(sizeof(client_data_t));
-        d->client_fd = client_sock;
-        d->addr = c_addr;
-        d->is_tls = is_tls;
-        d->ssl_ctx = ctx;
-
-        pthread_t tid;
-        pthread_attr_t attr;
-        pthread_attr_init(&attr);
-        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-        
+        d->client_fd = client_sock; d->addr = c_addr; d->is_tls = is_tls; d->ssl_ctx = ctx;
+
+        pthread_t tid; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
         if (pthread_create(&tid, &attr, connection_handler, d) != 0) {
             close(client_sock); free(d);
             pthread_mutex_lock(&conn_mutex); active_connections--; pthread_mutex_unlock(&conn_mutex);
         }
         pthread_attr_destroy(&attr);
     }
-
-    close(server_tcp);
-    close(server_tls);
-    SSL_CTX_free(ctx);
     return 0;
 }