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

Actualizar 'C/proxy_dual.c'

¿Qué recuperamos exactamente?
La Base de Datos de Baneo en RAM (ip_database): He creado una estructura nativa en C que rastrea las conexiones de hasta 200 IPs sospechosas. Si alguien intenta bombardear tu servidor (más de 3 conexiones en menos de 1 segundo), la IP queda guardada en la RAM y se rechaza automáticamente todo su tráfico durante 1 hora.

Los Encabezados Expandidos: Dentro del bloque donde se construye la respuesta HTTP 101, restauré todos tus Headers originales: X-Forwarded-For, Cache-Control, Proxy-Connection, etc. Esto fortalece el camuflaje ante el DPI.

El Log de Seguridad: Si alguien es baneado, verás en tu archivo /root/proxy-dual.log el mensaje: ⛔ IP Baneada (Flood/Spam detectado).
gcc -O3 -o proxy_dual proxy_dual.c -lssl -lcrypto -lpthread

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"
yosoyhendrix 1 день назад
Родитель
Сommit
d23a895036
1 измененных файлов с 97 добавлено и 24 удалено
  1. 97 24
      C/proxy_dual.c

+ 97 - 24
C/proxy_dual.c

@@ -1,7 +1,7 @@
 /*
  * =====================================================================================
- * PROXY VPN DUAL (TCP + TLS) - GRADO ENTERPRISE NATIVO EN C
- * Mejoras: Soporte DUAL-STACK (IPv4/IPv6) + Fix de Timeout OpenSSL para NetMod
+ * PROXY VPN DUAL (TCP + TLS) - ULTIMATE BARE-METAL EDITION
+ * Características: Dual-Stack, Mensajes Rotativos, Anti-Flood, Auto-Ban en RAM.
  * Compilación: gcc -O3 -o proxy_dual proxy_dual.c -lssl -lcrypto -lpthread
  * =====================================================================================
  */
@@ -30,10 +30,28 @@
 #define CERT_FILE "/root/cert.pem"
 #define KEY_FILE "/root/key.pem"
 
+// --- CONFIGURACIÓN DE SEGURIDAD (ANTI-FLOOD & BAN) ---
+#define MAX_TRACKED_IPS 200
+#define AUTO_BAN_STRIKES 3
+#define BAN_TIME 3600 // 1 Hora
+#define COOLDOWN_SEC 1 // 1 Segundo de enfriamiento
+
+typedef struct {
+    char ip[INET6_ADDRSTRLEN];
+    time_t last_connect;
+    int strikes;
+    time_t ban_until;
+} ip_record_t;
+
+ip_record_t ip_database[MAX_TRACKED_IPS];
+pthread_mutex_t ip_db_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+// --- RESPUESTAS FAKE WEB ---
 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 OK\r\nServer: nginx/1.21.0\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n<html><body><center><h1>400 Bad Request</h1></center></body></html>\r\n";
 
-const char *MENSAJES[] = {"🚀 CONEXION ESTABLECIDA", "🛡️ CIFRADO MILITAR ACTIVO", "Pfsense", "OPNsense", "VyOS", "Claro", "Altice", "🌐 BYPASS OK"};
+// --- MENSAJES ROTATIVOS ---
+const char *MENSAJES[] = {"🚀 CONEXION ESTABLECIDA", "🛡️ CIFRADO MILITAR ACTIVO", "🔋 MODO SIGILO SSL OK", "Pfsense", "OPNsense", "VyOS", "Claro", "Google", "TNSR", "🌐 BYPASS OK"};
 #define NUM_MENSAJES (sizeof(MENSAJES) / sizeof(MENSAJES[0]))
 int mensaje_idx = 0;
 pthread_mutex_t msg_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -49,6 +67,7 @@ typedef struct {
     SSL_CTX *ssl_ctx;
 } client_data_t;
 
