| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*
- * =====================================================================================
- * PROXY VPN DUAL (TCP + TLS) - GRADO ENTERPRISE NATIVO EN C
- * 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
- * =====================================================================================
- */
- #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>
- #include <openssl/ssl.h>
- #include <openssl/err.h>
- // --- CONFIGURACIÓN BASE ---
- #define DEFAULT_PORT_TCP 80
- #define DEFAULT_PORT_TLS 443
- #define SSH_HOST "127.0.0.1"
- #define SSH_PORT 22
- #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"
- 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;
- 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;
- int is_tls;
- SSL_CTX *ssl_ctx;
- } client_data_t;
- void write_log(const char *ip, const char *proto, 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);
- fprintf(f, "[%s] [%s] [%s] %s\n", ts, proto, ip ? ip : "SISTEMA", msg);
- printf("[%s] [%s] [%s] %s\n", ts, proto, ip ? ip : "SISTEMA", msg);
- fclose(f);
- }
- pthread_mutex_unlock(&log_mutex);
- }
- 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); }
- 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) {
- // 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;
- 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;
- }
- 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;
-
- // 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";
- SSL *ssl = NULL;
- if (is_tls) {
- ssl = SSL_new(ctx);
- SSL_set_fd(ssl, client_sock);
- if (SSL_accept(ssl) <= 0) {
- SSL_free(ssl); close(client_sock);
- pthread_mutex_lock(&conn_mutex); active_connections--; pthread_mutex_unlock(&conn_mutex);
- pthread_exit(NULL);
- }
- }
- struct timeval tv = {3, 0};
- setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
-
- char buffer[BUFLEN];
- 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) goto cleanup;
- if (strncmp(buffer, "SSH-", 4) == 0) {
- send(target_sock, buffer, bytes_read, 0);
- } else if (strstr(buffer, "HTTP/") != NULL && strstr(buffer, "Upgrade: websocket") == NULL) {
- 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 {
- 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];
- 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);
- }
- } else {
- 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;
- }
- 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 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;
- }
- if (pending > 0 || FD_ISSET(client_sock, &readfds)) {
- int b = is_tls ? SSL_read(ssl, buffer, BUFLEN) : recv(client_sock, buffer, BUFLEN, 0);
- if (b <= 0) break;
- 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;
- if (is_tls) SSL_write(ssl, buffer, b);
- else send(client_sock, buffer, b, 0);
- tx_bytes += b;
- }
- }
- 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);
- }
- 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]); }
- 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) exit(1);
- 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);
- if (select(max_server_fd + 1, &master_fds, NULL, NULL, NULL) < 0) continue;
- 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_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);
- 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);
- 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);
- }
- return 0;
- }
|