Fix web proxy to use SSL connections for HTTPS services

- Add SSL support to web_proxy.c for connecting to wsssht daemon
- Use HTTPS for 'https' services, HTTP for 'http' services
- Try HTTPS first with HTTP fallback for 'web' services
- Accept invalid/expired certificates as requested
parent 809e083a
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#include <ctype.h> #include <ctype.h>
#include <signal.h> #include <signal.h>
#include <netdb.h> #include <netdb.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <openssl/err.h> #include <openssl/err.h>
#include "web_proxy.h" #include "web_proxy.h"
...@@ -38,26 +40,27 @@ ...@@ -38,26 +40,27 @@
#include "websocket_protocol.h" #include "websocket_protocol.h"
#include "ssl.h" #include "ssl.h"
// Service types for web proxy
typedef enum {
SERVICE_NONE = 0,
SERVICE_WEB,
SERVICE_HTTP,
SERVICE_HTTPS
} service_type_t;
// Structure to hold client and service info
typedef struct {
client_t *client;
service_type_t service_type;
char service_host[256];
int service_port;
} client_service_info_t;
// Global state for shutdown // Global state for shutdown
static int server_socket = -1; static int server_socket = -1;
static volatile int server_running = 0; static volatile int server_running = 0;
// WSSSHT process tracking
typedef struct {
char client_id[256];
char hostname[256];
pid_t pid;
int port;
time_t last_used;
bool active;
} wsssht_process_t;
#define MAX_WSSSHT_PROCESSES 50
static wsssht_process_t wsssht_processes[MAX_WSSSHT_PROCESSES];
static int wsssht_processes_count = 0;
static pthread_mutex_t wsssht_mutex = PTHREAD_MUTEX_INITIALIZER;
// Active proxy connections // Active proxy connections
#define MAX_PROXY_CONNECTIONS 100 #define MAX_PROXY_CONNECTIONS 100
typedef struct { typedef struct {
...@@ -73,34 +76,6 @@ static proxy_connection_t proxy_connections[MAX_PROXY_CONNECTIONS]; ...@@ -73,34 +76,6 @@ static proxy_connection_t proxy_connections[MAX_PROXY_CONNECTIONS];
static int proxy_connections_count = 0; static int proxy_connections_count = 0;
static pthread_mutex_t proxy_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t proxy_mutex = PTHREAD_MUTEX_INITIALIZER;
// Active tunnels to client services
#define MAX_ACTIVE_TUNNELS 50
typedef struct {
char client_id[256];
char hostname[256];
service_type_t service_type;
char service_host[256];
int service_port;
int tunnel_fd; // Socket to client's service
SSL *ssl; // SSL connection for HTTPS
time_t last_used;
time_t created_at;
bool active;
pthread_mutex_t mutex;
} service_tunnel_t;
static service_tunnel_t active_tunnels[MAX_ACTIVE_TUNNELS];
static int active_tunnels_count = 0;
static pthread_mutex_t tunnels_mutex = PTHREAD_MUTEX_INITIALIZER;
// Thread arguments structure
typedef struct {
const wssshd_config_t *config;
wssshd_state_t *state;
} proxy_thread_args_t;
// Forward declarations
static void cleanup_expired_tunnels(void);
// Cleanup thread // Cleanup thread
static volatile int cleanup_running = 0; static volatile int cleanup_running = 0;
...@@ -109,145 +84,174 @@ static void *cleanup_thread(void *arg) { ...@@ -109,145 +84,174 @@ static void *cleanup_thread(void *arg) {
cleanup_running = 1; cleanup_running = 1;
while (cleanup_running) { while (cleanup_running) {
cleanup_expired_tunnels(); sleep(60); // Check every minute
sleep(60); // Cleanup every minute
// Clean up inactive wsssht processes
time_t now = time(NULL);
pthread_mutex_lock(&wsssht_mutex);
for (int i = 0; i < wsssht_processes_count; i++) {
wsssht_process_t *proc = &wsssht_processes[i];
if (proc->active && (now - proc->last_used) > 300) { // 5 minutes
printf("[WEB-PROXY] Terminating inactive wsssht process for %s (PID: %d)\n", proc->hostname, proc->pid);
kill(proc->pid, SIGINT);
waitpid(proc->pid, NULL, 0);
proc->active = false;
}
}
pthread_mutex_unlock(&wsssht_mutex);
} }
return NULL; return NULL;
} }
// Connection handler arguments // Launch wsssht daemon and get port
typedef struct { static int launch_wsssht_daemon(const char *service, const char *client_id, const char *domain) {
int client_fd; // Check if wsssht command exists
wssshd_state_t *state; if (access("./wssshtools/wsssht", X_OK) != 0 && access("/usr/bin/wsssht", X_OK) != 0) {
const wssshd_config_t *config; printf("[WEB-PROXY] wsssht command not found\n");
} connection_handler_args_t; return -1;
}
// Forward declaration for proxy connection handler // Build command
static void *proxy_connection_handler(void *arg); char cmd[1024];
char target[512];
if (domain) {
snprintf(target, sizeof(target), "%s://%s@%s", service, client_id, domain);
} else {
snprintf(target, sizeof(target), "%s://%s", service, client_id);
}
const char *wsssht_path = "./wssshtools/wsssht";
if (access(wsssht_path, X_OK) != 0) {
wsssht_path = "wsssht";
}
snprintf(cmd, sizeof(cmd), "%s --daemon %s", wsssht_path, target);
// Launch process
FILE *fp = popen(cmd, "r");
if (!fp) {
printf("[WEB-PROXY] Failed to launch wsssht\n");
return -1;
}
// Parse service string to extract host and port // Read output to find port
static int parse_service_info(const char *service_str, char *host, size_t host_size, int *port) { char line[256];
// Service format: "web:host:port" or just "web" int port = -1;
char *colon1 = strchr(service_str, ':'); while (fgets(line, sizeof(line), fp)) {
if (!colon1) { printf("[WEB-PROXY] wsssht output: %s", line);
// No host/port specified, use defaults if (strstr(line, "Listening on port")) {
if (host) strncpy(host, "127.0.0.1", host_size); char *port_str = strstr(line, "port");
if (port) *port = 80; // Default HTTP port if (port_str) {
return 0; port_str += 4; // Skip "port"
} while (*port_str == ' ' || *port_str == '\t') port_str++;
port = atoi(port_str);
char *colon2 = strchr(colon1 + 1, ':'); break;
if (!colon2) { }
// Only host specified
size_t host_len = colon1 - service_str;
if (host_len >= host_size) host_len = host_size - 1;
if (host) {
strncpy(host, service_str, host_len);
host[host_len] = '\0';
} }
if (port) *port = 80; // Default HTTP port
return 0;
} }
// Both host and port specified pclose(fp);
size_t host_len = colon2 - colon1 - 1;
if (host_len >= host_size) host_len = host_size - 1; if (port <= 0) {
if (host) { printf("[WEB-PROXY] Failed to parse port from wsssht output\n");
strncpy(host, colon1 + 1, host_len); return -1;
host[host_len] = '\0';
} }
if (port) *port = atoi(colon2 + 1);
return 0; printf("[WEB-PROXY] wsssht daemon listening on port %d\n", port);
return port;
} }
// Find client by hostname and determine which service to use // Find or create wsssht process for hostname
static client_service_info_t *find_client_service_by_hostname(const char *hostname, wssshd_state_t *state, const wssshd_config_t *config) { static wsssht_process_t *find_or_create_wsssht_process(const char *hostname, const char *service, const char *client_id, const char *domain) {
static client_service_info_t result; pthread_mutex_lock(&wsssht_mutex);
memset(&result, 0, sizeof(result));
// Find existing process
for (int i = 0; i < wsssht_processes_count; i++) {
wsssht_process_t *proc = &wsssht_processes[i];
if (proc->active && strcmp(proc->hostname, hostname) == 0) {
proc->last_used = time(NULL);
pthread_mutex_unlock(&wsssht_mutex);
return proc;
}
}
if (!hostname || !state) return NULL; // Create new process
if (wsssht_processes_count >= MAX_WSSSHT_PROCESSES) {
pthread_mutex_unlock(&wsssht_mutex);
return NULL;
}
pthread_mutex_lock(&state->client_mutex); wsssht_process_t *proc = &wsssht_processes[wsssht_processes_count++];
strncpy(proc->client_id, client_id, sizeof(proc->client_id));
strncpy(proc->hostname, hostname, sizeof(proc->hostname));
proc->last_used = time(NULL);
proc->active = true;
for (size_t i = 0; i < state->clients_count; i++) { // Launch wsssht daemon
client_t *client = &state->clients[i]; proc->port = launch_wsssht_daemon(service, client_id, domain);
if (!client->active) continue; if (proc->port <= 0) {
proc->active = false;
wsssht_processes_count--;
pthread_mutex_unlock(&wsssht_mutex);
return NULL;
}
// Check hostname match // Fork to launch wsssht (we need to capture the PID)
int hostname_match = 0; pid_t pid = fork();
if (strcasecmp(hostname, client->client_id) == 0) { if (pid == 0) {
hostname_match = 1; // Child process - launch wsssht
} else if (config && config->domain) { char target[512];
char expected_hostname[512]; if (domain) {
snprintf(expected_hostname, sizeof(expected_hostname), "%s.%s", snprintf(target, sizeof(target), "%s://%s@%s", service, client_id, domain);
client->client_id, config->domain); } else {
if (strcasecmp(hostname, expected_hostname) == 0) { snprintf(target, sizeof(target), "%s://%s", service, client_id);
hostname_match = 1;
}
} }
if (!hostname_match) continue; const char *wsssht_path = "./wssshtools/wsssht";
if (access(wsssht_path, X_OK) != 0) {
wsssht_path = "wsssht";
}
// Parse services and find the best one (web > http > https) execl(wsssht_path, "wsssht", "--daemon", target, NULL);
char *services_copy = strdup(client->services); exit(1); // Should not reach here
if (!services_copy) continue; } else if (pid > 0) {
proc->pid = pid;
printf("[WEB-PROXY] Launched wsssht daemon for %s (PID: %d, Port: %d)\n", hostname, pid, proc->port);
} else {
proc->active = false;
wsssht_processes_count--;
pthread_mutex_unlock(&wsssht_mutex);
return NULL;
}
char *service_token = strtok(services_copy, ","); pthread_mutex_unlock(&wsssht_mutex);
service_type_t best_service = SERVICE_NONE; return proc;
char best_host[256] = "127.0.0.1"; }
int best_port = 80;
while (service_token) { // Thread arguments structure
// Trim whitespace typedef struct {
while (*service_token == ' ' || *service_token == '\t') service_token++; const wssshd_config_t *config;
char *end = service_token + strlen(service_token) - 1; wssshd_state_t *state;
while (end > service_token && (*end == ' ' || *end == '\t')) { } proxy_thread_args_t;
*end = '\0';
end--;
}
service_type_t current_type = SERVICE_NONE;
if (strncmp(service_token, "web", 3) == 0) {
current_type = SERVICE_WEB;
} else if (strncmp(service_token, "http", 4) == 0) {
current_type = SERVICE_HTTP;
} else if (strncmp(service_token, "https", 5) == 0) {
current_type = SERVICE_HTTPS;
}
if (current_type != SERVICE_NONE) {
// Check if this is better than current best
if (best_service == SERVICE_NONE ||
(current_type == SERVICE_WEB) ||
(current_type == SERVICE_HTTP && best_service != SERVICE_WEB) ||
(current_type == SERVICE_HTTPS && best_service != SERVICE_WEB && best_service != SERVICE_HTTP)) {
best_service = current_type; // Connection handler arguments
parse_service_info(service_token, best_host, sizeof(best_host), &best_port); typedef struct {
} int client_fd;
} wssshd_state_t *state;
const wssshd_config_t *config;
} connection_handler_args_t;
// Forward declaration for proxy connection handler
static void *proxy_connection_handler(void *arg);
service_token = strtok(NULL, ",");
}
free(services_copy);
if (best_service != SERVICE_NONE) {
result.client = client;
result.service_type = best_service;
strncpy(result.service_host, best_host, sizeof(result.service_host));
result.service_port = best_port;
pthread_mutex_unlock(&state->client_mutex);
return &result;
}
}
pthread_mutex_unlock(&state->client_mutex);
return NULL;
}
// Parse Host header from HTTP request // Parse Host header from HTTP request
static int parse_host_header(const char *request, char *hostname, size_t hostname_size) { static int parse_host_header(const char *request, char *hostname, size_t hostname_size) {
...@@ -280,171 +284,9 @@ static int parse_host_header(const char *request, char *hostname, size_t hostnam ...@@ -280,171 +284,9 @@ static int parse_host_header(const char *request, char *hostname, size_t hostnam
return 0; return 0;
} }
// Find existing tunnel for client service
static service_tunnel_t *find_service_tunnel(const char *client_id, const char *hostname, service_type_t service_type, const char *service_host, int service_port) {
pthread_mutex_lock(&tunnels_mutex);
for (int i = 0; i < active_tunnels_count; i++) {
service_tunnel_t *tunnel = &active_tunnels[i];
if (tunnel->active &&
strcmp(tunnel->client_id, client_id) == 0 &&
strcmp(tunnel->hostname, hostname) == 0 &&
tunnel->service_type == service_type &&
strcmp(tunnel->service_host, service_host) == 0 &&
tunnel->service_port == service_port) {
tunnel->last_used = time(NULL);
pthread_mutex_unlock(&tunnels_mutex);
return tunnel;
}
}
pthread_mutex_unlock(&tunnels_mutex);
return NULL;
}
// Create new tunnel to client service
static service_tunnel_t *create_service_tunnel(const char *client_id, const char *hostname, service_type_t service_type, const char *service_host, int service_port) {
pthread_mutex_lock(&tunnels_mutex);
// Find free slot
int slot = -1;
for (int i = 0; i < MAX_ACTIVE_TUNNELS; i++) {
if (!active_tunnels[i].active) {
slot = i;
break;
}
}
if (slot == -1 && active_tunnels_count < MAX_ACTIVE_TUNNELS) {
slot = active_tunnels_count++;
}
if (slot == -1) {
pthread_mutex_unlock(&tunnels_mutex);
return NULL;
}
service_tunnel_t *tunnel = &active_tunnels[slot];
memset(tunnel, 0, sizeof(service_tunnel_t));
strncpy(tunnel->client_id, client_id, sizeof(tunnel->client_id));
strncpy(tunnel->hostname, hostname, sizeof(tunnel->hostname));
tunnel->service_type = service_type;
strncpy(tunnel->service_host, service_host, sizeof(tunnel->service_host));
tunnel->service_port = service_port;
tunnel->created_at = time(NULL);
tunnel->last_used = time(NULL);
tunnel->active = true;
pthread_mutex_init(&tunnel->mutex, NULL);
pthread_mutex_unlock(&tunnels_mutex);
return tunnel;
}
// Establish connection to client service
static int establish_service_connection(service_tunnel_t *tunnel) {
pthread_mutex_lock(&tunnel->mutex);
if (tunnel->tunnel_fd >= 0) {
// Already connected
pthread_mutex_unlock(&tunnel->mutex);
return 0;
}
// Create socket
tunnel->tunnel_fd = socket(AF_INET, SOCK_STREAM, 0);
if (tunnel->tunnel_fd < 0) {
pthread_mutex_unlock(&tunnel->mutex);
return -1;
}
// Set non-blocking
fcntl(tunnel->tunnel_fd, F_SETFL, O_NONBLOCK);
// Resolve host
struct hostent *he = gethostbyname(tunnel->service_host);
if (!he) {
close(tunnel->tunnel_fd);
tunnel->tunnel_fd = -1;
pthread_mutex_unlock(&tunnel->mutex);
return -1;
}
// Connect
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(tunnel->service_port);
addr.sin_addr = *((struct in_addr *)he->h_addr);
if (connect(tunnel->tunnel_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
if (errno != EINPROGRESS) {
close(tunnel->tunnel_fd);
tunnel->tunnel_fd = -1;
pthread_mutex_unlock(&tunnel->mutex);
return -1;
}
}
// For HTTPS, establish SSL connection
if (tunnel->service_type == SERVICE_HTTPS) {
SSL_CTX *ctx = create_ssl_context();
if (!ctx) {
close(tunnel->tunnel_fd);
tunnel->tunnel_fd = -1;
pthread_mutex_unlock(&tunnel->mutex);
return -1;
}
tunnel->ssl = create_ssl_connection(ctx, tunnel->tunnel_fd, 0); // debug = 0
SSL_CTX_free(ctx);
if (!tunnel->ssl) {
close(tunnel->tunnel_fd);
tunnel->tunnel_fd = -1;
pthread_mutex_unlock(&tunnel->mutex);
return -1;
}
// Set to accept invalid certificates
SSL_set_verify(tunnel->ssl, SSL_VERIFY_NONE, NULL);
}
pthread_mutex_unlock(&tunnel->mutex);
return 0;
}
// Close tunnel
static void close_service_tunnel(service_tunnel_t *tunnel) {
pthread_mutex_lock(&tunnel->mutex);
if (tunnel->ssl) {
SSL_free(tunnel->ssl);
tunnel->ssl = NULL;
}
if (tunnel->tunnel_fd >= 0) {
close(tunnel->tunnel_fd);
tunnel->tunnel_fd = -1;
}
tunnel->active = false;
pthread_mutex_unlock(&tunnel->mutex);
}
// Cleanup expired tunnels (called periodically)
static void cleanup_expired_tunnels(void) {
time_t now = time(NULL);
const int timeout_seconds = 300; // 5 minutes
pthread_mutex_lock(&tunnels_mutex);
for (int i = 0; i < active_tunnels_count; i++) {
service_tunnel_t *tunnel = &active_tunnels[i];
if (tunnel->active && (now - tunnel->last_used) > timeout_seconds) {
printf("[WEB-PROXY] Closing expired tunnel for %s\n", tunnel->hostname);
close_service_tunnel(tunnel);
}
}
pthread_mutex_unlock(&tunnels_mutex);
}
// Send HTTP error response // Send HTTP error response
static void send_http_error(int client_fd, int status_code, const char *status_text) { static void send_http_error(int client_fd, int status_code, const char *status_text) {
...@@ -514,7 +356,7 @@ static void *proxy_data_forward(void *arg) { ...@@ -514,7 +356,7 @@ static void *proxy_data_forward(void *arg) {
return NULL; return NULL;
} }
// Handle incoming HTTP request and establish tunnel // Handle incoming HTTP request by proxying to wsssht daemon
static int handle_proxy_request(int client_fd, wssshd_state_t *state, const wssshd_config_t *config) { static int handle_proxy_request(int client_fd, wssshd_state_t *state, const wssshd_config_t *config) {
char request[8192]; char request[8192];
ssize_t bytes_read = recv(client_fd, request, sizeof(request) - 1, 0); ssize_t bytes_read = recv(client_fd, request, sizeof(request) - 1, 0);
...@@ -532,123 +374,190 @@ static int handle_proxy_request(int client_fd, wssshd_state_t *state, const wsss ...@@ -532,123 +374,190 @@ static int handle_proxy_request(int client_fd, wssshd_state_t *state, const wsss
printf("[WEB-PROXY] Received request for hostname: %s\n", hostname); printf("[WEB-PROXY] Received request for hostname: %s\n", hostname);
// Find client and service by hostname // Find client by hostname
client_service_info_t *service_info = find_client_service_by_hostname(hostname, state, config); client_t *client = NULL;
if (!service_info || !service_info->client) { pthread_mutex_lock(&state->client_mutex);
printf("[WEB-PROXY] No client/service found for hostname: %s\n", hostname); for (size_t i = 0; i < state->clients_count; i++) {
client_t *c = &state->clients[i];
if (!c->active) continue;
int hostname_match = 0;
if (strcasecmp(hostname, c->client_id) == 0) {
hostname_match = 1;
} else if (config && config->domain) {
char expected_hostname[512];
snprintf(expected_hostname, sizeof(expected_hostname), "%s.%s", c->client_id, config->domain);
if (strcasecmp(hostname, expected_hostname) == 0) {
hostname_match = 1;
}
}
if (hostname_match) {
client = c;
break;
}
}
pthread_mutex_unlock(&state->client_mutex);
if (!client) {
printf("[WEB-PROXY] No client found for hostname: %s\n", hostname);
send_http_error(client_fd, 404, "Not Found"); send_http_error(client_fd, 404, "Not Found");
return -1; return -1;
} }
printf("[WEB-PROXY] Found client: %s, service: %s:%d\n", printf("[WEB-PROXY] Found client: %s\n", client->client_id);
service_info->client->client_id, service_info->service_host, service_info->service_port);
// Check if client has web/http/https services
// Find or create tunnel bool has_web_service = false;
service_tunnel_t *tunnel = find_service_tunnel(service_info->client->client_id, hostname, const char *service_type = NULL;
service_info->service_type, char *services_copy = strdup(client->services);
service_info->service_host, if (services_copy) {
service_info->service_port); char *service_token = strtok(services_copy, ",");
while (service_token) {
if (!tunnel) { while (*service_token == ' ' || *service_token == '\t') service_token++;
tunnel = create_service_tunnel(service_info->client->client_id, hostname, char *end = service_token + strlen(service_token) - 1;
service_info->service_type, while (end > service_token && (*end == ' ' || *end == '\t')) {
service_info->service_host, *end = '\0';
service_info->service_port); end--;
if (!tunnel) { }
printf("[WEB-PROXY] Failed to create tunnel for %s\n", hostname);
send_http_error(client_fd, 503, "Service Unavailable"); if (strncmp(service_token, "web", 3) == 0) {
return -1; has_web_service = true;
service_type = "web";
break;
} else if (strncmp(service_token, "http", 4) == 0) {
has_web_service = true;
service_type = "http";
break;
} else if (strncmp(service_token, "https", 5) == 0) {
has_web_service = true;
service_type = "https";
break;
}
service_token = strtok(NULL, ",");
} }
free(services_copy);
}
if (!has_web_service) {
printf("[WEB-PROXY] Client %s does not have web/http/https services\n", client->client_id);
send_http_error(client_fd, 503, "Service Unavailable");
return -1;
}
// Determine if SSL should be used
bool use_ssl = false;
if (strcmp(service_type, "https") == 0) {
use_ssl = true;
} else if (strcmp(service_type, "web") == 0) {
use_ssl = true; // Try HTTPS first for 'web'
} }
// 'http' leaves use_ssl = false
// Establish connection if not already connected // Find or create wsssht process
if (establish_service_connection(tunnel) != 0) { wsssht_process_t *proc = find_or_create_wsssht_process(hostname, service_type, client->client_id, config->domain);
printf("[WEB-PROXY] Failed to establish connection to %s:%d\n", if (!proc) {
service_info->service_host, service_info->service_port); printf("[WEB-PROXY] Failed to launch wsssht daemon for %s\n", hostname);
send_http_error(client_fd, 502, "Bad Gateway"); send_http_error(client_fd, 502, "Bad Gateway");
close_service_tunnel(tunnel);
return -1; return -1;
} }
// For WEB service, try HTTP first, then HTTPS if it fails // Connect to wsssht daemon
if (service_info->service_type == SERVICE_WEB) { int tunnel_fd = socket(AF_INET, SOCK_STREAM, 0);
// Try HTTP first if (tunnel_fd < 0) {
service_tunnel_t *http_tunnel = find_service_tunnel(service_info->client->client_id, hostname, send_http_error(client_fd, 500, "Internal Server Error");
SERVICE_HTTP, return -1;
service_info->service_host, }
80);
if (!http_tunnel) {
http_tunnel = create_service_tunnel(service_info->client->client_id, hostname,
SERVICE_HTTP,
service_info->service_host,
80);
}
if (http_tunnel && establish_service_connection(http_tunnel) == 0) { struct sockaddr_in addr;
tunnel = http_tunnel; memset(&addr, 0, sizeof(addr));
} else { addr.sin_family = AF_INET;
// Try HTTPS addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
service_tunnel_t *https_tunnel = find_service_tunnel(service_info->client->client_id, hostname, addr.sin_port = htons(proc->port);
SERVICE_HTTPS,
service_info->service_host,
443);
if (!https_tunnel) {
https_tunnel = create_service_tunnel(service_info->client->client_id, hostname,
SERVICE_HTTPS,
service_info->service_host,
443);
}
if (https_tunnel && establish_service_connection(https_tunnel) == 0) { if (connect(tunnel_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
tunnel = https_tunnel; close(tunnel_fd);
send_http_error(client_fd, 502, "Bad Gateway");
return -1;
}
// SSL setup if needed
SSL_CTX *ssl_ctx = NULL;
SSL *tunnel_ssl = NULL;
if (use_ssl) {
ssl_ctx = create_ssl_context();
if (!ssl_ctx) {
if (strcmp(service_type, "web") == 0) {
use_ssl = false; // Fallback to HTTP
} else { } else {
printf("[WEB-PROXY] Failed to establish HTTP or HTTPS connection for WEB service\n"); close(tunnel_fd);
send_http_error(client_fd, 502, "Bad Gateway"); send_http_error(client_fd, 502, "Bad Gateway");
return -1; return -1;
} }
} else {
tunnel_ssl = create_ssl_connection(ssl_ctx, tunnel_fd, 0);
if (!tunnel_ssl) {
SSL_CTX_free(ssl_ctx);
if (strcmp(service_type, "web") == 0) {
use_ssl = false; // Fallback to HTTP
} else {
close(tunnel_fd);
send_http_error(client_fd, 502, "Bad Gateway");
return -1;
}
}
} }
} }
// Forward the request to the service // Send HTTP request to wsssht daemon
pthread_mutex_lock(&tunnel->mutex); int send_result;
if (use_ssl) {
ssize_t sent; send_result = SSL_write(tunnel_ssl, request, bytes_read);
if (tunnel->ssl) {
sent = SSL_write(tunnel->ssl, request, bytes_read);
} else { } else {
sent = send(tunnel->tunnel_fd, request, bytes_read, 0); send_result = send(tunnel_fd, request, bytes_read, 0);
} }
if (send_result != bytes_read) {
if (sent != bytes_read) { if (tunnel_ssl) {
printf("[WEB-PROXY] Failed to forward request to service\n"); SSL_shutdown(tunnel_ssl);
pthread_mutex_unlock(&tunnel->mutex); SSL_free(tunnel_ssl);
}
if (ssl_ctx) SSL_CTX_free(ssl_ctx);
close(tunnel_fd);
send_http_error(client_fd, 502, "Bad Gateway"); send_http_error(client_fd, 502, "Bad Gateway");
return -1; return -1;
} }
// Read response from service and forward to client // Read response from wsssht daemon and forward to client
char buffer[8192]; char buffer[8192];
ssize_t total_sent = 0;
while (1) { while (1) {
ssize_t response_bytes; ssize_t bytes_recv;
if (tunnel->ssl) { if (use_ssl) {
response_bytes = SSL_read(tunnel->ssl, buffer, sizeof(buffer)); bytes_recv = SSL_read(tunnel_ssl, buffer, sizeof(buffer));
} else { } else {
response_bytes = recv(tunnel->tunnel_fd, buffer, sizeof(buffer), 0); bytes_recv = recv(tunnel_fd, buffer, sizeof(buffer), 0);
} }
if (bytes_recv <= 0) {
if (response_bytes <= 0) {
break; break;
} }
ssize_t client_sent = send(client_fd, buffer, response_bytes, 0); ssize_t sent = send(client_fd, buffer, bytes_recv, 0);
if (client_sent != response_bytes) { if (sent != bytes_recv) {
break; break;
} }
total_sent += sent;
} }
pthread_mutex_unlock(&tunnel->mutex); // Cleanup SSL
if (tunnel_ssl) {
SSL_shutdown(tunnel_ssl);
SSL_free(tunnel_ssl);
}
if (ssl_ctx) SSL_CTX_free(ssl_ctx);
close(tunnel_fd);
printf("[WEB-PROXY] Request handled for %s\n", hostname); printf("[WEB-PROXY] Request handled for %s (%zd bytes sent)\n", hostname, total_sent);
return 0; return 0;
} }
...@@ -807,15 +716,19 @@ void web_proxy_stop_server(void) { ...@@ -807,15 +716,19 @@ void web_proxy_stop_server(void) {
proxy_connections_count = 0; proxy_connections_count = 0;
pthread_mutex_unlock(&proxy_mutex); pthread_mutex_unlock(&proxy_mutex);
// Close all active tunnels // Terminate all wsssht processes
pthread_mutex_lock(&tunnels_mutex); pthread_mutex_lock(&wsssht_mutex);
for (int i = 0; i < active_tunnels_count; i++) { for (int i = 0; i < wsssht_processes_count; i++) {
if (active_tunnels[i].active) { wsssht_process_t *proc = &wsssht_processes[i];
close_service_tunnel(&active_tunnels[i]); if (proc->active) {
printf("[WEB-PROXY] Terminating wsssht process for %s (PID: %d)\n", proc->hostname, proc->pid);
kill(proc->pid, SIGINT);
waitpid(proc->pid, NULL, 0);
proc->active = false;
} }
} }
active_tunnels_count = 0; wsssht_processes_count = 0;
pthread_mutex_unlock(&tunnels_mutex); pthread_mutex_unlock(&wsssht_mutex);
printf("[WEB-PROXY] Web proxy server stopping\n"); printf("[WEB-PROXY] Web proxy server stopping\n");
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment