This commit is contained in:
2026-03-11 09:01:35 +00:00
parent fac75043ab
commit 8af9a74071
6 changed files with 411 additions and 34 deletions

2
sshwifty/README.md Normal file
View File

@@ -0,0 +1,2 @@
# SSHwifty
## online SSH client, connects via ssh and telnet

28
sshwifty/ingress.yaml Normal file
View File

@@ -0,0 +1,28 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sshwifty
namespace: sshwifty
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt
#external-dns.alpha.kubernetes.io/target: firewall.undercloud.dev
#external-dns.alpha.kubernetes.io/ttl: "120"
spec:
tls:
- hosts:
- sshwifty.apps.undercloud.dev
secretName: sshwifty-tls
rules:
- host: sshwifty.apps.undercloud.dev
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx
port:
number: 80

4
sshwifty/namespace.yaml Normal file
View File

@@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: sshwifty

321
sshwifty/sshwifty.yaml Normal file
View File

@@ -0,0 +1,321 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: config
namespace: sshwifty
data:
sshwifty.conf.json: |
{
// HTTP Host. Keep it empty to accept request from all hosts, otherwise, only
// specified host is allowed to access
"HostName": "localhost",
// Web interface access password. Set to empty to allow public access to the
// web interface (By pass the Authenticate page)
"SharedKey": "WEB_ACCESS_PASSWORD",
// Remote dial timeout. This limits how long of time the backend can spend
// to connect to a remote host. The max timeout will be determined by
// server configuration (ReadTimeout).
// (In Seconds)
"DialTimeout": 10,
// Socks5 proxy. When set, Sshwifty backend will try to connect remote through
// the given proxy
"Socks5": "localhost:1080",
// Username of the Socks5 server. Please set when needed
"Socks5User": "",
// Password of the Socks5 server. Please set when needed
"Socks5Password": "",
// Server side hooks, allowing operator to launch external processes on the
// server side to influence server behaver
//
// The operation of a Hook must be completed within the time limit defined
// by `HookTimeout` set below. Otherwise it will be terminated, and results
// a failure for the execution
//
// To determine how much time is still left for the execution, a Hook can
// fetch the deadline information from the `SSHWIFTY_HOOK_DEADLINE`
// environment variable which is a RFC3339 formatted date string indicating
// after what time the termination will occur
//
// Warning: the process will be launched within the same context and system
// permission which Sshwifty is running under, thus is it crucial that the
// Hook process is designed and operated in a secure manner, otherwise
// SECURITY VULNERABILITY (commandline injection, for example) maybe created
// as result
//
// Warning: all inputs passed by Sshwifty to the hook process must be
// considered unsanitized, and must be sanitized by each hook themselves
"Hooks": {
// before_connecting is called before Sshwifty starts to connect to a remote
// endpoint. If any of the Hook process exited with a non-zero return code,
// the connection request is aborted
//
// This Hook offers two parameters:
// - SSHWIFTY_HOOK_REMOTE_TYPE: Type of the connection (i.e. SSH or Telnet)
// - SSHWIFTY_HOOK_REMOTE_ADDRESS: Address of the remote host
"before_connecting": [
// Following example command launches a `/bin/sh` to execute a for loop
// that prints to Stdout as well as to Stderr
//
// Prints to Stdout will be sent to the client side visible to the user,
// and prints to Stderr will be captured as server side logs and it is
// invisible to the user (as server logs usually are)
//
// The command must be specified in Json array format. Each array element
// is mapped to a command fragment separated by space. For example:
// ["command", "-i", "Hello World"] will be mapped to `command -i "Hello
// World"` before it is executed
[
"/bin/sh",
"-c",
"for n in $(seq 1 5); do sleep 1 && echo Stdout $SSHWIFTY_HOOK_REMOTE_TYPE $n && echo Stderr $SSHWIFTY_HOOK_REMOTE_TYPE $n 1>&2; done"
],
// You can add multiple hooks, they're executed in sequence even when the
// previous one fails
[
"/bin/sh",
"-c",
"/etc/sshwifty/before_connecting.sh"
],
[
"/bin/another-command",
"...",
"..."
]
]
},
// The maximum execution time of each hook, in seconds. If this timeout is
// exceeded, the hook will be terminated, and thus cause a failure
"HookTimeout": 30,
// Sshwifty HTTP server, you can set multiple ones to serve on different
// ports
"Servers": [
{
// Which local network interface this server will be listening
"ListenInterface": "0.0.0.0",
// Which local network port this server will be listening
"ListenPort": 8182,
// Timeout of initial request. HTTP handshake must be finished within
// this time
// (In Seconds)
"InitialTimeout": 10,
// How long do the connection can stay in idle before the backend server
// disconnects the client
// (In Seconds)
"ReadTimeout": 120,
// How long the server will wait until the client connection is ready to
// recieve new data. If this timeout is exceed, the connection will be
// closed.
// (In Seconds)
"WriteTimeout": 120,
// The interval between internal echo requests
// (In Seconds)
"HeartbeatTimeout": 10,
// Forced delay between each request
// (In Milliseconds)
"ReadDelay": 10,
// Forced delay between each write
// (In Milliseconds)
"WriteDelay": 10,
// Path to TLS certificate file. Set empty to use HTTP
"TLSCertificateFile": "",
// Path to TLS certificate key file. Set empty to use HTTP
"TLSCertificateKeyFile": "",
// Display a short text message on the Home page. Link is supported
// through `[Title text](https://link.example.com)` format
"ServerMessage": ""
},
{
"ListenInterface": "0.0.0.0",
"ListenPort": 8182,
"InitialTimeout": 3,
.....
}
],
// Remote Presets, the operater can define few presets for user so the user
// won't have to manually fill-in all the form fields
//
// Presets will be displayed in the "Known remotes" tab on the Connector
// window
//
// Notice: You can use the same JSON value for `SSHWIFTY_PRESETS` if you are
// configuring your Sshwifty through enviroment variables.
//
// Warning: Presets Data will be sent to user client WITHOUT any protection.
// DO NOT add any secret information into Preset.
//
"Presets": [
{
// Title of the preset
"Title": "SDF.org Unix Shell",
// Preset Types, i.e. Telnet, and SSH
"Type": "SSH",
// Target address and port
"Host": "sdf.org:22",
// Define the tab and background color of the console in RGB hex format
// for better visual identification
//
// For example: 110000 will give you a dark red background, 001100 is
// dark green and 000011 is dark blue
//
// The color must not be too bright, as it will make the foreground text
// hard to read
"TabColor": "112233",
// Form fields and values, you have to manually validate the correctness
// of the field value
//
// Defining a Meta field will prevent user from changing it on their
// Connector Wizard. If you want to allow users to use their own settings,
// leave the field unsetted
//
// Values in Meta are scheme enabled, and supports following scheme
// prefixes:
// - "literal://": Text literal (Default)
// Example: literal://Data value
// (The final value will be "Data value")
// Example: literal://file:///tmp/afile
// (The final value will be "file:///tmp/afile")
// - "file://": Load Meta value from given file.
// Example: file:///home/user/.ssh/private_key
// (The file path is /home/user/.ssh/private_key)
// - "environment://": Load Meta value from an Environment Variable.
// Example: environment://PRIVATE_KEY_DATA
// (The name of the target environment variable is
// PRIVATE_KEY_DATA)
//
// All data in Meta is loaded during start up, and will not be updated
// even the source already been modified.
//
"Meta": {
// Data for predefined User field
"User": "pre-defined-username",
// Data for predefined Encoding field. Valid data is those displayed on
// the page
"Encoding": "pre-defined-encoding",
// Data for predefined Password field
"Password": "pre-defined-password",
// Data for predefined Private Key field, should contains the content
// of a Key file
"Private Key": "file:///home/user/.ssh/private_key",
// Data for predefined Authentication field. Valid values is what
// displayed on the page (Password, Private Key, None)
"Authentication": "Password",
// Data for server public key fingerprint. You can acquire the value of
// the fingerprint by manually connect to a new SSH host with Sshwifty,
// the fingerprint will be displayed on the Fingerprint comformation
// page.
"Fingerprint": "SHA256:bgO...."
}
},
{
"Title": "Endpoint Telnet",
"Type": "Telnet",
"Host": "endpoint.nirui.org:23",
"Meta": {
// Data for predefined Encoding field. Valid data is those displayed on
// the page
"Encoding": "utf-8"
....
}
},
....
],
// Allow the Preset Remotes only, and refuse to connect to any other remote
// host
//
// NOTICE: You can only configure OnlyAllowPresetRemotes through a config
// file. This option is not supported when you are configuring with
// environment variables
"OnlyAllowPresetRemotes": false
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: sshwifty
namespace: sshwifty
labels:
app: sshwifty
spec:
replicas: 1
selector:
matchLabels:
app: sshwifty
template:
metadata:
annotations:
#backup.velero.io/backup-volumes: html
labels:
app: sshwifty
spec:
containers:
- name: sshwifty
image: niruix/sshwifty:latest
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8182
env:
- name: SSHWIFTY_CONFIG
value: "./sshwifty.conf.json ./sshwifty"
volumeMounts:
- mountPath: "./sshwifty.conf.json"
name: config
subPath: sshwifty.conf.json
volumes:
- name: config
configMap:
name: config
defaultMode: 0777
items:
- key: "sshwifty.conf.json"
path: "sshwifty.conf.json"
---
apiVersion: v1
kind: Service
metadata:
name: sshwifty
namespace: sshwifty
spec:
internalTrafficPolicy: Cluster
ipFamilies:
- IPv6
- IPv4
ipFamilyPolicy: PreferDualStack
#ipFamilyPolicy: SingleStack
ports:
- name: http
port: 80
protocol: TCP
targetPort: 8182
selector:
app: sshwifty
#sessionAffinity: None
type: ClusterIP