Commit 8feb3370 authored by nextime's avatar nextime

Version 1.3.2: Add wssshd configuration file support

- Added system-wide config file /etc/wssshd.conf for wssshd daemon
- Default jhost, port, password, domain, web-port, web-host, web-https settings
- Command line arguments take precedence over config file values
- Updated documentation and version numbers
- Enhanced wssshc config file support from version 1.3.1
parent 3c9ab553
......@@ -5,6 +5,51 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.3.2] - 2025-09-13
### Added
- **wssshd Configuration File Support**: Added INI-formatted config file `/etc/wssshd.conf` for wssshd daemon
- Default jhost, port, password, domain, web-port, web-host, and web-https settings
- Command line arguments take precedence over config file values
- System-wide configuration for server deployment
- **Enhanced wssshd Deployment**: wssshd now supports config file for easier system integration
- Support for all daemon parameters in config file
- Automatic config file detection at `/etc/wssshd.conf`
- Improved server configuration management
### Changed
- **wssshd Parameter Handling**: Command line options override config file values, config file provides defaults
- **wssshd Configuration**: Added system-wide config file support for better deployment practices
- **Cross-Component Consistency**: All components now support config file configuration
### Technical Details
- **Config File Location**: `/etc/wssshd.conf` for system-wide wssshd configuration
- **Config File Format**: INI format with `[wssshd]` section
- **Implementation**: Added config file parsing to wssshd.py using configparser
- **Backward Compatibility**: All existing functionality preserved, config file is optional
## [1.3.1] - 2025-09-13
### Added
- **wssshc Configuration File Support**: Extended INI-formatted config file `~/.config/wsssh/wssshc.conf` to include wssshc parameters
- Default password, domain, server-ip, port, and id settings for wssshc
- Command line arguments take precedence over config file values
- Optional parameters become required only when not provided in config or command line
- **Enhanced wssshc Flexibility**: wssshc now supports config file defaults for all parameters
- Support for both `server-ip` and `domain` config options (server-ip takes precedence)
- Automatic fallback to config values when command line options are omitted
- Improved user experience with optional command line parameters
### Changed
- **wssshc Parameter Handling**: Command line options override config file values, config file provides defaults
- **wssshc Error Messages**: Updated to reflect optional nature of parameters when config is available
- **Cross-Implementation Consistency**: Both Python and C versions of wssshc support identical config file format
### Technical Details
- **Config File Format**: Extended INI format with `[wssshc]` section for wssshc-specific parameters
- **Implementation**: Added config file parsing to both Python (configparser) and C (custom parser) versions
- **Backward Compatibility**: All existing functionality preserved, config file is optional
## [1.3.0] - 2025-09-13
### Added
......
......@@ -209,11 +209,44 @@ Input: hostname (e.g., "myclient.example.com:9898")
wssshd --host HOST --port PORT --domain DOMAIN --password PASS [--web-host HOST --web-port PORT] [--web-https] [--debug]
```
- `--host HOST`: Bind address for WebSocket server (default: 0.0.0.0)
- `--port PORT`: WebSocket server port (required)
- `--domain DOMAIN`: Domain suffix for hostname parsing (required)
- `--host HOST`: Bind address for WebSocket server
- `--port PORT`: WebSocket server port
- `--domain DOMAIN`: Domain suffix for hostname parsing
- `--password PASS`: Registration password
- `--web-host HOST`: Web interface host (optional)
- `--web-port PORT`: Web interface port (optional)
- `--web-https`: Enable HTTPS for web interface
- `--debug`: Enable debug output
#### Configuration File
wssshd supports a system-wide INI-formatted configuration file at `/etc/wssshd.conf`:
```ini
[wssshd]
jhost = 0.0.0.0
port = 9898
password = mysecret
domain = example.com
web-host = 0.0.0.0
web-port = 8080
web-https = false
```
**Configuration Options:**
- `jhost`: Default WebSocket server bind address
- `port`: Default WebSocket server port
- `password`: Default registration password
- `domain`: Default domain suffix for hostname parsing
- `web-host`: Default web interface bind address
- `web-port`: Default web interface port
- `web-https`: Enable HTTPS for web interface (true/false)
**Precedence Rules:**
- Command line options override configuration file values
- Configuration file provides defaults when command line options are not specified
- Required parameters must be provided either via command line or configuration file
#### WebSocket Endpoints
- `ws://HOST:PORT/`: Main WebSocket endpoint for client connections
......@@ -226,12 +259,38 @@ wssshd --host HOST --port PORT --domain DOMAIN --password PASS [--web-host HOST
wssshc --server-ip IP --port PORT --id ID --password PASS [--interval SEC] [--debug]
```
- `--server-ip IP`: wssshd server IP address (required)
- `--port PORT`: wssshd server port (required)
- `--id ID`: Unique client identifier (required)
- `--server-ip IP`: wssshd server IP address
- `--port PORT`: wssshd server port (default: 9898)
- `--id ID`: Unique client identifier
- `--password PASS`: Registration password
- `--interval SEC`: Reconnection interval in seconds (default: 30)
- `--debug`: Enable debug output
#### Configuration File
wssshc supports an optional INI-formatted configuration file at `~/.config/wsssh/wssshc.conf`:
```ini
[wssshc]
password = mysecret
domain = example.com
server-ip = 192.168.1.100
port = 9898
id = client1
```
**Configuration Options:**
- `password`: Default registration password
- `domain`: Default domain suffix (fallback for server-ip)
- `server-ip`: Default wssshd server IP address
- `port`: Default wssshd server port
- `id`: Default client identifier
**Precedence Rules:**
- Command line options override configuration file values
- Configuration file provides defaults when command line options are not specified
- Required parameters must be provided either via command line or configuration file
### wsssh (SSH Wrapper)
#### Command Line Options
......
......@@ -190,18 +190,35 @@ Port is specified using `-p` (SSH) or `-P` (SCP) options, or from config file.
### wssshd (WebSocket SSH Daemon)
```bash
./wssshd --host 0.0.0.0 --port 9898 --domain example.com --password mysecret [--web-host 0.0.0.0 --web-port 8080] [--debug]
./wssshd --host 0.0.0.0 --port 9898 --domain example.com --password mysecret [--web-host 0.0.0.0 --web-port 8080] [--web-https] [--debug]
```
**Options:**
- `--host`: Bind address (default: 0.0.0.0)
- `--port`: WebSocket port (required)
- `--host`: Bind address
- `--port`: WebSocket port
- `--domain`: Domain suffix for hostname parsing
- `--password`: Registration password (required)
- `--password`: Registration password
- `--web-host`: Web interface bind address (optional)
- `--web-port`: Web interface port (optional)
- `--web-https`: Enable HTTPS for web interface
- `--debug`: Enable debug output
**Configuration File:**
wssshd supports a system-wide configuration file at `/etc/wssshd.conf`:
```ini
[wssshd]
jhost = 0.0.0.0
port = 9898
password = mysecret
domain = example.com
web-host = 0.0.0.0
web-port = 8080
web-https = false
```
Command line options override configuration file values. Required parameters are only mandatory when not provided in either the config file or command line.
**Web Interface:**
When `--web-host` and `--web-port` are specified, a web management interface is available with:
- User authentication (default: admin/admin123)
......@@ -216,13 +233,27 @@ When `--web-host` and `--web-port` are specified, a web management interface is
```
**Options:**
- `--server-ip`: wssshd server IP address (required)
- `--port`: wssshd server port (required)
- `--id`: Unique client identifier (required)
- `--password`: Registration password (required)
- `--server-ip`: wssshd server IP address
- `--port`: wssshd server port (default: 9898)
- `--id`: Unique client identifier
- `--password`: Registration password
- `--interval`: Reconnection interval in seconds (default: 30)
- `--debug`: Enable debug output
**Configuration File:**
wssshc supports an optional configuration file at `~/.config/wsssh/wssshc.conf`:
```ini
[wssshc]
password = mysecret
domain = example.com
server-ip = 192.168.1.100
port = 9898
id = client1
```
Command line options override configuration file values. Required parameters are only mandatory when not provided in either the config file or command line.
### wsssh (SSH Wrapper)
```bash
......
......@@ -25,6 +25,8 @@ import ssl
import websockets
import json
import socket
import configparser
import os
debug = False
......@@ -111,15 +113,42 @@ async def connect_to_server(server_ip, port, client_id, password, interval):
await asyncio.sleep(interval)
def main():
config = configparser.ConfigParser()
config_path = os.path.expanduser('~/.config/wsssh/wssshc.conf')
defaults = {'interval': 30, 'port': 9898}
if os.path.exists(config_path):
config.read(config_path)
if 'wssshc' in config:
section = config['wssshc']
for key in ['password', 'id']:
if key in section:
defaults[key] = section[key]
if 'server-ip' in section:
defaults['server_ip'] = section['server-ip']
elif 'domain' in section:
defaults['server_ip'] = section['domain']
if 'port' in section:
defaults['port'] = int(section['port'])
parser = argparse.ArgumentParser(description='WebSocket SSH Client (wssshc)')
parser.add_argument('--server-ip', required=True, help='Server IP address')
parser.add_argument('--port', type=int, required=True, help='Server port')
parser.add_argument('--id', required=True, help='Client ID')
parser.add_argument('--password', required=True, help='Registration password')
parser.add_argument('--interval', type=int, default=30, help='Reconnect interval in seconds (default: 30)')
parser.set_defaults(**defaults)
parser.add_argument('--server-ip', help='Server IP address')
parser.add_argument('--port', type=int, help='Server port')
parser.add_argument('--id', help='Client ID')
parser.add_argument('--password', help='Registration password')
parser.add_argument('--interval', type=int, help='Reconnect interval in seconds (default: 30)')
parser.add_argument('--debug', action='store_true', help='Enable debug output')
args = parser.parse_args()
# Check required arguments
if not args.server_ip:
parser.error('--server-ip is required')
if not args.id:
parser.error('--id is required')
if not args.password:
parser.error('--password is required')
global debug
debug = args.debug
......
[wssshd]
jhost = 0.0.0.0
port = 9898
password = mysecret
domain = example.com
web-host = 0.0.0.0
web-port = 8080
web-https = false
\ No newline at end of file
......@@ -34,6 +34,7 @@ import select
import fcntl
import termios
import stat
import configparser
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, send_from_directory
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_sqlalchemy import SQLAlchemy
......@@ -465,11 +466,33 @@ async def handle_websocket(websocket, path=None):
del active_tunnels[request_id]
async def main():
config = configparser.ConfigParser()
config_path = '/etc/wssshd.conf'
defaults = {}
if os.path.exists(config_path):
config.read(config_path)
if 'wssshd' in config:
section = config['wssshd']
for key in ['password', 'domain']:
if key in section:
defaults[key] = section[key]
if 'jhost' in section: # Map jhost to host
defaults['host'] = section['jhost']
if 'port' in section:
defaults['port'] = int(section['port'])
if 'web-host' in section:
defaults['web_host'] = section['web-host']
if 'web-port' in section:
defaults['web_port'] = int(section['web-port'])
if 'web-https' in section:
defaults['web_https'] = section.getboolean('web-https', False)
parser = argparse.ArgumentParser(description='WebSocket SSH Daemon (wssshd)')
parser.add_argument('--host', required=True, help='WebSocket server host')
parser.add_argument('--port', type=int, required=True, help='WebSocket server port')
parser.add_argument('--domain', required=True, help='Base domain name')
parser.add_argument('--password', required=True, help='Registration password')
parser.set_defaults(**defaults)
parser.add_argument('--host', help='WebSocket server host')
parser.add_argument('--port', type=int, help='WebSocket server port')
parser.add_argument('--domain', help='Base domain name')
parser.add_argument('--password', help='Registration password')
parser.add_argument('--web-host', help='Web interface host (optional)')
parser.add_argument('--web-port', type=int, help='Web interface port (optional)')
parser.add_argument('--web-https', action='store_true', help='Enable HTTPS for web interface')
......@@ -477,6 +500,21 @@ async def main():
global args
args = parser.parse_args()
# Handle web-https from config if not specified on command line
if 'web_https' in defaults and not any(arg.startswith('--web-https') for arg in sys.argv):
args.web_https = defaults['web_https']
# Check required arguments
if not args.host:
parser.error('--host is required')
if not args.port:
parser.error('--port is required')
if not args.domain:
parser.error('--domain is required')
if not args.password:
parser.error('--password is required')
global debug
debug = args.debug
global server_password
......
wsssh-tools (1.3.2-1) unstable; urgency=medium
* Version 1.3.2: Added configuration file support to wssshd
* Added system-wide config file /etc/wssshd.conf for wssshd daemon
* Default jhost, port, password, domain, web-port, web-host, web-https settings
* Command line arguments take precedence over config file values
* Improved server deployment and configuration management
-- Stefy Lanza <stefy@nexlab.net> Fri, 13 Sep 2025 15:50:00 +0200
wsssh-tools (1.3.1-1) unstable; urgency=medium
* Version 1.3.1: Extended configuration file support to wssshc
* Added wssshc parameters to ~/.config/wsssh/wssshc.conf
* Default password, domain, server-ip, port, and id settings for wssshc
* Command line arguments take precedence over config file values
* Optional parameters become required only when not provided in config
-- Stefy Lanza <stefy@nexlab.net> Fri, 13 Sep 2025 15:45:00 +0200
wsssh-tools (1.3.0-1) unstable; urgency=medium
* Version 1.3.0: Added configuration file support
......
.TH WSSCP 1 "September 2024" "wsssh-tools 1.1.0" "WebSocket SSH Tools"
.TH WSSCP 1 "September 2025" "wsssh-tools 1.3.2" "WebSocket SSH Tools"
.SH NAME
wsscp \- WebSocket SCP wrapper for secure file transfer
.SH SYNOPSIS
......
.TH WSSH 1 "September 2024" "wsssh-tools 1.1.0" "WebSocket SSH Tools"
.TH WSSH 1 "September 2025" "wsssh-tools 1.3.2" "WebSocket SSH Tools"
.SH NAME
wsssh \- WebSocket SSH wrapper for secure tunneling
.SH SYNOPSIS
......
.TH WSSHc 1 "September 2024" "wsssh-tools 1.1.0" "WebSocket SSH Tools"
.TH WSSHc 1 "September 2025" "wsssh-tools 1.3.2" "WebSocket SSH Tools"
.SH NAME
wssshc \- WebSocket SSH Client for registration
.SH SYNOPSIS
......@@ -13,19 +13,25 @@ wssshc \- WebSocket SSH Client for registration
.SH DESCRIPTION
.B wssshc
is a lightweight client for registering machines with a WebSocket SSH daemon (wssshd). It establishes a persistent WebSocket connection and maintains registration with the server, allowing SSH/SCP tunneling through the registered machine.
.PP
Configuration can be provided via command line options or an optional INI-formatted configuration file at
.B ~/.config/wsssh/wssshc.conf
with a
.B [wssshc]
section. Command line options take precedence over configuration file values.
.SH OPTIONS
.TP
.BR \-\-server\-ip " \fIIP\fR"
IP address of the wssshd server (required)
IP address or hostname of the wssshd server
.TP
.BR \-\-port " \fIPORT\fR"
Port number of the wssshd server (default: 9898)
.TP
.BR \-\-id " \fIID\fR"
Unique client identifier for registration (required)
Unique client identifier for registration
.TP
.BR \-\-password " \fIPASSWORD\fR"
Registration password for authentication (required)
Registration password for authentication
.TP
.BR \-\-interval " \fISECONDS\fR"
Reconnection interval in seconds if connection is lost (default: 30)
......@@ -35,6 +41,21 @@ Enable debug output for troubleshooting
.TP
.B \-\-help
Display help message and exit
.SH CONFIGURATION
Configuration can be specified in
.B ~/.config/wsssh/wssshc.conf
using INI format:
.PP
.nf
[wssshc]
password = yourpassword
domain = example.com
server-ip = 192.168.1.100
port = 9898
id = client01
.fi
.PP
Command line options override configuration file values. If neither configuration file nor command line provides a required value, the program will exit with an error.
.SH EXAMPLES
.TP
Register a client machine:
......
......@@ -53,6 +53,48 @@ typedef struct {
int debug;
} wssshc_config_t;
void load_config(wssshc_config_t *config) {
char path[256];
char *home = getenv("HOME");
if (!home) return;
snprintf(path, sizeof(path), "%s/.config/wsssh/wssshc.conf", home);
FILE *file = fopen(path, "r");
if (!file) return;
char line[256];
int in_section = 0;
while (fgets(line, sizeof(line), file)) {
line[strcspn(line, "\n")] = 0;
if (line[0] == '[' && strstr(line, "wssshc")) {
in_section = 1;
} else if (line[0] == '[') {
in_section = 0;
} else if (in_section && strchr(line, '=')) {
char *key = strtok(line, "=");
char *value = strtok(NULL, "=");
if (key && value) {
while (*key == ' ') key++;
char *end = key + strlen(key) - 1;
while (end > key && *end == ' ') *end-- = 0;
while (*value == ' ') value++;
end = value + strlen(value) - 1;
while (end > value && *end == ' ') *end-- = 0;
if (strcmp(key, "password") == 0 && !config->password) {
config->password = strdup(value);
} else if (strcmp(key, "server-ip") == 0 && !config->server_ip) {
config->server_ip = strdup(value);
} else if (strcmp(key, "domain") == 0 && !config->server_ip) {
config->server_ip = strdup(value);
} else if (strcmp(key, "port") == 0) {
config->port = atoi(value);
} else if (strcmp(key, "id") == 0 && !config->client_id) {
config->client_id = strdup(value);
}
}
}
}
fclose(file);
}
tunnel_t *active_tunnel = NULL;
void *tunnel_thread(void *arg);
......@@ -333,13 +375,15 @@ void print_usage(const char *program_name) {
fprintf(stderr, "WebSocket SSH Client - Register with wssshd server\n\n");
fprintf(stderr, "Protect the dolls!\n\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " --server-ip IP Server IP address (required)\n");
fprintf(stderr, " --server-ip IP Server IP address\n");
fprintf(stderr, " --port PORT Server port (default: %d)\n", DEFAULT_PORT);
fprintf(stderr, " --id ID Client identifier (required)\n");
fprintf(stderr, " --password PASS Registration password (required)\n");
fprintf(stderr, " --id ID Client identifier\n");
fprintf(stderr, " --password PASS Registration password\n");
fprintf(stderr, " --interval SEC Reconnection interval (default: 30)\n");
fprintf(stderr, " --debug Enable debug output\n");
fprintf(stderr, " --help Show this help\n");
fprintf(stderr, "\nConfiguration file: ~/.config/wsssh/wssshc.conf\n");
fprintf(stderr, "Command line options override configuration file values.\n");
fprintf(stderr, "\nDonations:\n");
fprintf(stderr, " BTC: bc1q3zlkpu95amtcltsk85y0eacyzzk29v68tgc5hx\n");
fprintf(stderr, " ETH: 0xdA6dAb526515b5cb556d20269207D43fcc760E51\n");
......@@ -361,15 +405,18 @@ int parse_args(int argc, char *argv[], wssshc_config_t *config) {
while ((opt = getopt_long(argc, argv, "s:p:i:w:t:dh", long_options, NULL)) != -1) {
switch (opt) {
case 's':
if (config->server_ip) free(config->server_ip);
config->server_ip = strdup(optarg);
break;
case 'p':
config->port = atoi(optarg);
break;
case 'i':
if (config->client_id) free(config->client_id);
config->client_id = strdup(optarg);
break;
case 'w':
if (config->password) free(config->password);
config->password = strdup(optarg);
break;
case 't':
......@@ -393,16 +440,6 @@ int parse_args(int argc, char *argv[], wssshc_config_t *config) {
}
}
// Validate required arguments
if (!config->server_ip || !config->client_id || !config->password) {
fprintf(stderr, "Error: --server-ip, --id, and --password are required\n");
print_usage(argv[0]);
if (config->server_ip) free(config->server_ip);
if (config->client_id) free(config->client_id);
if (config->password) free(config->password);
return 0;
}
return 1;
}
......@@ -943,11 +980,24 @@ int main(int argc, char *argv[]) {
pthread_mutex_init(&tunnel_mutex, NULL);
load_config(&config);
if (!parse_args(argc, argv, &config)) {
pthread_mutex_destroy(&tunnel_mutex);
return 1;
}
// Validate required arguments
if (!config.server_ip || !config.client_id || !config.password) {
fprintf(stderr, "Error: --server-ip, --id, and --password are required\n");
print_usage(argv[0]);
if (config.server_ip) free(config.server_ip);
if (config.client_id) free(config.client_id);
if (config.password) free(config.password);
pthread_mutex_destroy(&tunnel_mutex);
return 1;
}
global_debug = config.debug;
printf("WebSocket SSH Client starting...\n");
......
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