+// --- FUNCIONES DE SOPORTE ---
 void write_log(const char *ip, const char *proto, const char *msg) {
     pthread_mutex_lock(&log_mutex);
     FILE *f = fopen(LOG_FILE, "a");
@@ -64,11 +83,51 @@ void write_log(const char *ip, const char *proto, const char *msg) {
     pthread_mutex_unlock(&log_mutex);
 }
 
+// --- MOTOR DE SEGURIDAD (Devuelve 1 si OK, 0 si BANEADO, -1 si NUEVO BANEO) ---
+int check_and_update_ip(const char *ip) {
+    pthread_mutex_lock(&ip_db_mutex);
+    time_t now = time(NULL);
+    int empty_slot = -1;
+    int found = 0;
+
+    for (int i = 0; i < MAX_TRACKED_IPS; i++) {
+        if (ip_database[i].ip[0] == '\0' && empty_slot == -1) empty_slot = i;
+        else if (strcmp(ip_database[i].ip, ip) == 0) {
+            found = 1;
+            if (ip_database[i].ban_until > now) {
+                pthread_mutex_unlock(&ip_db_mutex);
+                return 0; // Sigue baneado
+            }
+            if (now - ip_database[i].last_connect <= COOLDOWN_SEC) {
+                ip_database[i].strikes++;
+                ip_database[i].last_connect = now;
+                if (ip_database[i].strikes >= AUTO_BAN_STRIKES) {
+                    ip_database[i].ban_until = now + BAN_TIME;
+                    pthread_mutex_unlock(&ip_db_mutex);
+                    return -1; // Acaba de ser baneado
+                }
+            } else {
+                ip_database[i].strikes = 0;
+                ip_database[i].last_connect = now;
+            }
+            break;
+        }
+    }
+    if (!found && empty_slot != -1) {
+        strcpy(ip_database[empty_slot].ip, ip);
+        ip_database[empty_slot].last_connect = now;
+        ip_database[empty_slot].strikes = 0;
+        ip_database[empty_slot].ban_until = 0;
+    }
+    pthread_mutex_unlock(&ip_db_mutex);
+    return 1;
+}
+
 SSL_CTX *create_ssl_context() {
     SSL_load_error_strings();
     OpenSSL_add_ssl_algorithms();
     SSL_CTX *ctx = SSL_CTX_new(TLS_server_method());
-    if (!ctx) { exit(1); }
+    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;
@@ -77,10 +136,8 @@ SSL_CTX *create_ssl_context() {
 int create_server_socket(int port) {
     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));
-    int no = 0;
-    setsockopt(s_sock, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
+    int opt = 1; setsockopt(s_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+    int no = 0; setsockopt(s_sock, IPPROTO_IPV6, IPV6_V6ONLY, &no, sizeof(no));
 
     struct sockaddr_in6 addr;
     memset(&addr, 0, sizeof(addr));
@@ -110,8 +167,21 @@ void *connection_handler(void *arg) {
     free(data);
 
     const char *proto_name = is_tls ? "TLS" : "TCP";
-    SSL *ssl = NULL;
 
+    // --- FILTRO DE SEGURIDAD ---
+    int sec_status = check_and_update_ip(client_ip);
+    if (sec_status == 0) {
+        close(client_sock);
+        pthread_mutex_lock(&conn_mutex); active_connections--; pthread_mutex_unlock(&conn_mutex);
+        pthread_exit(NULL);
+    } else if (sec_status == -1) {
+        write_log(client_ip, proto_name, "⛔ IP Baneada (Flood/Spam detectado)");
+        close(client_sock);
+        pthread_mutex_lock(&conn_mutex); active_connections--; pthread_mutex_unlock(&conn_mutex);
+        pthread_exit(NULL);
+    }
+
+    SSL *ssl = NULL;
     if (is_tls) {
         ssl = SSL_new(ctx);
         SSL_set_fd(ssl, client_sock);
@@ -122,23 +192,15 @@ void *connection_handler(void *arg) {
         }
     }
 
-    // --- 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
-
+    fd_set init_fds; FD_ZERO(&init_fds); FD_SET(client_sock, &init_fds);
+    struct timeval init_tv = {3, 0}; 
     char buffer[BUFLEN];
     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;
@@ -156,10 +218,12 @@ void *connection_handler(void *arg) {
         if (strncmp(buffer, "SSH-", 4) == 0) {
             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. Fake Web (400 OK).");
             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 {
+            // --- ENCABEZADOS EXTENDIDOS RECUPERADOS ---
             pthread_mutex_lock(&msg_mutex);
             const char *status_msg = MENSAJES[mensaje_idx];
             mensaje_idx = (mensaje_idx + 1) % NUM_MENSAJES;
@@ -167,23 +231,28 @@ void *connection_handler(void *arg) {
 
             char response[1024];
             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);
+                "HTTP/1.1 101 %s\r\n"
+                "Server: nginx/1.24.0\r\n"
+                "X-Forwarded-For: 127.0.0.1\r\n"
+                "Content-Type: text/html; charset=UTF-8\r\n"
+                "Proxy-Connection: keep-alive\r\n"
+                "Cache-Control: no-cache\r\n"
+                "X-Proxy-Agent: Gemini-Ultra-Dual-C\r\n"
+                "Connection: Upgrade\r\n"
+                "Upgrade: websocket\r\n\r\n", status_msg);
 
             if (is_tls) SSL_write(ssl, response, strlen(response));
             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");
     }
 
-    // El túnel bidireccional se mantiene intacto
     int max_fd = (client_sock > target_sock) ? client_sock : target_sock;
 
     while (1) {
@@ -222,6 +291,9 @@ int main(int argc, char **argv) {
     int port_tcp = DEFAULT_PORT_TCP, port_tls = DEFAULT_PORT_TLS;
     if (argc >= 3) { port_tcp = atoi(argv[1]); port_tls = atoi(argv[2]); }
 
+    // Limpiar base de datos de IPs al inicio
+    memset(ip_database, 0, sizeof(ip_database));
+
     signal(SIGPIPE, SIG_IGN); 
     SSL_CTX *ctx = create_ssl_context();
     int server_tcp = create_server_socket(port_tcp);
@@ -229,7 +301,8 @@ int main(int argc, char **argv) {
 
     if (server_tcp < 0 || server_tls < 0) exit(1);
 
-    write_log(NULL, "SISTEMA", "🚀 PROXY DUAL ENTERPRISE INICIADO (Fix NetMod TLS)");
+    write_log(NULL, "SISTEMA", "🚀 PROXY DUAL BARE-METAL INICIADO (Ultimate Edition)");
+    write_log(NULL, "SISTEMA", "🛡️  Módulos cargados: Anti-Flood, Auto-Ban, IPv4/IPv6, Full Headers");
 
     int max_server_fd = (server_tcp > server_tls) ? server_tcp : server_tls;