|
|
@@ -1,7 +1,7 @@
|
|
|
/*
|
|
|
* =====================================================================================
|
|
|
* PROXY VPN DUAL (TCP + TLS) - GRADO ENTERPRISE NATIVO EN C
|
|
|
- * Mejoras: Soporte DUAL-STACK (IPv4 e IPv6 simultáneo en el mismo puerto).
|
|
|
+ * Mejoras: Soporte DUAL-STACK (IPv4/IPv6) + Fix de Timeout OpenSSL para NetMod
|
|
|
* Compilación: gcc -O3 -o proxy_dual proxy_dual.c -lssl -lcrypto -lpthread
|
|
|
* =====================================================================================
|
|
|
*/
|
|
|
@@ -42,7 +42,6 @@ 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;
|
|
|
@@ -75,20 +74,14 @@ SSL_CTX *create_ssl_context() {
|
|
|
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;
|
|
|
@@ -106,12 +99,11 @@ void *connection_handler(void *arg) {
|
|
|
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
|
|
|
+ } else {
|
|
|
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&data->addr;
|
|
|
inet_ntop(AF_INET6, &s->sin6_addr, client_ip, sizeof(client_ip));
|
|
|
}
|
|
|
@@ -130,11 +122,23 @@ void *connection_handler(void *arg) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- struct timeval tv = {3, 0};
|
|
|
- setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
|
|
|
-
|
|
|
+ // --- 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
|
|
|
+
|
|
|
char buffer[BUFLEN];
|
|
|
- int bytes_read = is_tls ? SSL_read(ssl, buffer, sizeof(buffer)-1) : recv(client_sock, buffer, sizeof(buffer)-1, 0);
|
|
|
+ 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;
|
|
|
@@ -169,16 +173,17 @@ void *connection_handler(void *arg) {
|
|
|
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");
|
|
|
}
|
|
|
|
|
|
- tv.tv_sec = 0;
|
|
|
- setsockopt(client_sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
|
|
|
+ // El túnel bidireccional se mantiene intacto
|
|
|
int max_fd = (client_sock > target_sock) ? client_sock : target_sock;
|
|
|
|
|
|
while (1) {
|
|
|
@@ -224,7 +229,7 @@ int main(int argc, char **argv) {
|
|
|
|
|
|
if (server_tcp < 0 || server_tls < 0) exit(1);
|
|
|
|
|
|
- write_log(NULL, "SISTEMA", "🚀 PROXY DUAL ENTERPRISE INICIADO (Soporte IPv4 + IPv6)");
|
|
|
+ write_log(NULL, "SISTEMA", "🚀 PROXY DUAL ENTERPRISE INICIADO (Fix NetMod TLS)");
|
|
|
|
|
|
int max_server_fd = (server_tcp > server_tls) ? server_tcp : server_tls;
|
|
|
|