Implement web proxy functionality for client services

- Added support for proxying requests to CLIENT_NAME.dominio
- Implemented service type detection (web, http, https) with priority ordering
- Added tunnel establishment and management for client services
- Implemented HTTPS support with invalid certificate acceptance
- Added tunnel reuse and timeout management (5 minutes)
- Added SSL connection functions for HTTPS tunneling
- Fixed build issues and updated dependencies
parent 153b6344
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
#include "html_pages/novnc_input_fixedkeys_js_page.h" #include "html_pages/novnc_input_fixedkeys_js_page.h"
#include "html_pages/novnc_input_gesturehandler_js_page.h" #include "html_pages/novnc_input_gesturehandler_js_page.h"
#include "html_pages/novnc_input_keyboard_js_page.h" #include "html_pages/novnc_input_keyboard_js_page.h"
#include "html_pages/novnc_input_keysymdef_js_page.h"
#include "html_pages/novnc_input_keysym_js_page.h" #include "html_pages/novnc_input_keysym_js_page.h"
#include "html_pages/novnc_input_keysymdef_js_page.h"
#include "html_pages/novnc_input_util_js_page.h" #include "html_pages/novnc_input_util_js_page.h"
#include "html_pages/novnc_input_vkeys_js_page.h" #include "html_pages/novnc_input_vkeys_js_page.h"
#include "html_pages/novnc_input_xtscancodes_js_page.h" #include "html_pages/novnc_input_xtscancodes_js_page.h"
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
#include "html_pages/rdp_clipboard_js_page.h" #include "html_pages/rdp_clipboard_js_page.h"
#include "html_pages/rdp_mstsc_js_page.h" #include "html_pages/rdp_mstsc_js_page.h"
#include "html_pages/rdp_out_stream_js_page.h" #include "html_pages/rdp_out_stream_js_page.h"
#include "html_pages/rdp_rdp_graphics_js_page.h"
#include "html_pages/rdp_rdp_wasm_js_page.h" #include "html_pages/rdp_rdp_wasm_js_page.h"
#include "html_pages/rdp_rdp_graphics_js_page.h"
#include "html_pages/rdp_reversed_layouts_js_page.h" #include "html_pages/rdp_reversed_layouts_js_page.h"
#include "html_pages/rdp_scancodes_js_page.h" #include "html_pages/rdp_scancodes_js_page.h"
#include "html_pages/rdp_rdp_wasm_page.h" #include "html_pages/rdp_rdp_wasm_page.h"
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <openssl/err.h>
#include "ssl.h" #include "ssl.h"
SSL_CTX *ssl_create_context(void) { SSL_CTX *ssl_create_context(void) {
...@@ -43,6 +44,46 @@ SSL_CTX *ssl_create_context(void) { ...@@ -43,6 +44,46 @@ SSL_CTX *ssl_create_context(void) {
return ctx; return ctx;
} }
SSL_CTX *create_ssl_context(void) {
SSL_CTX *ssl_ctx;
// Initialize SSL
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ssl_ctx = SSL_CTX_new(TLS_client_method());
if (!ssl_ctx) {
ERR_print_errors_fp(stderr);
return NULL;
}
// Allow self-signed certificates
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_NONE, NULL);
return ssl_ctx;
}
SSL *create_ssl_connection(SSL_CTX *ssl_ctx, int sock, int debug) {
SSL *ssl = SSL_new(ssl_ctx);
SSL_set_fd(ssl, sock);
if (debug) {
fprintf(stderr, "[DEBUG] Establishing SSL connection...\n");
}
if (SSL_connect(ssl) <= 0) {
ERR_print_errors_fp(stderr);
fprintf(stderr, "SSL connection failed\n");
SSL_free(ssl);
return NULL;
}
if (debug) {
fprintf(stderr, "[DEBUG] SSL connection established\n");
}
return ssl;
}
void ssl_cleanup(void) { void ssl_cleanup(void) {
EVP_cleanup(); EVP_cleanup();
} }
......
...@@ -31,4 +31,8 @@ void ssl_cleanup(void); ...@@ -31,4 +31,8 @@ void ssl_cleanup(void);
int ssl_load_certificates(SSL_CTX *ctx, const char *cert_file, const char *key_file); int ssl_load_certificates(SSL_CTX *ctx, const char *cert_file, const char *key_file);
int ssl_generate_self_signed_cert(const char *cert_file, const char *key_file); int ssl_generate_self_signed_cert(const char *cert_file, const char *key_file);
// Client SSL functions (for web proxy)
SSL_CTX *create_ssl_context(void);
SSL *create_ssl_connection(SSL_CTX *ssl_ctx, int sock, int debug);
#endif /* SSL_H */ #endif /* SSL_H */
\ No newline at end of file
...@@ -30,9 +30,29 @@ ...@@ -30,9 +30,29 @@
#include <time.h> #include <time.h>
#include <ctype.h> #include <ctype.h>
#include <signal.h> #include <signal.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "web_proxy.h" #include "web_proxy.h"
#include "websocket.h" #include "websocket.h"
#include "websocket_protocol.h" #include "websocket_protocol.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;
...@@ -53,12 +73,49 @@ static proxy_connection_t proxy_connections[MAX_PROXY_CONNECTIONS]; ...@@ -53,12 +73,49 @@ 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 // Thread arguments structure
typedef struct { typedef struct {
const wssshd_config_t *config; const wssshd_config_t *config;
wssshd_state_t *state; wssshd_state_t *state;
} proxy_thread_args_t; } proxy_thread_args_t;
// Forward declarations
static void cleanup_expired_tunnels(void);
// Cleanup thread
static volatile int cleanup_running = 0;
static void *cleanup_thread(void *arg) {
(void)arg; // Unused
cleanup_running = 1;
while (cleanup_running) {
cleanup_expired_tunnels();
sleep(60); // Cleanup every minute
}
return NULL;
}
// Connection handler arguments // Connection handler arguments
typedef struct { typedef struct {
int client_fd; int client_fd;
...@@ -69,8 +126,48 @@ typedef struct { ...@@ -69,8 +126,48 @@ typedef struct {
// Forward declaration for proxy connection handler // Forward declaration for proxy connection handler
static void *proxy_connection_handler(void *arg); static void *proxy_connection_handler(void *arg);
// Find client by hostname (matching subdomain or client_id)
static client_t *find_client_by_hostname(const char *hostname, wssshd_state_t *state, const wssshd_config_t *config) { // Parse service string to extract host and port
static int parse_service_info(const char *service_str, char *host, size_t host_size, int *port) {
// Service format: "web:host:port" or just "web"
char *colon1 = strchr(service_str, ':');
if (!colon1) {
// No host/port specified, use defaults
if (host) strncpy(host, "127.0.0.1", host_size);
if (port) *port = 80; // Default HTTP port
return 0;
}
char *colon2 = strchr(colon1 + 1, ':');
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
size_t host_len = colon2 - colon1 - 1;
if (host_len >= host_size) host_len = host_size - 1;
if (host) {
strncpy(host, colon1 + 1, host_len);
host[host_len] = '\0';
}
if (port) *port = atoi(colon2 + 1);
return 0;
}
// Find client by hostname and determine which service to use
static client_service_info_t *find_client_service_by_hostname(const char *hostname, wssshd_state_t *state, const wssshd_config_t *config) {
static client_service_info_t result;
memset(&result, 0, sizeof(result));
if (!hostname || !state) return NULL; if (!hostname || !state) return NULL;
pthread_mutex_lock(&state->client_mutex); pthread_mutex_lock(&state->client_mutex);
...@@ -79,28 +176,73 @@ static client_t *find_client_by_hostname(const char *hostname, wssshd_state_t *s ...@@ -79,28 +176,73 @@ static client_t *find_client_by_hostname(const char *hostname, wssshd_state_t *s
client_t *client = &state->clients[i]; client_t *client = &state->clients[i];
if (!client->active) continue; if (!client->active) continue;
// Check if client has web service // Check hostname match
if (strstr(client->services, "web") == NULL && int hostname_match = 0;
strstr(client->services, "http") == NULL) {
continue;
}
// Try exact match with client_id
if (strcasecmp(hostname, client->client_id) == 0) { if (strcasecmp(hostname, client->client_id) == 0) {
pthread_mutex_unlock(&state->client_mutex); hostname_match = 1;
return client; } else if (config && config->domain) {
}
// Try subdomain match: hostname.client_id.domain
if (config && config->domain) {
char expected_hostname[512]; char expected_hostname[512];
snprintf(expected_hostname, sizeof(expected_hostname), "%s.%s", snprintf(expected_hostname, sizeof(expected_hostname), "%s.%s",
client->client_id, config->domain); client->client_id, config->domain);
if (strcasecmp(hostname, expected_hostname) == 0) { if (strcasecmp(hostname, expected_hostname) == 0) {
pthread_mutex_unlock(&state->client_mutex); hostname_match = 1;
return client;
} }
} }
if (!hostname_match) continue;
// Parse services and find the best one (web > http > https)
char *services_copy = strdup(client->services);
if (!services_copy) continue;
char *service_token = strtok(services_copy, ",");
service_type_t best_service = SERVICE_NONE;
char best_host[256] = "127.0.0.1";
int best_port = 80;
while (service_token) {
// Trim whitespace
while (*service_token == ' ' || *service_token == '\t') service_token++;
char *end = service_token + strlen(service_token) - 1;
while (end > service_token && (*end == ' ' || *end == '\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;
parse_service_info(service_token, best_host, sizeof(best_host), &best_port);
}
}
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); pthread_mutex_unlock(&state->client_mutex);
...@@ -138,6 +280,172 @@ static int parse_host_header(const char *request, char *hostname, size_t hostnam ...@@ -138,6 +280,172 @@ 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) {
const char *body_format = "<html><body><h1>%d %s</h1></body></html>"; const char *body_format = "<html><body><h1>%d %s</h1></body></html>";
...@@ -224,32 +532,123 @@ static int handle_proxy_request(int client_fd, wssshd_state_t *state, const wsss ...@@ -224,32 +532,123 @@ 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 by hostname // Find client and service by hostname
client_t *client = find_client_by_hostname(hostname, state, config); client_service_info_t *service_info = find_client_service_by_hostname(hostname, state, config);
if (!client) { if (!service_info || !service_info->client) {
printf("[WEB-PROXY] No client found for hostname: %s\n", hostname); printf("[WEB-PROXY] No client/service 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\n", client->client_id); printf("[WEB-PROXY] Found client: %s, service: %s:%d\n",
service_info->client->client_id, service_info->service_host, service_info->service_port);
// Find or create tunnel
service_tunnel_t *tunnel = find_service_tunnel(service_info->client->client_id, hostname,
service_info->service_type,
service_info->service_host,
service_info->service_port);
if (!tunnel) {
tunnel = create_service_tunnel(service_info->client->client_id, hostname,
service_info->service_type,
service_info->service_host,
service_info->service_port);
if (!tunnel) {
printf("[WEB-PROXY] Failed to create tunnel for %s\n", hostname);
send_http_error(client_fd, 503, "Service Unavailable");
return -1;
}
}
// TODO: Establish tunnel to the client's web service // Establish connection if not already connected
// For now, we'll return a simple response indicating the proxy is working if (establish_service_connection(tunnel) != 0) {
const char *response = printf("[WEB-PROXY] Failed to establish connection to %s:%d\n",
"HTTP/1.1 200 OK\r\n" service_info->service_host, service_info->service_port);
"Content-Type: text/plain\r\n" send_http_error(client_fd, 502, "Bad Gateway");
"Content-Length: 50\r\n" close_service_tunnel(tunnel);
"Connection: close\r\n" return -1;
"\r\n" }
"Web proxy tunnel established for client: ";
// For WEB service, try HTTP first, then HTTPS if it fails
if (service_info->service_type == SERVICE_WEB) {
// Try HTTP first
service_tunnel_t *http_tunnel = find_service_tunnel(service_info->client->client_id, hostname,
SERVICE_HTTP,
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) {
tunnel = http_tunnel;
} else {
// Try HTTPS
service_tunnel_t *https_tunnel = find_service_tunnel(service_info->client->client_id, hostname,
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) {
tunnel = https_tunnel;
} else {
printf("[WEB-PROXY] Failed to establish HTTP or HTTPS connection for WEB service\n");
send_http_error(client_fd, 502, "Bad Gateway");
return -1;
}
}
}
// Forward the request to the service
pthread_mutex_lock(&tunnel->mutex);
ssize_t sent;
if (tunnel->ssl) {
sent = SSL_write(tunnel->ssl, request, bytes_read);
} else {
sent = send(tunnel->tunnel_fd, request, bytes_read, 0);
}
char response_body[512]; if (sent != bytes_read) {
snprintf(response_body, sizeof(response_body), "%s%s", response, client->client_id); printf("[WEB-PROXY] Failed to forward request to service\n");
pthread_mutex_unlock(&tunnel->mutex);
send_http_error(client_fd, 502, "Bad Gateway");
return -1;
}
// Read response from service and forward to client
char buffer[8192];
while (1) {
ssize_t response_bytes;
if (tunnel->ssl) {
response_bytes = SSL_read(tunnel->ssl, buffer, sizeof(buffer));
} else {
response_bytes = recv(tunnel->tunnel_fd, buffer, sizeof(buffer), 0);
}
if (response_bytes <= 0) {
break;
}
ssize_t client_sent = send(client_fd, buffer, response_bytes, 0);
if (client_sent != response_bytes) {
break;
}
}
send(client_fd, response_body, strlen(response_body), 0); pthread_mutex_unlock(&tunnel->mutex);
// Close the connection for now (full tunnel implementation requires more work) printf("[WEB-PROXY] Request handled for %s\n", hostname);
return 0; return 0;
} }
...@@ -356,6 +755,14 @@ int web_proxy_start_server(const wssshd_config_t *config, wssshd_state_t *state) ...@@ -356,6 +755,14 @@ int web_proxy_start_server(const wssshd_config_t *config, wssshd_state_t *state)
return 0; // Web proxy not enabled return 0; // Web proxy not enabled
} }
// Start cleanup thread
pthread_t cleanup_tid;
if (pthread_create(&cleanup_tid, NULL, cleanup_thread, NULL) != 0) {
perror("[WEB-PROXY] Failed to create cleanup thread");
return -1;
}
pthread_detach(cleanup_tid);
// Allocate thread arguments // Allocate thread arguments
proxy_thread_args_t *args = malloc(sizeof(proxy_thread_args_t)); proxy_thread_args_t *args = malloc(sizeof(proxy_thread_args_t));
if (!args) { if (!args) {
...@@ -379,6 +786,7 @@ int web_proxy_start_server(const wssshd_config_t *config, wssshd_state_t *state) ...@@ -379,6 +786,7 @@ int web_proxy_start_server(const wssshd_config_t *config, wssshd_state_t *state)
void web_proxy_stop_server(void) { void web_proxy_stop_server(void) {
server_running = 0; server_running = 0;
cleanup_running = 0;
// Close server socket to unblock accept() // Close server socket to unblock accept()
if (server_socket >= 0) { if (server_socket >= 0) {
...@@ -399,5 +807,15 @@ void web_proxy_stop_server(void) { ...@@ -399,5 +807,15 @@ 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
pthread_mutex_lock(&tunnels_mutex);
for (int i = 0; i < active_tunnels_count; i++) {
if (active_tunnels[i].active) {
close_service_tunnel(&active_tunnels[i]);
}
}
active_tunnels_count = 0;
pthread_mutex_unlock(&tunnels_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