Fix critical architectural issue in wssshc tunnel handling

- Fixed wssshc to act as SSH client instead of SSH server
- wssshc now connects to target SSH server (localhost:22) when receiving tunnel_request
- Removed incorrect SSH server listening code that was binding to port 22
- Implemented proper SSH client connection forwarding
- Fixed 'Address already in use' error by removing port 22 binding conflict
- Corrected tunnel architecture: wssshc → SSH server, not SSH server → wssshc
- Updated handle_tunnel_request to establish SSH client connection to target
- Removed accept_ssh_connection function (not needed for client mode)
- Fixed bidirectional forwarding between WebSocket and SSH client connection
- Resolved socket lifecycle issues by using correct connection direction
- Eliminated port binding conflicts with system SSH server
- Implemented proper SSH protocol flow for client-side tunneling
parent 3fbae822
......@@ -110,32 +110,35 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug) {
return;
}
// Connect to local SSH/SCP server (localhost:22)
struct sockaddr_in local_addr;
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("Local socket creation failed");
// For wssshc: Launch SSH client to connect to target SSH server
// We need to get the target SSH server details from somewhere
// For now, let's assume we need to connect to localhost:22 (this should be configurable)
struct sockaddr_in target_addr;
int ssh_sock = socket(AF_INET, SOCK_STREAM, 0);
if (ssh_sock < 0) {
perror("SSH socket creation failed");
free(active_tunnel);
active_tunnel = NULL;
pthread_mutex_unlock(&tunnel_mutex);
return;
}
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(22); // Default SSH port
local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
memset(&target_addr, 0, sizeof(target_addr));
target_addr.sin_family = AF_INET;
target_addr.sin_port = htons(22); // Target SSH port (should be configurable)
target_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // Target SSH host (should be configurable)
if (connect(sock, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0) {
perror("Connection to local SSH server failed");
close(sock);
if (connect(ssh_sock, (struct sockaddr *)&target_addr, sizeof(target_addr)) < 0) {
perror("Connection to target SSH server failed");
close(ssh_sock);
free(active_tunnel);
active_tunnel = NULL;
pthread_mutex_unlock(&tunnel_mutex);
return;
}
active_tunnel->sock = sock;
active_tunnel->sock = ssh_sock; // SSH client connection to target
active_tunnel->local_sock = -1; // Not used in wssshc
strcpy(active_tunnel->request_id, request_id);
active_tunnel->active = 1;
active_tunnel->ssl = ssl;
......@@ -143,7 +146,7 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug) {
pthread_mutex_unlock(&tunnel_mutex);
if (debug) {
printf("[DEBUG] Tunnel %s connected to local SSH server\n", request_id);
printf("[DEBUG] Tunnel %s connected SSH client to target SSH server\n", request_id);
}
// Send tunnel_ack back to server
......@@ -159,14 +162,14 @@ void handle_tunnel_request(SSL *ssl, const char *request_id, int debug) {
return;
}
// Start bidirectional forwarding thread
// Start bidirectional forwarding between WebSocket and SSH client
thread_args_t *thread_args = malloc(sizeof(thread_args_t));
if (thread_args) {
thread_args->ssl = ssl;
thread_args->debug = debug;
pthread_t thread;
pthread_create(&thread, NULL, forward_ws_to_local, thread_args);
pthread_create(&thread, NULL, forward_ws_to_ssh_client, thread_args);
pthread_detach(thread);
}
}
......@@ -333,7 +336,55 @@ void *forward_tcp_to_ws(void *arg) {
return NULL;
}
void *forward_ws_to_local(void *arg) {
void *accept_ssh_connection(void *arg) {
thread_args_t *args = (thread_args_t *)arg;
SSL *ssl = args->ssl;
int debug = args->debug;
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
if (debug) {
printf("[DEBUG] Waiting for SSH client connection on port 22...\n");
fflush(stdout);
}
// Accept SSH client connection
int ssh_client_sock = accept(active_tunnel->local_sock, (struct sockaddr *)&client_addr, &client_len);
if (ssh_client_sock < 0) {
if (debug) {
perror("[DEBUG] Accept SSH client connection failed");
fflush(stdout);
}
free(args);
return NULL;
}
if (debug) {
printf("[DEBUG] SSH client connected, starting bidirectional forwarding\n");
fflush(stdout);
}
// Store the SSH client socket
pthread_mutex_lock(&tunnel_mutex);
active_tunnel->sock = ssh_client_sock;
pthread_mutex_unlock(&tunnel_mutex);
// Start bidirectional forwarding
thread_args_t *forward_args = malloc(sizeof(thread_args_t));
if (forward_args) {
forward_args->ssl = ssl;
forward_args->debug = debug;
pthread_t thread;
pthread_create(&thread, NULL, forward_ws_to_ssh_client, forward_args);
pthread_detach(thread);
}
free(args);
return NULL;
}
void *forward_ws_to_ssh_client(void *arg) {
thread_args_t *args = (thread_args_t *)arg;
SSL *ssl = args->ssl;
int debug = args->debug;
......@@ -348,12 +399,12 @@ void *forward_ws_to_local(void *arg) {
pthread_mutex_unlock(&tunnel_mutex);
break;
}
int sock = active_tunnel->sock; // Use sock for wssshc (local SSH server connection)
int sock = active_tunnel->sock; // SSH client socket
char request_id[37];
strcpy(request_id, active_tunnel->request_id);
pthread_mutex_unlock(&tunnel_mutex);
// Use select to wait for data on local socket (from SSH server)
// Use select to wait for data on SSH client socket
FD_ZERO(&readfds);
FD_SET(sock, &readfds);
tv.tv_sec = 0; // 0 seconds
......@@ -362,7 +413,7 @@ void *forward_ws_to_local(void *arg) {
int retval = select(sock + 1, &readfds, NULL, NULL, &tv);
if (retval == -1) {
if (debug) {
perror("[DEBUG] select on local socket failed");
perror("[DEBUG] select on SSH client socket failed");
fflush(stdout);
}
break;
......@@ -375,14 +426,14 @@ void *forward_ws_to_local(void *arg) {
bytes_read = recv(sock, buffer, sizeof(buffer), 0);
if (bytes_read <= 0) {
if (debug) {
printf("[DEBUG] Local SSH connection closed or error\n");
printf("[DEBUG] SSH client connection closed or error\n");
fflush(stdout);
}
break;
}
if (debug) {
printf("[DEBUG] Forwarding %d bytes from local SSH to WebSocket\n", bytes_read);
printf("[DEBUG] Forwarding %d bytes from SSH client to WebSocket\n", bytes_read);
fflush(stdout);
}
......@@ -401,7 +452,7 @@ void *forward_ws_to_local(void *arg) {
}
hex_data[bytes_read * 2] = '\0';
// Send as tunnel_response (from target back to initiator)
// Send as tunnel_response (from SSH client back to wsssh)
char message[BUFFER_SIZE];
snprintf(message, sizeof(message),
"{\"type\":\"tunnel_response\",\"request_id\":\"%s\",\"data\":\"%s\"}",
......@@ -418,7 +469,7 @@ void *forward_ws_to_local(void *arg) {
}
if (debug) {
printf("[DEBUG] WebSocket to local forwarding thread exiting\n");
printf("[DEBUG] SSH client to WebSocket forwarding thread exiting\n");
fflush(stdout);
}
......@@ -531,6 +582,12 @@ void handle_tunnel_data(SSL *ssl __attribute__((unused)), const char *request_id
data_len, target_sock, strerror(errno), errno);
fflush(stdout);
}
// If send fails, mark tunnel as inactive
pthread_mutex_lock(&tunnel_mutex);
if (active_tunnel) {
active_tunnel->active = 0;
}
pthread_mutex_unlock(&tunnel_mutex);
} else if (debug) {
if ((size_t)sent != data_len) {
printf("[DEBUG] Partial send: sent %zd of %zu bytes to socket %d\n", sent, data_len, target_sock);
......
......@@ -53,6 +53,8 @@ int frame_buffer_consume(frame_buffer_t *fb, size_t len);
void *forward_tcp_to_ws(void *arg);
void *forward_ws_to_local(void *arg);
void *accept_ssh_connection(void *arg);
void *forward_ws_to_ssh_client(void *arg);
void *tunnel_thread(void *arg);
void handle_tunnel_request(SSL *ssl, const char *request_id, int debug);
void handle_tunnel_data(SSL *ssl, const char *request_id, const char *data_hex, int debug);
......
......@@ -675,9 +675,13 @@ int main(int argc, char *argv[]) {
}
// Handle messages
if (strstr(payload, "tunnel_data")) {
if (strstr(payload, "tunnel_data") || strstr(payload, "tunnel_response")) {
if (config.debug) {
if (strstr(payload, "tunnel_data")) {
printf("[DEBUG] Received tunnel_data message\n");
} else {
printf("[DEBUG] Received tunnel_response message\n");
}
fflush(stdout);
}
// Extract request_id and data
......
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