Add proxy functionality

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