Add --config option and update config files

- Added --config FILE option to specify custom config file path
- Removed [wssht] section from wsssh.conf.example (legacy)
- Created separate wsssht.conf.example with wssht-specific options
- Updated man page with new --config option and mode options
- Updated usage message to include all new options
- Config file validation: errors if specified file doesn't exist
parent 2ed32275
......@@ -21,7 +21,7 @@
# service = ssh
[wsssh]
# WebSocket SSH Daemon domain (used for hostname parsing)
# WebSocket SSH Daemon domain (legacy, used for hostname parsing in wsssh)
domain = example.com
# Transport types for data channel (comma-separated or 'any')
......
# WebSocket SSH Tunnel (wsssht) Configuration Example
#
# This is an example configuration file for wsssht.
# Copy this file to ~/.config/wsssh/wssht.conf
# and modify the settings as needed.
# Copy this file to ~/.config/wsssh/wsssht.conf and modify the settings as needed.
#
# Configuration options:
# wssshd-host: Default wssshd server hostname
# wssshd-port: Default wssshd server port
# clientid: Default client ID for the tunnel
# tunnel-port: Default local tunnel port (0 = auto-assign)
# tunnel-host: Local IP address to bind tunnel to (default: 127.0.0.1)
# tunnel: Default transport for data channel (comma-separated or 'any', or 'websocket')
# tunnel-control: Default transport for control channel (comma-separated or 'any', or 'websocket')
# service: Default service type (default: ssh)
# interval: Connection retry interval in seconds (default: 5)
wssshd-host=mbetter.nexlab.net
wssshd-port=9898
clientid=myclient
tunnel-port=0
tunnel-host=127.0.0.1
tunnel=websocket
tunnel-control=websocket
service=ssh
interval=5
\ No newline at end of file
[wssht]
# wssshd server hostname
wssshd-host = mbetter.nexlab.net
# Client ID for the tunnel
clientid = myclient
# Operating mode: interactive, silent, bridge, script
mode = interactive
# Enable daemon mode (true/false)
daemon = false
# Transport types for data channel (comma-separated or 'any')
# Available transports: websocket
tunnel = any
# Transport types for control channel (comma-separated or 'any')
# Only transports with is_relay=true can be used for control
tunnel-control = any
# Service type (default: ssh)
service = ssh
# Local tunnel host (default: 127.0.0.1)
tunnel-host = 127.0.0.1
# Connection retry interval in seconds (default: 5)
interval = 5
\ No newline at end of file
......@@ -3,6 +3,7 @@
wsssht \- WebSocket SSH Tunnel Setup Tool
.SH SYNOPSIS
.B wsssht
[\fB\-\-config\fR \fIFILE\fR]
[\fB\-\-clientid\fR \fIID\fR]
[\fB\-\-tunnel\-port\fR \fIPORT\fR]
[\fB\-\-tunnel\-host\fR \fIHOST\fR]
......@@ -13,6 +14,11 @@ wsssht \- WebSocket SSH Tunnel Setup Tool
[\fB\-\-tunnel\fR \fITRANSPORT\fR]
[\fB\-\-tunnel\-control\fR \fITYPES\fR]
[\fB\-\-service\fR \fISERVICE\fR]
[\fB\-\-mode\fR \fIMODE\fR]
[\fB\-\-silent\fR]
[\fB\-\-bridge\fR]
[\fB\-\-script\fR]
[\fB\-\-daemon\fR]
[\fB\-\-help\fR]
[\fIservice://\fR]\fIclientid\fR[\fI@wssshd-host\fR][\fI:wssshd-port\fR]
.SH DESCRIPTION
......@@ -27,6 +33,9 @@ and
does not fork and execute external commands. Instead, it sets up the tunnel and displays connection instructions for manual use.
.SH OPTIONS
.TP
.BR \-\-config " \fIFILE\fR"
Use custom config file (takes precedence over default)
.TP
.BR \-\-clientid " \fIID\fR"
Specify the client ID for the tunnel (default: from config)
.TP
......@@ -57,6 +66,21 @@ Transport types for control channel (comma\-separated or 'any', default: any)
.BR \-\-service " \fISERVICE\fR"
Service type (default: ssh)
.TP
.BR \-\-mode " \fIMODE\fR"
Operating mode: interactive, silent, bridge, script (default: interactive)
.TP
.BR \-\-silent
Shortcut for --mode silent
.TP
.BR \-\-bridge
Shortcut for --mode bridge
.TP
.BR \-\-script
Shortcut for --mode script
.TP
.BR \-\-daemon
Enable daemon mode for lazy initialization
.TP
.BR \-\-help
Display help message and exit
.SH CONNECTION STRING FORMAT
......
......@@ -52,6 +52,14 @@ extern volatile sig_atomic_t sigint_received;
// SSL mutex for thread-safe SSL operations
extern pthread_mutex_t ssl_mutex;
// Operating modes
typedef enum {
MODE_INTERACTIVE = 0, // Default: current functionality
MODE_SILENT, // Same as interactive but no output
MODE_BRIDGE, // JSON stdin/stdout bridge
MODE_SCRIPT // JSON protocol for scripting
} wsssh_mode_t;
// Config structures
typedef struct {
char *local_port;
......@@ -65,6 +73,8 @@ typedef struct {
char *tunnel; // Transport types for data channel (comma-separated or "any")
char *tunnel_control; // Transport types for control channel (comma-separated or "any")
char *service; // Service type (default: "ssh")
wsssh_mode_t mode; // Operating mode
int daemon; // Daemon mode: lazy initialization
} wsssh_config_t;
typedef struct {
......
No preview for this file type
......@@ -45,6 +45,7 @@ void print_usage(const char *program_name) {
fprintf(stderr, "WebSocket SSH Tunnel - Setup WebSocket tunnels for manual connections\n\n");
fprintf(stderr, "Protect the dolls!\n\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " --config FILE Use custom config file (takes precedence over default)\n");
fprintf(stderr, " --clientid ID Client ID for the tunnel (default: from config)\n");
fprintf(stderr, " --tunnel-port PORT Local tunnel port (default: auto)\n");
fprintf(stderr, " --tunnel-host HOST Local IP address to bind tunnel to (default: 127.0.0.1)\n");
......@@ -55,12 +56,19 @@ void print_usage(const char *program_name) {
fprintf(stderr, " --tunnel TRANSPORT Transport for data channel (comma-separated or 'any', or 'websocket' default: any)\n");
fprintf(stderr, " --tunnel-control TYPES Transport types for control channel (comma-separated or 'any', default: any)\n");
fprintf(stderr, " --service SERVICE Service type (default: ssh)\n");
fprintf(stderr, " --mode MODE Operating mode: interactive, silent, bridge, script (default: interactive)\n");
fprintf(stderr, " --silent Shortcut for --mode silent\n");
fprintf(stderr, " --bridge Shortcut for --mode bridge\n");
fprintf(stderr, " --script Shortcut for --mode script\n");
fprintf(stderr, " --daemon Enable daemon mode for lazy initialization\n");
fprintf(stderr, " --help Show this help\n");
fprintf(stderr, "\nExamples:\n");
fprintf(stderr, " %s --clientid myclient --wssshd-host mbetter.nexlab.net\n", program_name);
fprintf(stderr, " %s myclient@mbetter.nexlab.net:9898\n", program_name);
fprintf(stderr, " %s ssh://myclient@mbetter.nexlab.net\n", program_name);
fprintf(stderr, " %s --tunnel websocket myclient@mbetter.nexlab.net\n", program_name);
fprintf(stderr, " %s --silent myclient@mbetter.nexlab.net\n", program_name);
fprintf(stderr, " %s --daemon --clientid myclient --wssshd-host mbetter.nexlab.net\n", program_name);
fprintf(stderr, "\nDonations:\n");
fprintf(stderr, " BTC: bc1q3zlkpu95amtcltsk85y0eacyzzk29v68tgc5hx\n");
fprintf(stderr, " ETH: 0xdA6dAb526515b5cb556d20269207D43fcc760E51\n");
......@@ -114,9 +122,13 @@ int parse_connection_string(const char *conn_str, char **service, char **client_
int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_argc, char ***remaining_argv) {
// Parse wsssht options and optional connection string
int target_start = -1;
char *custom_config = NULL;
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--clientid") == 0 && i + 1 < argc) {
if (strcmp(argv[i], "--config") == 0 && i + 1 < argc) {
custom_config = strdup(argv[i + 1]);
i++; // Skip the argument
} else if (strcmp(argv[i], "--clientid") == 0 && i + 1 < argc) {
if (config->client_id) free(config->client_id);
config->client_id = strdup(argv[i + 1]);
i++; // Skip the argument
......@@ -151,6 +163,29 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar
i++; // Skip the argument
} else if (strcmp(argv[i], "--debug") == 0) {
config->debug = 1;
} else if (strcmp(argv[i], "--mode") == 0 && i + 1 < argc) {
if (strcmp(argv[i + 1], "interactive") == 0) {
config->mode = MODE_INTERACTIVE;
} else if (strcmp(argv[i + 1], "silent") == 0) {
config->mode = MODE_SILENT;
} else if (strcmp(argv[i + 1], "bridge") == 0) {
config->mode = MODE_BRIDGE;
} else if (strcmp(argv[i + 1], "script") == 0) {
config->mode = MODE_SCRIPT;
} else {
fprintf(stderr, "Error: Invalid mode: %s\n", argv[i + 1]);
print_usage(argv[0]);
return 0;
}
i++; // Skip the argument
} else if (strcmp(argv[i], "--daemon") == 0) {
config->daemon = 1;
} else if (strcmp(argv[i], "--silent") == 0) {
config->mode = MODE_SILENT;
} else if (strcmp(argv[i], "--bridge") == 0) {
config->mode = MODE_BRIDGE;
} else if (strcmp(argv[i], "--script") == 0) {
config->mode = MODE_SCRIPT;
} else if (strcmp(argv[i], "--help") == 0 || strcmp(argv[i], "-h") == 0) {
print_usage(argv[0]);
return 0;
......@@ -172,6 +207,21 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar
}
}
// Handle custom config file if specified
if (custom_config) {
// TODO: Implement custom config file loading
// For now, just validate the file exists
FILE *test = fopen(custom_config, "r");
if (!test) {
fprintf(stderr, "Error: Config file not found: %s\n", custom_config);
free(custom_config);
return 0;
}
fclose(test);
fprintf(stderr, "Warning: Custom config file support not yet implemented\n");
free(custom_config);
}
// Handle connection string if present
if (target_start != -1) {
char *service = NULL;
......@@ -224,17 +274,75 @@ int parse_args(int argc, char *argv[], wsssh_config_t *config, int *remaining_ar
int run_bridge_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port) {
// Bridge mode: JSON messages to/from stdin/stdout
if (config->debug) {
printf("[DEBUG] Starting bridge mode\n");
fflush(stdout);
}
// TODO: Implement bridge mode
// - Establish websocket connection
// - Forward JSON messages from wssshd to stdout
// - Forward JSON messages from stdin to wssshd
// - Handle tunnel_data and tunnel_response messages
fprintf(stderr, "Bridge mode not yet implemented\n");
return 1;
}
int run_script_mode(wsssh_config_t *config, const char *client_id, const char *wssshd_host, int wssshd_port) {
// Script mode: JSON protocol for scripting
if (config->debug) {
printf("[DEBUG] Starting script mode\n");
fflush(stdout);
}
// TODO: Implement script mode
// - Establish websocket connection
// - Send JSON status messages to stdout
// - Accept JSON commands from stdin
// - Handle tunnel lifecycle events
fprintf(stderr, "Script mode not yet implemented\n");
return 1;
}
int main(int argc, char *argv[]) {
// Read config from wsssht.conf
char *config_domain = read_config_value_from_file("wssshd-host", "wsssht");
char *config_clientid = read_config_value_from_file("clientid", "wsssht");
char *config_wssshd_port = read_config_value_from_file("wssshd-port", "wsssht");
char *config_mode = read_config_value_from_file("mode", "wsssht");
char *config_daemon = read_config_value_from_file("daemon", "wsssht");
char *config_tunnel = read_config_value_from_file("tunnel", "wsssht");
char *config_tunnel_control = read_config_value_from_file("tunnel-control", "wsssht");
char *config_service = read_config_value_from_file("service", "wsssht");
char *config_tunnel_host = read_config_value_from_file("tunnel-host", "wsssht");
char *config_interval = read_config_value_from_file("interval", "wsssht");
// Parse mode from config
wsssh_mode_t initial_mode = MODE_INTERACTIVE;
if (config_mode) {
if (strcmp(config_mode, "silent") == 0) {
initial_mode = MODE_SILENT;
} else if (strcmp(config_mode, "bridge") == 0) {
initial_mode = MODE_BRIDGE;
} else if (strcmp(config_mode, "script") == 0) {
initial_mode = MODE_SCRIPT;
}
free(config_mode);
}
// Parse daemon from config
int initial_daemon = 0;
if (config_daemon) {
if (strcmp(config_daemon, "true") == 0 || strcmp(config_daemon, "1") == 0) {
initial_daemon = 1;
}
free(config_daemon);
}
wsssh_config_t config = {
.local_port = NULL,
.tunnel_host = config_tunnel_host,
......@@ -246,7 +354,9 @@ int main(int argc, char *argv[]) {
.dev_tunnel = 0,
.tunnel = config_tunnel,
.tunnel_control = config_tunnel_control,
.service = config_service
.service = config_service,
.mode = initial_mode,
.daemon = initial_daemon
};
// Set defaults if not provided
......@@ -273,6 +383,8 @@ int main(int argc, char *argv[]) {
free(config_domain);
free(config_clientid);
free(config_wssshd_port);
free(config_mode);
free(config_daemon);
return 0;
}
......@@ -283,12 +395,16 @@ int main(int argc, char *argv[]) {
free(config_domain);
free(config_clientid);
free(config_wssshd_port);
free(config_mode);
free(config_daemon);
return 0;
} else if (strcmp(argv[i], "--free") == 0) {
print_palestinian_flag();
free(config_domain);
free(config_clientid);
free(config_wssshd_port);
free(config_mode);
free(config_daemon);
return 0;
}
}
......@@ -348,6 +464,14 @@ int main(int argc, char *argv[]) {
fflush(stdout);
}
// Handle different operating modes
if (config.mode == MODE_BRIDGE) {
return run_bridge_mode(&config, client_id, wssshd_host, wssshd_port);
} else if (config.mode == MODE_SCRIPT) {
return run_script_mode(&config, client_id, wssshd_host, wssshd_port);
}
// MODE_INTERACTIVE and MODE_SILENT continue with normal flow
// Find available local port
int local_port = config.local_port ? atoi(config.local_port) : find_available_port();
if (local_port == 0) {
......@@ -401,35 +525,37 @@ int main(int argc, char *argv[]) {
return 1;
}
// Print tunnel information and connection instructions
printf("\n");
printf("========================================\n");
printf(" WEBSSH TUNNEL READY\n");
printf("========================================\n");
printf("Tunnel established successfully!\n");
printf("Local port: %d\n", local_port);
printf("Target: %s@%s\n", client_id, wssshd_host);
printf("\n");
printf("Connect manually using one of these commands:\n");
printf("\n");
printf(" Telnet:\n");
printf(" telnet localhost %d\n", local_port);
printf("\n");
printf(" Netcat:\n");
printf(" nc localhost %d\n", local_port);
printf("\n");
printf(" SSH (if connecting to SSH server):\n");
printf(" ssh -p %d user@localhost\n", local_port);
printf("\n");
printf(" SCP (if connecting to SSH server):\n");
printf(" scp -P %d user@localhost:/remote/path ./local/path\n", local_port);
printf("\n");
printf(" Any TCP client:\n");
printf(" Connect to localhost:%d\n", local_port);
printf("\n");
printf("Press Ctrl+C to close the tunnel and exit.\n");
printf("========================================\n");
printf("\n");
// Print tunnel information and connection instructions (unless silent mode)
if (config.mode != MODE_SILENT) {
printf("\n");
printf("========================================\n");
printf(" WEBSSH TUNNEL READY\n");
printf("========================================\n");
printf("Tunnel established successfully!\n");
printf("Local port: %d\n", local_port);
printf("Target: %s@%s\n", client_id, wssshd_host);
printf("\n");
printf("Connect manually using one of these commands:\n");
printf("\n");
printf(" Telnet:\n");
printf(" telnet localhost %d\n", local_port);
printf("\n");
printf(" Netcat:\n");
printf(" nc localhost %d\n", local_port);
printf("\n");
printf(" SSH (if connecting to SSH server):\n");
printf(" ssh -p %d user@localhost\n", local_port);
printf("\n");
printf(" SCP (if connecting to SSH server):\n");
printf(" scp -P %d user@localhost:/remote/path ./local/path\n", local_port);
printf("\n");
printf(" Any TCP client:\n");
printf(" Connect to localhost:%d\n", local_port);
printf("\n");
printf("Press Ctrl+C to close the tunnel and exit.\n");
printf("========================================\n");
printf("\n");
}
// Start forwarding threads to handle bidirectional communication
// Parent process: accept connection and start forwarding
......
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