Przeglądaj źródła

Añadir 'C/proxy.c'

```

### Un detalle técnico brillante (Anti-Crash nativo)
Si te fijas en la línea 127 del código, añadí `signal(SIGPIPE, SIG_IGN);`. En C puro, si el cliente (tu NetMod) cierra la conexión de golpe justo cuando el servidor le está enviando datos, el sistema operativo le envía una "señal de muerte" (`SIGPIPE`) al servidor, apagándolo instantáneamente. Al ignorar esa señal, hacemos que el servidor sea "a prueba de balas" frente a caídas de red bruscas.

### Para compilarlo y probarlo en tu VPS
Al no usar OpenSSL en esta versión, la compilación es aún más sencilla y directa.

1. Guarda el código: `nano /root/proxy_v3_nativo.c`
2. Compílalo:
   ```bash
   gcc -O3 -o /root/proxy_v3 /root/proxy_v3_nativo.c -lpthread
   ```
3. Detén cualquier servicio previo que use tu puerto y ejecútalo:
   ```bash
   /root/proxy_v3 8080
yosoyhendrix 2 dni temu
rodzic
commit
a7406434bc
1 zmienionych plików z 232 dodań i 0 usunięć
  1. 232 0
      C/proxy.c

+ 232 - 0
C/proxy.c

