Add proxy functionality

parent f8266bf1
...@@ -116,7 +116,8 @@ static void load_config_file(wssshd_config_t *config, const char *config_file) { ...@@ -116,7 +116,8 @@ static void load_config_file(wssshd_config_t *config, const char *config_file) {
} else if (strcmp(key, "web-https") == 0) { } else if (strcmp(key, "web-https") == 0) {
config->web_https = (strcmp(value, "true") == 0 || strcmp(value, "1") == 0); config->web_https = (strcmp(value, "true") == 0 || strcmp(value, "1") == 0);
} else if (strcmp(key, "web-proxy") == 0) { } else if (strcmp(key, "web-proxy") == 0) {
config->web_proxy_enabled = (strcmp(value, "true") == 0 || strcmp(value, "1") == 0); config->web_proxy_enabled = true;
config->web_proxy_port = atoi(value);
} else if (strcmp(key, "web-proxy-port") == 0) { } else if (strcmp(key, "web-proxy-port") == 0) {
config->web_proxy_port = atoi(value); config->web_proxy_port = atoi(value);
} else if (strcmp(key, "websocket-tls-only") == 0) { } else if (strcmp(key, "websocket-tls-only") == 0) {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <pthread.h> #include <pthread.h>
#include <time.h> #include <time.h>
#include <arpa/inet.h>
#include "config.h" #include "config.h"
#include "websocket.h" #include "websocket.h"
#include "web.h" #include "web.h"
...@@ -169,22 +170,25 @@ int main(int argc, char *argv[]) { ...@@ -169,22 +170,25 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "Warning: Failed to start web interface\n"); fprintf(stderr, "Warning: Failed to start web interface\n");
} }
// Start web proxy server if enabled
printf("Checking web proxy: enabled=%d, port=%d\n", config->web_proxy_enabled, config->web_proxy_port);
if (config->web_proxy_enabled) {
printf("Starting web proxy server\n");
if (web_proxy_start_server(config, state) != 0) {
fprintf(stderr, "Warning: Failed to start web proxy server\n");
}
}
// Start WebSocket server // Start WebSocket server
if (websocket_start_server(config, state) != 0) { if (websocket_start_server(config, state) != 0) {
fprintf(stderr, "Failed to start WebSocket server\n"); fprintf(stderr, "Failed to start WebSocket server\n");
web_proxy_stop_server();
web_stop_server(); web_stop_server();
websocket_free_state(state); websocket_free_state(state);
free_config(config); free_config(config);
return 1; return 1;
} }
// Start web proxy server if enabled
if (config->web_proxy_enabled) {
if (web_proxy_start_server(config, state) != 0) {
fprintf(stderr, "Warning: Failed to start web proxy server\n");
}
}
printf("WSSSH Daemon running on %s:%d\n", config->host, config->port); printf("WSSSH Daemon running on %s:%d\n", config->host, config->port);
if (config->web_proxy_enabled) { if (config->web_proxy_enabled) {
printf("Web proxy server running on 127.0.0.1:%d\n", config->web_proxy_port); printf("Web proxy server running on 127.0.0.1:%d\n", config->web_proxy_port);
...@@ -208,9 +212,9 @@ int main(int argc, char *argv[]) { ...@@ -208,9 +212,9 @@ int main(int argc, char *argv[]) {
printf("\nShutting down WSSSH Daemon...\n"); printf("\nShutting down WSSSH Daemon...\n");
// Stop servers // Stop servers
websocket_stop_server();
web_proxy_stop_server(); web_proxy_stop_server();
web_stop_server(); web_stop_server();
websocket_stop_server();
// Clean up plugin system // Clean up plugin system
plugin_system_cleanup(); plugin_system_cleanup();
......
This diff is collapsed.
...@@ -34,9 +34,7 @@ ...@@ -34,9 +34,7 @@
#include "websocket.h" #include "websocket.h"
#include "websocket_protocol.h" #include "websocket_protocol.h"
// Global state // Global state for shutdown
static wssshd_state_t *global_state = NULL;
static const wssshd_config_t *global_config = NULL;
static int server_socket = -1; static int server_socket = -1;
static volatile int server_running = 0; static volatile int server_running = 0;
...@@ -55,17 +53,30 @@ static proxy_connection_t proxy_connections[MAX_PROXY_CONNECTIONS]; ...@@ -55,17 +53,30 @@ 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;
// Thread arguments structure
typedef struct {
const wssshd_config_t *config;
wssshd_state_t *state;
} proxy_thread_args_t;
// Connection handler arguments
typedef struct {
int client_fd;
wssshd_state_t *state;
const wssshd_config_t *config;
} connection_handler_args_t;
// 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) // Find client by hostname (matching subdomain or client_id)
static client_t *find_client_by_hostname(const char *hostname) { static client_t *find_client_by_hostname(const char *hostname, wssshd_state_t *state, const wssshd_config_t *config) {
if (!hostname || !global_state) return NULL; if (!hostname || !state) return NULL;
pthread_mutex_lock(&global_state->client_mutex); pthread_mutex_lock(&state->client_mutex);
for (size_t i = 0; i < global_state->clients_count; i++) { for (size_t i = 0; i < state->clients_count; i++) {
client_t *client = &global_state->clients[i]; client_t *client = &state->clients[i];
if (!client->active) continue; if (!client->active) continue;
// Check if client has web service // Check if client has web service
...@@ -76,23 +87,23 @@ static client_t *find_client_by_hostname(const char *hostname) { ...@@ -76,23 +87,23 @@ static client_t *find_client_by_hostname(const char *hostname) {
// Try exact match with client_id // Try exact match with client_id
if (strcasecmp(hostname, client->client_id) == 0) { if (strcasecmp(hostname, client->client_id) == 0) {
pthread_mutex_unlock(&global_state->client_mutex); pthread_mutex_unlock(&state->client_mutex);
return client; return client;
} }
// Try subdomain match: hostname.client_id.domain // Try subdomain match: hostname.client_id.domain
if (global_config && global_config->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, global_config->domain); client->client_id, config->domain);
if (strcasecmp(hostname, expected_hostname) == 0) { if (strcasecmp(hostname, expected_hostname) == 0) {
pthread_mutex_unlock(&global_state->client_mutex); pthread_mutex_unlock(&state->client_mutex);
return client; return client;
} }
} }
} }
pthread_mutex_unlock(&global_state->client_mutex); pthread_mutex_unlock(&state->client_mutex);
return NULL; return NULL;
} }
...@@ -196,7 +207,7 @@ static void *proxy_data_forward(void *arg) { ...@@ -196,7 +207,7 @@ static void *proxy_data_forward(void *arg) {
} }
// Handle incoming HTTP request and establish tunnel // Handle incoming HTTP request and establish tunnel
static int handle_proxy_request(int client_fd) { 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);
if (bytes_read <= 0) { if (bytes_read <= 0) {
...@@ -214,7 +225,7 @@ static int handle_proxy_request(int client_fd) { ...@@ -214,7 +225,7 @@ static int handle_proxy_request(int client_fd) {
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 by hostname
client_t *client = find_client_by_hostname(hostname); client_t *client = find_client_by_hostname(hostname, state, config);
if (!client) { if (!client) {
printf("[WEB-PROXY] No client found for hostname: %s\n", hostname); 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");
...@@ -244,12 +255,15 @@ static int handle_proxy_request(int client_fd) { ...@@ -244,12 +255,15 @@ static int handle_proxy_request(int client_fd) {
// Proxy connection handler thread // Proxy connection handler thread
static void *proxy_connection_handler(void *arg) { static void *proxy_connection_handler(void *arg) {
int client_fd = *(int *)arg; connection_handler_args_t *args = (connection_handler_args_t *)arg;
free(arg); int client_fd = args->client_fd;
wssshd_state_t *state = args->state;
const wssshd_config_t *config = args->config;
free(args);
printf("[WEB-PROXY] New connection received\n"); printf("[WEB-PROXY] New connection received\n");
handle_proxy_request(client_fd); handle_proxy_request(client_fd, state, config);
close(client_fd); close(client_fd);
printf("[WEB-PROXY] Connection closed\n"); printf("[WEB-PROXY] Connection closed\n");
...@@ -257,16 +271,21 @@ static void *proxy_connection_handler(void *arg) { ...@@ -257,16 +271,21 @@ static void *proxy_connection_handler(void *arg) {
return NULL; return NULL;
} }
// Main HTTP server thread static void *http_proxy_thread(void *arg) {
static void *http_proxy_thread(void *arg __attribute__((unused))) { proxy_thread_args_t *args = (proxy_thread_args_t *)arg;
const wssshd_config_t *config = args->config;
wssshd_state_t *state = args->state;
free(args);
struct sockaddr_in server_addr, client_addr; struct sockaddr_in server_addr, client_addr;
socklen_t client_len = sizeof(client_addr); socklen_t client_len = sizeof(client_addr);
printf("[WEB-PROXY] Creating socket\n");
server_socket = socket(AF_INET, SOCK_STREAM, 0); server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 0) { if (server_socket < 0) {
perror("[WEB-PROXY] Failed to create server socket"); perror("[WEB-PROXY] Failed to create server socket");
return NULL; return NULL;
} }
printf("[WEB-PROXY] Socket created\n");
// Set socket options // Set socket options
int opt = 1; int opt = 1;
...@@ -274,22 +293,25 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) { ...@@ -274,22 +293,25 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) {
memset(&server_addr, 0, sizeof(server_addr)); memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Listen only on localhost server_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // Listen on localhost only
server_addr.sin_port = htons(global_config->web_proxy_port); server_addr.sin_port = htons(config->web_proxy_port);
printf("[WEB-PROXY] Binding to 127.0.0.1:%d\n", config->web_proxy_port);
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("[WEB-PROXY] Failed to bind server socket"); perror("[WEB-PROXY] Failed to bind server socket");
close(server_socket); close(server_socket);
return NULL; return NULL;
} }
printf("[WEB-PROXY] Bound successfully\n");
if (listen(server_socket, 10) < 0) { if (listen(server_socket, 10) < 0) {
perror("[WEB-PROXY] Failed to listen on server socket"); perror("[WEB-PROXY] Failed to listen on server socket");
close(server_socket); close(server_socket);
return NULL; return NULL;
} }
printf("[WEB-PROXY] Listening successfully\n");
printf("[WEB-PROXY] Web proxy server starting on 127.0.0.1:%d\n", global_config->web_proxy_port); printf("[WEB-PROXY] Web proxy server starting on 127.0.0.1:%d\n", config->web_proxy_port);
server_running = 1; server_running = 1;
// Ignore SIGPIPE to prevent crashes on broken connections // Ignore SIGPIPE to prevent crashes on broken connections
...@@ -303,17 +325,19 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) { ...@@ -303,17 +325,19 @@ static void *http_proxy_thread(void *arg __attribute__((unused))) {
} }
// Create a new thread to handle the connection // Create a new thread to handle the connection
int *client_fd_ptr = malloc(sizeof(int)); connection_handler_args_t *handler_args = malloc(sizeof(connection_handler_args_t));
if (!client_fd_ptr) { if (!handler_args) {
close(client_fd); close(client_fd);
continue; continue;
} }
*client_fd_ptr = client_fd; handler_args->client_fd = client_fd;
handler_args->state = state;
handler_args->config = config;
pthread_t thread; pthread_t thread;
if (pthread_create(&thread, NULL, proxy_connection_handler, client_fd_ptr) != 0) { if (pthread_create(&thread, NULL, proxy_connection_handler, handler_args) != 0) {
perror("[WEB-PROXY] Failed to create connection handler thread"); perror("[WEB-PROXY] Failed to create connection handler thread");
free(client_fd_ptr); free(handler_args);
close(client_fd); close(client_fd);
continue; continue;
} }
...@@ -332,18 +356,20 @@ int web_proxy_start_server(const wssshd_config_t *config, wssshd_state_t *state) ...@@ -332,18 +356,20 @@ 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
} }
global_config = config; // Allocate thread arguments
global_state = state; proxy_thread_args_t *args = malloc(sizeof(proxy_thread_args_t));
if (!args) {
// Set default port if not specified perror("[WEB-PROXY] Failed to allocate thread arguments");
if (config->web_proxy_port == 0) { return -1;
// This won't work directly since config is const, but the CLI parsing sets it
} }
args->config = config;
args->state = state;
// Start HTTP proxy server thread // Start HTTP proxy server thread
pthread_t thread; pthread_t thread;
if (pthread_create(&thread, NULL, http_proxy_thread, NULL) != 0) { if (pthread_create(&thread, NULL, http_proxy_thread, args) != 0) {
perror("[WEB-PROXY] Failed to create HTTP proxy server thread"); perror("[WEB-PROXY] Failed to create HTTP proxy server thread");
free(args);
return -1; return -1;
} }
......
...@@ -643,6 +643,8 @@ int websocket_handle_message(wssshd_state_t *state, ws_connection_t *conn __attr ...@@ -643,6 +643,8 @@ int websocket_handle_message(wssshd_state_t *state, ws_connection_t *conn __attr
if (client_id && password && strcmp(password, state->server_password) == 0) { if (client_id && password && strcmp(password, state->server_password) == 0) {
client_t *client = websocket_add_client(state, client_id, (void *)conn, services); client_t *client = websocket_add_client(state, client_id, (void *)conn, services);
if (client) { if (client) {
// Set client IP
strcpy(client->ip, inet_ntoa(conn->addr.sin_addr));
// Send registration success // Send registration success
char response[512]; char response[512];
snprintf(response, sizeof(response), REGISTERED_MSG, client_id); snprintf(response, sizeof(response), REGISTERED_MSG, client_id);
...@@ -1780,17 +1782,22 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state) ...@@ -1780,17 +1782,22 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
// Load or generate certificates // Load or generate certificates
char cert_file[256], key_file[256]; char cert_file[256], key_file[256];
// Try system location first, then fall back to local directory bool use_system_location = false;
// Check if /etc/wssshd directory exists
if (access("/etc/wssshd", F_OK) == 0) {
// Try to use system location
snprintf(cert_file, sizeof(cert_file), "/etc/wssshd/cert.pem"); snprintf(cert_file, sizeof(cert_file), "/etc/wssshd/cert.pem");
snprintf(key_file, sizeof(key_file), "/etc/wssshd/key.pem"); snprintf(key_file, sizeof(key_file), "/etc/wssshd/key.pem");
use_system_location = true;
// If system location doesn't exist and we can't write there, use local directory } else {
if (access(cert_file, F_OK) != 0) { // Fall back to local directory
char local_dir[256]; char local_dir[256];
snprintf(local_dir, sizeof(local_dir), "./certs"); snprintf(local_dir, sizeof(local_dir), "./certs");
mkdir(local_dir, 0755); // Create directory if it doesn't exist mkdir(local_dir, 0755); // Create directory if it doesn't exist
snprintf(cert_file, sizeof(cert_file), "./certs/cert.pem"); snprintf(cert_file, sizeof(cert_file), "./certs/cert.pem");
snprintf(key_file, sizeof(key_file), "./certs/key.pem"); snprintf(key_file, sizeof(key_file), "./certs/key.pem");
use_system_location = false;
} }
printf("Using certificates: %s, %s\n", cert_file, key_file); printf("Using certificates: %s, %s\n", cert_file, key_file);
...@@ -1798,13 +1805,33 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state) ...@@ -1798,13 +1805,33 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
if (access(cert_file, F_OK) != 0 || access(key_file, F_OK) != 0) { if (access(cert_file, F_OK) != 0 || access(key_file, F_OK) != 0) {
printf("Generating self-signed certificate...\n"); printf("Generating self-signed certificate...\n");
if (ssl_generate_self_signed_cert(cert_file, key_file) != 0) { if (ssl_generate_self_signed_cert(cert_file, key_file) != 0) {
if (use_system_location) {
// If system location failed, fall back to local directory
printf("Failed to generate certificate in system location, falling back to local directory...\n");
char local_dir[256];
snprintf(local_dir, sizeof(local_dir), "./certs");
mkdir(local_dir, 0755); // Create directory if it doesn't exist
snprintf(cert_file, sizeof(cert_file), "./certs/cert.pem");
snprintf(key_file, sizeof(key_file), "./certs/key.pem");
printf("Using certificates: %s, %s\n", cert_file, key_file);
if (ssl_generate_self_signed_cert(cert_file, key_file) != 0) {
fprintf(stderr, "Failed to generate certificate in fallback location\n");
SSL_CTX_free(ssl_ctx);
close(server_sock);
return -1;
}
printf("Certificate generated successfully in fallback location\n");
} else {
fprintf(stderr, "Failed to generate certificate\n"); fprintf(stderr, "Failed to generate certificate\n");
SSL_CTX_free(ssl_ctx); SSL_CTX_free(ssl_ctx);
close(server_sock); close(server_sock);
return -1; return -1;
} }
} else {
printf("Certificate generated successfully\n"); printf("Certificate generated successfully\n");
} }
}
printf("Loading certificates...\n"); printf("Loading certificates...\n");
if (ssl_load_certificates(ssl_ctx, cert_file, key_file) != 0) { if (ssl_load_certificates(ssl_ctx, cert_file, key_file) != 0) {
...@@ -1862,6 +1889,9 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state) ...@@ -1862,6 +1889,9 @@ int websocket_start_server(const wssshd_config_t *config, wssshd_state_t *state)
continue; continue;
} }
// Set the client address
conn->addr = client_addr;
// Start client handler thread // Start client handler thread
client_thread_args_t *thread_args = malloc(sizeof(client_thread_args_t)); client_thread_args_t *thread_args = malloc(sizeof(client_thread_args_t));
......
...@@ -38,6 +38,7 @@ typedef struct { ...@@ -38,6 +38,7 @@ typedef struct {
char tunnel_control[16]; char tunnel_control[16];
char wssshd_private_ip[64]; char wssshd_private_ip[64];
char services[256]; // Comma-separated list of services (e.g., "ssh,rdp,vnc") char services[256]; // Comma-separated list of services (e.g., "ssh,rdp,vnc")
char ip[INET_ADDRSTRLEN];
} client_t; } client_t;
// Terminal session (defined in terminal.h) // Terminal session (defined in terminal.h)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <netinet/in.h>
#include <openssl/ssl.h> #include <openssl/ssl.h>
// WebSocket frame opcodes // WebSocket frame opcodes
...@@ -60,6 +61,7 @@ typedef struct { ...@@ -60,6 +61,7 @@ typedef struct {
char *recv_buffer; char *recv_buffer;
size_t recv_buffer_size; size_t recv_buffer_size;
size_t recv_buffer_used; size_t recv_buffer_used;
struct sockaddr_in addr;
} ws_connection_t; } ws_connection_t;
// Function declarations // Function declarations
......
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