/* * ===================================================================================== * PROXY MULTIFILAMENTADO PROFESIONAL - VERSIÓN 3 (NATIVO EN C) * Mejoras: Registro de Logs detallados y Monitoreo de tráfico. * Compilación: gcc -O3 -o proxy_v3 proxy_v3_nativo.c -lpthread * ===================================================================================== */ #include #include #include #include #include #include #include #include #include #include #include // --- CONFIGURACIÓN BASE --- #define DEFAULT_PORT 8080 #define SSH_HOST "127.0.0.1" #define SSH_PORT 22 #define BUFLEN 16384 #define MAX_CONNECTIONS 300 #define LOG_FILE "/root/proxy-v3.log" // --- FAKE WEB ROBUSTA (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" "\r\n400 Bad Request\r\n" "\r\n

400 Bad Request

\r\n" "
nginx/1.24.0
\r\n\r\n\r\n"; 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"; // Mutexes para sincronización pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t conn_mutex = PTHREAD_MUTEX_INITIALIZER; int active_connections = 0; typedef struct { int client_fd; struct sockaddr_in addr; } client_data_t; // --- FUNCIÓN DE LOGS (ESTILO V6 TLS) --- void write_log(const char *ip, const char *msg) { pthread_mutex_lock(&log_mutex); FILE *f = fopen(LOG_FILE, "a"); if (f) { time_t now = time(NULL); struct tm *t = localtime(&now); char ts[64]; strftime(ts, sizeof(ts), "%Y-%m-%d %H:%M:%S", t); if (ip) { fprintf(f, "[%s] [%s] %s\n", ts, ip, msg); printf("[%s] [%s] %s\n", ts, ip, msg); } else { fprintf(f, "[%s] %s\n", ts, msg); printf("[%s] %s\n", ts, msg); } fclose(f); } pthread_mutex_unlock(&log_mutex); } // --- MANEJADOR 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); 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; long tx_bytes = 0, rx_bytes = 0; if (bytes_read > 0) { buffer[bytes_read] = '\0'; // Conectar a SSH local 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, "❌ Error: No se pudo conectar al SSH local"); goto cleanup; } if (strncmp(buffer, "SSH-", 4) == 0) { write_log(client_ip, "✅ Túnel cifrado (Modo SSH Directo)"); send(target_sock, buffer, bytes_read, 0); rx_bytes += bytes_read; } else if (strstr(buffer, "HTTP/") != NULL && strstr(buffer, "Upgrade: websocket") == NULL) { write_log(client_ip, "🕵️ Escáner detectado. Respondiendo 400 Bad Request Fake Web."); send(client_sock, FAKE_WEB_RESPONSE, strlen(FAKE_WEB_RESPONSE), 0); goto cleanup; } else { write_log(client_ip, "✅ Túnel cifrado (Modo WebSocket HTTP): Gemini-V3"); send(client_sock, HTTP_101_RESPONSE, strlen(HTTP_101_RESPONSE), 0); tx_bytes += strlen(HTTP_101_RESPONSE); char *h_end = strstr(buffer, "\r\n\r\n"); if (h_end) { int h_len = (h_end - buffer) + 4; if (bytes_read > h_len) { send(target_sock, buffer + h_len, bytes_read - h_len, 0); rx_bytes += (bytes_read - h_len); } } } } else { // Posible Stunnel o NetMod Silencioso 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, "✅ Túnel cifrado (Modo Stunnel Silencioso)"); } else { goto cleanup; } } // --- PUENTE DE DATOS --- tv.tv_sec = 0; 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 fds; FD_ZERO(&fds); FD_SET(client_sock, &fds); FD_SET(target_sock, &fds); struct timeval sel_tv = {300, 0}; if (select(max_fd + 1, &fds, NULL, NULL, &sel_tv) <= 0) break; if (FD_ISSET(client_sock, &fds)) { int b = recv(client_sock, buffer, BUFLEN, 0); if (b <= 0) break; send(target_sock, buffer, b, 0); rx_bytes += b; } if (FD_ISSET(target_sock, &fds)) { int b = recv(target_sock, buffer, BUFLEN, 0); if (b <= 0) break; send(client_sock, buffer, b, 0); tx_bytes += b; } } cleanup: // Log de tráfico final double total_mb = (double)(tx_bytes + rx_bytes) / (1024.0 * 1024.0); if (total_mb > 0.01) { char stat_msg[128]; snprintf(stat_msg, sizeof(stat_msg), "[*] Conexión finalizada. Tráfico consumido: %.2f MB", total_mb); write_log(client_ip, stat_msg); } 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]); signal(SIGPIPE, SIG_IGN); int s_sock = socket(AF_INET, SOCK_STREAM, 0); int opt = 1; setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in s_addr; s_addr.sin_family = AF_INET; s_addr.sin_addr.s_addr = INADDR_ANY; s_addr.sin_port = htons(port); if (bind(s_sock, (struct sockaddr *)&s_addr, sizeof(s_addr)) < 0) { perror("Error Bind"); exit(1); } listen(s_sock, 500); write_log(NULL, "====================================================="); char start_msg[128]; snprintf(start_msg, sizeof(start_msg), "🚀 PROXY NATIVO V3 (TCP) INICIADO - PUERTO %d", port); write_log(NULL, start_msg); write_log(NULL, "🛡️ Backlog: 500 | Fake-Web: Nginx 1.24 | Logs: ACTIVADOS"); write_log(NULL, "====================================================="); while (1) { struct sockaddr_in c_addr; socklen_t c_len = sizeof(c_addr); int c_sock = accept(s_sock, (struct sockaddr *)&c_addr, &c_len); if (c_sock < 0) continue; pthread_mutex_lock(&conn_mutex); if (active_connections >= MAX_CONNECTIONS) { pthread_mutex_unlock(&conn_mutex); close(c_sock); continue; } active_connections++; pthread_mutex_unlock(&conn_mutex); client_data_t *d = malloc(sizeof(client_data_t)); d->client_fd = c_sock; d->addr = c_addr; 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(c_sock); free(d); pthread_mutex_lock(&conn_mutex); active_connections--; pthread_mutex_unlock(&conn_mutex); } pthread_attr_destroy(&attr); } close(s_sock); return 0; }