@@ -0,0 +1,232 @@
+/*
+ * =====================================================================================
+ * PROXY MULTIFILAMENTADO PROFESIONAL - VERSIÓN 3 (NATIVO EN C)
+ * Compilación en Ubuntu: gcc -O3 -o proxy_v3 proxy_v3_nativo.c -lpthread
+ * =====================================================================================
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <pthread.h>
+#include <signal.h>
+#include <time.h>
+
+// --- CONFIGURACIÓN BASE ---
+#define DEFAULT_PORT 8080 // Puedes cambiarlo al ejecutar
+#define SSH_HOST "127.0.0.1"
+#define SSH_PORT 22
+#define BUFLEN 16384
+#define MAX_CONNECTIONS 300
+
+// --- FAKE WEB ROBUSTA (Réplica exacta de Nginx 1.24) ---
+const char *FAKE_WEB_RESPONSE = 
+    "HTTP/1.1 400 Bad Request\r\n"
+    "Server: nginx/1.24.0\r\n"
+    "Content-Type: text/html\r\n"
+    "Content-Length: 157\r\n"
+    "Connection: close\r\n\r\n"
+    "<html>\r\n<head><title>400 Bad Request</title></head>\r\n"
+    "<body>\r\n<center><h1>400 Bad Request</h1></center>\r\n"
+    "<hr><center>nginx/1.24.0</center>\r\n</body>\r\n</html>\r\n";
+
+// --- RESPUESTA DE CONEXIÓN ACEPTADA (Con tu Agent) ---
+const char *HTTP_101_RESPONSE = 
+    "HTTP/1.1 101 Switching Protocols\r\n"
+    "Server: nginx/1.24.0\r\n"
+    "Upgrade: websocket\r\n"
+    "Connection: Upgrade\r\n"
+    "X-Proxy-Agent: Gemini-Ultra-Robust-v3\r\n\r\n";
+
+// Variables globales de estado
+int active_connections = 0;
+pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// Estructura para pasar datos al hilo
+typedef struct {
+    int client_fd;
+    struct sockaddr_in addr;
+} client_data_t;
+
+// Imprimir logs en pantalla
+void log_msg(const char *ip, const char *msg) {
+    time_t now = time(NULL);
+    struct tm *t = localtime(&now);
+    char time_str[64];
+    strftime(time_str, sizeof(time_str), "%H:%M:%S", t);
+    printf("[%s] [%s] %s\n", time_str, ip ? ip : "SISTEMA", msg);
+}
+
+// Hilo de manejo de conexión
+void *connection_handler(void *arg) {
+    client_data_t *data = (client_data_t *)arg;
+    int client_sock = data->client_fd;
+    
+    char client_ip[INET_ADDRSTRLEN];
+    inet_ntop(AF_INET, &(data->addr.sin_addr), client_ip, INET_ADDRSTRLEN);
+    free(data); // Liberar memoria del argumento
+
+    // Timeout inicial para leer la petición
+    struct timeval tv;
+    tv.tv_sec = 3; tv.tv_usec = 0;
+    setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
+
+    char buffer[BUFLEN];
+    int bytes_read = recv(client_sock, buffer, sizeof(buffer) - 1, 0);
+    int target_sock = -1;
+
+    if (bytes_read > 0) {
+        buffer[bytes_read] = '\0';
+
+        // Conectar al destino (SSH Local)
+        struct sockaddr_in target_addr;
+        target_sock = socket(AF_INET, SOCK_STREAM, 0);
+        target_addr.sin_family = AF_INET;
+        target_addr.sin_port = htons(SSH_PORT);
+        inet_pton(AF_INET, SSH_HOST, &target_addr.sin_addr);
+
+        if (connect(target_sock, (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0) {
+            log_msg(client_ip, "❌ Error destino SSH");
+            goto cleanup;
+        }
+
+        // Lógica de ruteo y Fake Web
+        if (strncmp(buffer, "SSH-", 4) == 0) {
+            log_msg(client_ip, "✅ Túnel Directo SSH");
+            send(target_sock, buffer, bytes_read, 0);
+        } else if (strstr(buffer, "HTTP/") != NULL && strstr(buffer, "Upgrade: websocket") == NULL) {
+            log_msg(client_ip, "🕵️ Escáner detectado. Enviando Nginx Fake Web (400).");
+            send(client_sock, FAKE_WEB_RESPONSE, strlen(FAKE_WEB_RESPONSE), 0);
+            goto cleanup;
+        } else {
+            // Es NetMod / Inyector HTTP
+            log_msg(client_ip, "✅ Túnel WebSocket Inyectado (V3)");
+            send(client_sock, HTTP_101_RESPONSE, strlen(HTTP_101_RESPONSE), 0);
+            // Si hay datos extra (payload SSH adelantado), reenviarlo
+            char *headers_end = strstr(buffer, "\r\n\r\n");
+            if (headers_end) {
+                int header_len = (headers_end - buffer) + 4;
+                if (bytes_read > header_len) {
+                    send(target_sock, buffer + header_len, bytes_read - header_len, 0);
+                }
+            }
+        }
+    } else {
+        goto cleanup; // Conexión vacía o timeout
+    }
+
+    // --- BUCLE SELECT (EL PUENTE DE DATOS) ---
+    tv.tv_sec = 0; // Quitar timeout
+    setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
+    
+    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);
+
+        // Timeout de inactividad de 5 minutos
+        struct timeval select_tv = {300, 0}; 
+
+        int activity = select(max_fd + 1, &readfds, NULL, NULL, &select_tv);
+        if (activity <= 0) break; // Cierre por timeout o error
+
+        // Del Cliente al SSH
+        if (FD_ISSET(client_sock, &readfds)) {
+            int bytes = recv(client_sock, buffer, sizeof(buffer), 0);
+            if (bytes <= 0) break;
+            if (send(target_sock, buffer, bytes, 0) <= 0) break;
+        }
+
+        // Del SSH al Cliente
+        if (FD_ISSET(target_sock, &readfds)) {
+            int bytes = recv(target_sock, buffer, sizeof(buffer), 0);
+            if (bytes <= 0) break;
+            if (send(client_sock, buffer, bytes, 0) <= 0) break;
+        }
+    }
+
+cleanup:
+    if (target_sock != -1) close(target_sock);
+    close(client_sock);
+
+    pthread_mutex_lock(&conn_mutex);
+    active_connections--;
+    pthread_mutex_unlock(&conn_mutex);
+
+    pthread_exit(NULL);
+}
+
+int main(int argc, char **argv) {
+    int port = DEFAULT_PORT;
+    if (argc > 1) port = atoi(argv[1]);
+
+    // Ignorar SIGPIPE (Vital en C: evita que el servidor crashee si un cliente corta de golpe)
+    signal(SIGPIPE, SIG_IGN);
+
+    int server_sock = socket(AF_INET, SOCK_STREAM, 0);
+    int opt = 1;
+    setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+
+    struct sockaddr_in server_addr;
+    server_addr.sin_family = AF_INET;
+    server_addr.sin_addr.s_addr = INADDR_ANY;
+    server_addr.sin_port = htons(port);
+
+    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
+        perror("Fallo en bind");
+        exit(EXIT_FAILURE);
+    }
+
+    if (listen(server_sock, 500) < 0) {
+        perror("Fallo en listen");
+        exit(EXIT_FAILURE);
+    }
+
+    printf("=====================================================\n");
+    printf("🚀 PROXY NATIVO V3 (TCP) INICIADO - PUERTO %d\n", port);
+    printf("🛡️  Fake Web: Nginx 1.24 | Agent: Gemini-Ultra-Robust-v3\n");
+    printf("=====================================================\n");
+
+    while (1) {
+        struct sockaddr_in client_addr;
+        socklen_t addr_len = sizeof(client_addr);
+        int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_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);
+
+        client_data_t *data = malloc(sizeof(client_data_t));
+        data->client_fd = client_sock;
+        data->addr = client_addr;
+
+        pthread_t thread_id;
+        pthread_attr_t attr;
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+        
+        if (pthread_create(&thread_id, &attr, connection_handler, (void *)data) != 0) {
+            close(client_sock);
+            free(data);
+            pthread_mutex_lock(&conn_mutex); active_connections--; pthread_mutex_unlock(&conn_mutex);
+        }
+        pthread_attr_destroy(&attr);
+    }
+
+    close(server_sock);
+    return 0;
+}