Add extensive debug logging for control channel messages in wssshd and wssshc

- wssshd (websocket.py): Log full JSON content of all received and sent control channel messages when --debug enabled
- wssshc: Verified existing debug logging for control messages
- Fixed wsssht script mode data forwarding for tunnel_response messages
- Suppressed data channel message output in script mode for clean JSON protocol
- Fixed wsssht daemon mode to properly handle multiple connections and wait indefinitely
parent 4614c081
No preview for this file type
......@@ -841,7 +841,7 @@ int run_script_mode(wsssh_config_t *config, const char *client_id, const char *w
}
int run_daemon_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port) {
// Daemon mode: Lazy tunnel establishment
// Daemon mode: Lazy tunnel establishment - bind port immediately, establish tunnel on connection
if (config->debug) {
printf("[DEBUG] Starting daemon mode with lazy tunnel establishment\n");
fflush(stdout);
......@@ -912,30 +912,67 @@ int run_daemon_mode(wsssh_config_t *config, const char *client_id, const char *w
fflush(stdout);
}
// Wait for first connection
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int accepted_sock = accept(listen_sock, (struct sockaddr *)&client_addr, &client_len);
if (accepted_sock < 0) {
perror("Local accept failed");
close(listen_sock);
return 1;
}
// Daemon mode main loop - accept connections and establish tunnels
int daemon_restart = 0;
do {
daemon_restart = 0;
// Check for SIGINT
if (sigint_received) {
if (config->debug) {
printf("[DEBUG] SIGINT received in daemon mode, exiting\n");
fflush(stdout);
}
daemon_restart = 0;
break;
}
close(listen_sock); // No longer needed
// Wait for connection with timeout
fd_set readfds;
struct timeval tv;
FD_ZERO(&readfds);
FD_SET(listen_sock, &readfds);
tv.tv_sec = 1; // 1 second timeout to check for signals
tv.tv_usec = 0;
int retval = select(listen_sock + 1, &readfds, NULL, NULL, &tv);
if (retval < 0) {
if (errno == EINTR) {
// Interrupted by signal, continue to check sigint_received
continue;
}
perror("Select failed in daemon mode");
// In daemon mode, don't exit on select errors, wait a bit and retry
sleep(1);
continue;
} else if (retval == 0) {
// Timeout, continue loop to check signals
continue;
}
if (config->debug) {
printf("[DEBUG] Connection received, establishing tunnel...\n");
fflush(stdout);
}
// Accept connection
struct sockaddr_in client_addr;
socklen_t client_len = sizeof(client_addr);
int accepted_sock = accept(listen_sock, (struct sockaddr *)&client_addr, &client_len);
if (accepted_sock < 0) {
if (errno == EINTR) {
continue;
}
perror("Local accept failed");
continue; // Don't exit on accept failure, keep listening
}
// Now establish the tunnel
int tunnel_sock = setup_tunnel(wssshd_host, wssshd_port, client_id, local_port, config->debug, 0, config->tunnel_host);
if (tunnel_sock < 0) {
fprintf(stderr, "Failed to establish tunnel in daemon mode\n");
close(accepted_sock);
return 1;
}
if (config->debug) {
printf("[DEBUG] Connection received on port %d, establishing tunnel...\n", local_port);
fflush(stdout);
}
// Now establish the tunnel for this connection
int tunnel_sock = setup_tunnel(wssshd_host, wssshd_port, client_id, local_port, config->debug, 0, config->tunnel_host);
if (tunnel_sock < 0) {
fprintf(stderr, "Failed to establish tunnel for connection\n");
close(accepted_sock);
continue; // Don't exit, keep listening for new connections
}
// Print tunnel information (unless silent mode)
if (config->mode != MODE_SILENT) {
......@@ -1023,8 +1060,8 @@ int run_daemon_mode(wsssh_config_t *config, const char *client_id, const char *w
// Main tunnel loop - handle WebSocket messages
char buffer[BUFFER_SIZE];
int bytes_read;
fd_set readfds;
struct timeval tv;
fd_set tunnel_readfds;
struct timeval tunnel_tv;
int tunnel_broken = 0;
// Frame accumulation buffer for handling partial WebSocket frames
......@@ -1089,12 +1126,12 @@ int run_daemon_mode(wsssh_config_t *config, const char *client_id, const char *w
pthread_mutex_unlock(&tunnel_mutex);
// Use select to wait for data on SSL socket with timeout
FD_ZERO(&readfds);
FD_SET(ssl_fd, &readfds);
tv.tv_sec = 0;
tv.tv_usec = 50000; // 50ms timeout
FD_ZERO(&tunnel_readfds);
FD_SET(ssl_fd, &tunnel_readfds);
tunnel_tv.tv_sec = 0;
tunnel_tv.tv_usec = 50000; // 50ms timeout
int retval = select(ssl_fd + 1, &readfds, NULL, NULL, &tv);
int retval = select(ssl_fd + 1, &tunnel_readfds, NULL, NULL, &tunnel_tv);
if (retval == -1) {
if (config->debug) {
perror("[DEBUG - WebSockets] select on SSL fd failed");
......@@ -1125,7 +1162,7 @@ int run_daemon_mode(wsssh_config_t *config, const char *client_id, const char *w
}
// Read more data if we don't have a complete frame
if (FD_ISSET(ssl_fd, &readfds)) {
if (FD_ISSET(ssl_fd, &tunnel_readfds)) {
if ((size_t)frame_buffer_used < sizeof(frame_buffer)) {
// Validate SSL connection state
if (SSL_get_shutdown(current_ssl) & SSL_RECEIVED_SHUTDOWN) {
......@@ -1446,7 +1483,18 @@ cleanup_and_exit:
fflush(stdout);
}
return tunnel_broken ? 1 : 0;
// In daemon mode, restart to accept new connections instead of exiting
if (config->daemon) {
daemon_restart = 1;
}
if (!daemon_restart) {
return tunnel_broken ? 1 : 0;
}
} while (daemon_restart);
// This should never be reached, but just in case
return 0;
}
int main(int argc, char *argv[]) {
......
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