Add C implementation and Debian packaging

- Added wssshtools/ directory with C implementations:
  * wssshc.c - WebSocket SSH client (registration)
  * wsssh.c - SSH wrapper for tunneling
  * wsscp.c - SCP wrapper for tunneling
  * configure.sh - Build configuration script
  * Makefile - Build system

- Added Debian packaging:
  * debian/control - Package metadata and dependencies
  * debian/rules - Build rules
  * debian/changelog - Package changelog
  * debian/copyright - Copyright information
  * debian/compat - Debhelper compatibility level

- Updated build.sh to support C builds and Debian packaging (--debian flag)
- Updated clean.sh to clean C artifacts and Debian build files
- Updated .gitignore to exclude C build artifacts and Debian files
- All C tools use OpenSSL for SSL/TLS WebSocket connections
parent cc2c35e9
......@@ -3,6 +3,24 @@ build/
dist/
*.spec
# C build artifacts
wssshtools/*.o
wssshtools/wssshc
wssshtools/wsssh
wssshtools/wsscp
wssshtools/Makefile
wssshtools/configure.sh.stamp
# Debian packaging artifacts
wssshtools/debian/wsssh-tools/
wssshtools/debian/files
wssshtools/debian/*.debhelper
wssshtools/debian/*.substvars
*.deb
*.dsc
*.tar.gz
*.changes
# SSL certificates (generated during build)
cert.pem
key.pem
......
#!/bin/bash
# Parse command line arguments
BUILD_DEBIAN=false
while [[ $# -gt 0 ]]; do
case $1 in
--debian)
BUILD_DEBIAN=true
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: $0 [--debian]"
exit 1
;;
esac
done
# Check if virtual environment exists, create if not
if [ ! -d "venv" ]; then
echo "Creating virtual environment..."
......@@ -25,6 +41,9 @@ if [ ! -f "cert.pem" ] || [ ! -f "key.pem" ]; then
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"
fi
# Build Python binaries
echo "Building Python binaries..."
# Build wssshd (server) binary with certificates and web assets
pyinstaller --onefile --distpath dist --add-data "cert.pem:." --add-data "key.pem:." --add-data "templates:templates" --add-data "static:static" --runtime-tmpdir /tmp --clean wssshd.py
......@@ -37,6 +56,34 @@ pyinstaller --onefile --distpath dist --runtime-tmpdir /tmp --clean wsssh.py
# Build wsscp binary
pyinstaller --onefile --distpath dist --runtime-tmpdir /tmp --clean wsscp.py
# Build C version if wssshtools directory exists
if [ -d "wssshtools" ]; then
echo "Building C version..."
cd wssshtools
if [ -f "configure.sh" ]; then
./configure.sh
make
cd ..
else
echo "Warning: configure.sh not found in wssshtools/"
cd ..
fi
fi
# Build Debian package if requested
if [ "$BUILD_DEBIAN" = true ]; then
echo "Building Debian package..."
if [ -d "wssshtools" ] && [ -d "wssshtools/debian" ]; then
cd wssshtools
dpkg-buildpackage -us -uc
cd ..
# Move deb file to dist
mv ../wsssh-tools*.deb dist/ 2>/dev/null || true
else
echo "Warning: Debian packaging not available (missing wssshtools/debian/)"
fi
fi
# Deactivate venv
deactivate
......@@ -45,3 +92,13 @@ echo "- dist/wssshd (server with web interface)"
echo "- dist/wssshc (client)"
echo "- dist/wsssh (SSH wrapper)"
echo "- dist/wsscp (SCP wrapper)"
if [ -d "wssshtools" ] && [ -f "wssshtools/wssshc" ]; then
echo "- wssshtools/wssshc (C client)"
echo "- wssshtools/wsssh (C SSH wrapper)"
echo "- wssshtools/wsscp (C SCP wrapper)"
fi
if [ "$BUILD_DEBIAN" = true ] && ls dist/wsssh-tools*.deb >/dev/null 2>&1; then
echo "- dist/wsssh-tools*.deb (Debian package)"
fi
\ No newline at end of file
......@@ -5,6 +5,20 @@ rm -rf build/
rm -rf dist/
rm -f *.spec
# Remove C version build artifacts
if [ -d "wssshtools" ]; then
cd wssshtools
make clean 2>/dev/null || true
rm -f configure.sh.stamp
cd ..
fi
# Remove Debian packaging artifacts
rm -f ../wsssh-tools*.deb
rm -f ../wsssh-tools*.dsc
rm -f ../wsssh-tools*.tar.gz
rm -f ../wsssh-tools*.changes
# Optionally remove SSL certificates (uncomment if needed)
# rm -f cert.pem key.pem
......
#!/bin/bash
# configure.sh - Configuration script for wssshtools C implementation
echo "Configuring wssshtools..."
# Check for required tools
echo "Checking for required tools..."
if ! command -v gcc &> /dev/null; then
echo "Error: gcc not found. Please install gcc."
exit 1
fi
if ! command -v make &> /dev/null; then
echo "Error: make not found. Please install make."
exit 1
fi
if ! command -v pkg-config &> /dev/null; then
echo "Error: pkg-config not found. Please install pkg-config."
exit 1
fi
# Check for OpenSSL development libraries
if ! pkg-config --exists openssl; then
echo "Error: OpenSSL development libraries not found."
echo "Please install openssl-dev or libssl-dev package."
exit 1
fi
echo "All required tools found."
# Generate Makefile
cat > Makefile << 'EOF'
# Makefile for wssshtools
CC = gcc
CFLAGS = -Wall -Wextra -O2 $(shell pkg-config --cflags openssl)
LDFLAGS = $(shell pkg-config --libs openssl)
# Source files
SRCS = wssshc.c wsssh.c wsscp.c
OBJS = $(SRCS:.c=.o)
TARGETS = wssshc wsssh wsscp
# Default target
all: $(TARGETS)
# Individual targets
wssshc: wssshc.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
wsssh: wsssh.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
wsscp: wsscp.o
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
# Object files
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Clean
clean:
rm -f $(OBJS) $(TARGETS)
# Install (optional)
install: all
install -d $(DESTDIR)/usr/local/bin
install -m 755 $(TARGETS) $(DESTDIR)/usr/local/bin/
# Uninstall (optional)
uninstall:
rm -f $(DESTDIR)/usr/local/bin/wssshc
rm -f $(DESTDIR)/usr/local/bin/wsssh
rm -f $(DESTDIR)/usr/local/bin/wsscp
.PHONY: all clean install uninstall
EOF
echo "Makefile generated successfully."
# Create configure stamp
touch configure.sh.stamp
echo "Configuration complete. Run 'make' to build the C tools."
\ No newline at end of file
wsssh-tools (1.0.0-1) unstable; urgency=medium
* Initial release of WebSocket SSH Tools C implementation
* Includes wssshc (client), wsssh (SSH wrapper), wsscp (SCP wrapper)
* Provides secure SSH/SCP tunneling through WebSocket connections
-- Stefy Lanza <stefy@nexlab.net> $(date -R)
\ No newline at end of file
13
\ No newline at end of file
Source: wsssh-tools
Section: net
Priority: optional
Maintainer: Stefy Lanza <stefy@nexlab.net>
Build-Depends: debhelper-compat (= 13), gcc, make, pkg-config, libssl-dev
Standards-Version: 4.6.2
Homepage: https://github.com/stefy/wsssh
Vcs-Browser: https://github.com/stefy/wsssh
Vcs-Git: https://github.com/stefy/wsssh.git
Package: wsssh-tools
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, openssl
Description: WebSocket SSH Tools - C implementation
A modern SSH tunneling system that uses WebSocket connections to securely
route SSH/SCP traffic through registered client machines.
.
This package contains the C implementation of the WebSocket SSH tools:
wssshc (client registration), wsssh (SSH wrapper), and wsscp (SCP wrapper).
\ No newline at end of file
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: wsssh-tools
Upstream-Contact: Stefy Lanza <stefy@nexlab.net>
Source: https://github.com/stefy/wsssh
Files: *
Copyright: 2024 Stefy Lanza <stefy@nexlab.net> and SexHack.me
License: GPL-3.0+
Files: debian/*
Copyright: 2024 Stefy Lanza <stefy@nexlab.net>
License: GPL-3.0+
License: GPL-3.0+
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
.
This package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
.
On Debian systems, the complete text of the GNU General
Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
\ No newline at end of file
#!/usr/bin/make -f
# See debhelper(7) (uncomment to enable)
# output every command that modifies files on the build system.
#export DH_VERBOSE = 1
# see FEATURE AREAS in dpkg-buildflags(1)
#export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# see ENVIRONMENT in dpkg-buildflags(1)
# package maintainers to append CFLAGS
#export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
# package maintainers to append LDFLAGS
#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
%:
dh $@
override_dh_auto_configure:
./configure.sh
override_dh_auto_build:
make
override_dh_auto_install:
make install DESTDIR=debian/wsssh-tools
override_dh_auto_clean:
make clean
rm -f configure.sh.stamp
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <getopt.h>
#define BUFFER_SIZE 4096
#define DEFAULT_PORT 9898
typedef struct {
char *server_ip;
int port;
char *client_id;
char *password;
int interval;
int debug;
} wssshc_config_t;
void print_usage(const char *program_name) {
fprintf(stderr, "Usage: %s [options]\n", program_name);
fprintf(stderr, "WebSocket SSH Client - Register with wssshd server\n\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, " --server-ip IP Server IP address (required)\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, " --interval SEC Reconnection interval (default: 30)\n");
fprintf(stderr, " --debug Enable debug output\n");
fprintf(stderr, " --help Show this help\n");
}
int parse_args(int argc, char *argv[], wssshc_config_t *config) {
static struct option long_options[] = {
{"server-ip", required_argument, 0, 's'},
{"port", required_argument, 0, 'p'},
{"id", required_argument, 0, 'i'},
{"password", required_argument, 0, 'w'},
{"interval", required_argument, 0, 't'},
{"debug", no_argument, 0, 'd'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
int opt;
while ((opt = getopt_long(argc, argv, "s:p:i:w:t:dh", long_options, NULL)) != -1) {
switch (opt) {
case 's':
config->server_ip = strdup(optarg);
break;
case 'p':
config->port = atoi(optarg);
break;
case 'i':
config->client_id = strdup(optarg);
break;
case 'w':
config->password = strdup(optarg);
break;
case 't':
config->interval = atoi(optarg);
break;
case 'd':
config->debug = 1;
break;
case 'h':
default:
print_usage(argv[0]);
return 0;
}
}
// 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]);
return 0;
}
return 1;
}
SSL_CTX* init_ssl_ctx() {
SSL_CTX *ctx;
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(TLS_client_method());
if (!ctx) {
ERR_print_errors_fp(stderr);
return NULL;
}
// Allow self-signed certificates
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
return ctx;
}
int websocket_handshake(int sock, const char *host, int port, const char *path) {
char request[1024];
char response[BUFFER_SIZE];
int bytes_read;
// Send WebSocket handshake
snprintf(request, sizeof(request),
"GET %s HTTP/1.1\r\n"
"Host: %s:%d\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
"Sec-WebSocket-Version: 13\r\n"
"\r\n",
path, host, port);
if (send(sock, request, strlen(request), 0) < 0) {
perror("WebSocket handshake send failed");
return 0;
}
// Read response
bytes_read = recv(sock, response, sizeof(response) - 1, 0);
if (bytes_read <= 0) {
perror("WebSocket handshake recv failed");
return 0;
}
response[bytes_read] = '\0';
// Check for successful handshake
if (strstr(response, "101 Switching Protocols") == NULL) {
fprintf(stderr, "WebSocket handshake failed\n");
return 0;
}
return 1;
}
int send_json_message(int sock, const char *type, const char *id, const char *password) {
char message[1024];
if (password) {
snprintf(message, sizeof(message),
"{\"type\":\"%s\",\"id\":\"%s\",\"password\":\"%s\"}",
type, id, password);
} else {
snprintf(message, sizeof(message),
"{\"type\":\"%s\",\"id\":\"%s\"}",
type, id);
}
if (send(sock, message, strlen(message), 0) < 0) {
perror("Send failed");
return 0;
}
return 1;
}
int connect_to_server(const wssshc_config_t *config) {
struct sockaddr_in server_addr;
struct hostent *he;
int sock;
SSL_CTX *ssl_ctx;
SSL *ssl;
char buffer[BUFFER_SIZE];
int bytes_read;
// Resolve hostname
if ((he = gethostbyname(config->server_ip)) == NULL) {
herror("gethostbyname");
return 0;
}
// Create socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("Socket creation failed");
return 0;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(config->port);
server_addr.sin_addr = *((struct in_addr *)he->h_addr);
// Connect to server
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
perror("Connection failed");
close(sock);
return 0;
}
// Initialize SSL
ssl_ctx = init_ssl_ctx();
if (!ssl_ctx) {
close(sock);
return 0;
}
ssl = SSL_new(ssl_ctx);
SSL_set_fd(ssl, sock);
if (SSL_connect(ssl) <= 0) {
ERR_print_errors_fp(stderr);
SSL_free(ssl);
SSL_CTX_free(ssl_ctx);
close(sock);
return 0;
}
// Perform WebSocket handshake
if (!websocket_handshake(sock, config->server_ip, config->port, "/")) {
SSL_free(ssl);
SSL_CTX_free(ssl_ctx);
close(sock);
return 0;
}
// Send registration message
if (!send_json_message(sock, "register", config->client_id, config->password)) {
SSL_free(ssl);
SSL_CTX_free(ssl_ctx);
close(sock);
return 0;
}
printf("Connected and registered as %s\n", config->client_id);
// Keep connection alive and handle messages
while (1) {
bytes_read = SSL_read(ssl, buffer, sizeof(buffer) - 1);
if (bytes_read <= 0) {
if (config->debug) {
printf("[DEBUG] Connection lost\n");
}
break;
}
buffer[bytes_read] = '\0';
if (config->debug) {
printf("[DEBUG] Received: %s\n", buffer);
}
// Handle different message types if needed
// For now, just keep the connection alive
}
// Cleanup
SSL_free(ssl);
SSL_CTX_free(ssl_ctx);
close(sock);
return 1;
}
int main(int argc, char *argv[]) {
wssshc_config_t config = {
.server_ip = NULL,
.port = DEFAULT_PORT,
.client_id = NULL,
.password = NULL,
.interval = 30,
.debug = 0
};
if (!parse_args(argc, argv, &config)) {
return 1;
}
printf("WebSocket SSH Client starting...\n");
while (1) {
if (connect_to_server(&config)) {
printf("Connection successful\n");
// In a real implementation, we might want to keep the connection alive
// For now, just exit on successful connection
break;
} else {
printf("Connection failed, retrying in %d seconds...\n", config.interval);
sleep(config.interval);
}
}
// Cleanup
free(config.server_ip);
free(config.client_id);
free(config.password);
return 0;
}
\ No newline at end of file
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