313 lines
8.9 KiB
ReStructuredText
Executable File
313 lines
8.9 KiB
ReStructuredText
Executable File
WebSSH
|
|
------
|
|
|
|
|Build Status| |codecov| |PyPI - Python Version| |PyPI|
|
|
|
|
Introduction
|
|
~~~~~~~~~~~~
|
|
|
|
A simple web application to be used as an ssh client to connect to your
|
|
ssh servers. It is written in Python, base on tornado, paramiko and
|
|
xterm.js.
|
|
|
|
Features
|
|
~~~~~~~~
|
|
|
|
- SSH password authentication supported, including empty password.
|
|
- SSH public-key authentication supported, including DSA RSA ECDSA
|
|
Ed25519 keys.
|
|
- Encrypted keys supported.
|
|
- Two-Factor Authentication (time-based one-time password) supported.
|
|
- Fullscreen terminal supported.
|
|
- Terminal window resizable.
|
|
- Auto detect the ssh server's default encoding.
|
|
- Modern browsers including Chrome, Firefox, Safari, Edge, Opera
|
|
supported.
|
|
|
|
Preview
|
|
~~~~~~~
|
|
|
|
|Login| |Terminal|
|
|
|
|
How it works
|
|
~~~~~~~~~~~~
|
|
|
|
::
|
|
|
|
+---------+ http +--------+ ssh +-----------+
|
|
| browser | <==========> | webssh | <=======> | ssh server|
|
|
+---------+ websocket +--------+ ssh +-----------+
|
|
|
|
Requirements
|
|
~~~~~~~~~~~~
|
|
|
|
- Python 3.10+
|
|
|
|
Quickstart
|
|
~~~~~~~~~~
|
|
|
|
1. Install this app, run command ``pip install webssh``
|
|
2. Start a webserver, run command ``wssh``
|
|
3. Open your browser, navigate to ``127.0.0.1:8888``
|
|
4. Create the WebSSH administrator account on first visit
|
|
5. Input your ssh data, submit the form.
|
|
|
|
WebSSH login and saved connections
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
WebSSH requires a login before opening ssh sessions. On first startup, if
|
|
no administrator password has been configured, the login page will ask you
|
|
to create one. The password is stored as a PBKDF2 hash under the data
|
|
directory, not as plain text.
|
|
|
|
You can also provide credentials with environment variables:
|
|
|
|
.. code:: bash
|
|
|
|
WEBSSH_AUTH_USERNAME=admin WEBSSH_AUTH_PASSWORD='strong-password' wssh
|
|
|
|
Saved connections are stored under the data directory too. Connection
|
|
details include hostname, port, username, terminal type, initial directory,
|
|
name, group and notes. Search or filter saved connections by group, and use
|
|
the Save notes button to update metadata without reconnecting.
|
|
|
|
Saving connection details and saving credentials are separate options.
|
|
Passwords and private keys are encrypted using the server cookie secret
|
|
only when Save password / private key is selected. Saving the private-key
|
|
passphrase requires its own checkbox. Credentials are never returned in
|
|
connection listings, and TOTP codes are never saved. After a successful
|
|
connection with Save connection enabled, deselecting Save credentials
|
|
clears the previously saved credentials for that destination.
|
|
|
|
Each terminal tab owns a separate SSH session. New connection opens another
|
|
tab; switching or closing a tab does not interrupt other sessions. Reconnect
|
|
starts a new SSH session using saved credentials when available. Encrypted
|
|
keys without a saved passphrase and two-factor connections require fresh
|
|
input. To retain remote processes across disconnects, use tmux on the SSH
|
|
server. Reloading the browser closes its live sessions.
|
|
|
|
The terminal toolbar provides output search (also Ctrl/Cmd+F), fullscreen,
|
|
font size, themes and cursor settings. Terminal preferences and single-line
|
|
command bookmarks are stored in the current browser. Inserting a bookmark
|
|
does not send Enter; review it and press Enter yourself.
|
|
|
|
File management uses the active tab's SSH connection and requires SFTP on
|
|
the remote server. Browse directories and upload or download regular files
|
|
up to 16 MiB. Uploads exclusively create a new file and never overwrite an
|
|
existing filename. A failed upload may leave a partial file. One file
|
|
operation at a time is allowed per SSH session; other terminals remain
|
|
usable. HTTP requests are limited to 17 MiB to allow multipart overhead.
|
|
|
|
Export configuration produces JSON without credentials. Encrypted backup
|
|
includes stored credentials protected by an independent backup password
|
|
(at least 10 characters). Keep this password to restore on another server;
|
|
restored credentials are encrypted using that server's cookie secret.
|
|
Import validates the whole batch before writing, accepts at most 500
|
|
connections and merges by host, port and username under the current user.
|
|
Configuration imports preserve existing credentials; encrypted backup
|
|
imports replace them for matching destinations. Connection imports do not
|
|
change active sessions, browser settings or command bookmarks.
|
|
|
|
Use ``--auth=false`` only for a trusted private deployment where another
|
|
layer already protects access to WebSSH.
|
|
|
|
Server options
|
|
~~~~~~~~~~~~~~
|
|
|
|
.. code:: bash
|
|
|
|
# start a http server with specified listen address and listen port
|
|
wssh --address='2.2.2.2' --port=8000
|
|
|
|
# start a https server, certfile and keyfile must be passed
|
|
wssh --certfile='/path/to/cert.crt' --keyfile='/path/to/cert.key'
|
|
|
|
# missing host key policy
|
|
wssh --policy=reject
|
|
|
|
# logging level
|
|
wssh --logging=debug
|
|
|
|
# log to file
|
|
wssh --log-file-prefix=main.log
|
|
|
|
# data directory for login and saved connection data
|
|
wssh --data-dir='/path/to/webssh-data'
|
|
|
|
# more options
|
|
wssh --help
|
|
|
|
Browser console
|
|
~~~~~~~~~~~~~~~
|
|
|
|
.. code:: javascript
|
|
|
|
// connect to your ssh server
|
|
wssh.connect(hostname, port, username, password, privatekey, passphrase, totp);
|
|
|
|
// pass an object to wssh.connect
|
|
var opts = {
|
|
hostname: 'hostname',
|
|
port: 'port',
|
|
username: 'username',
|
|
password: 'password',
|
|
privatekey: 'the private key text',
|
|
passphrase: 'passphrase',
|
|
totp: 'totp'
|
|
};
|
|
wssh.connect(opts);
|
|
|
|
// without an argument, wssh will use the form data to connect
|
|
wssh.connect();
|
|
|
|
// set a new encoding for client to use
|
|
wssh.set_encoding(encoding);
|
|
|
|
// reset encoding to use the default one
|
|
wssh.reset_encoding();
|
|
|
|
// send a command to the server
|
|
wssh.send('ls -l');
|
|
|
|
Custom Font
|
|
~~~~~~~~~~~
|
|
|
|
To use custom font, put your font file in the directory
|
|
``webssh/static/css/fonts/`` and restart the server.
|
|
|
|
URL Arguments
|
|
~~~~~~~~~~~~~
|
|
|
|
Support passing arguments by url (query or fragment) like following
|
|
examples:
|
|
|
|
Passing form data (password must be encoded in base64, privatekey not
|
|
supported)
|
|
|
|
.. code:: bash
|
|
|
|
http://localhost:8888/?hostname=xx&username=yy&password=str_base64_encoded
|
|
|
|
Passing a terminal background color
|
|
|
|
.. code:: bash
|
|
|
|
http://localhost:8888/#bgcolor=green
|
|
|
|
Passing a user defined title
|
|
|
|
.. code:: bash
|
|
|
|
http://localhost:8888/?title=my-ssh-server
|
|
|
|
Passing an encoding
|
|
|
|
.. code:: bash
|
|
|
|
http://localhost:8888/#encoding=gbk
|
|
|
|
Passing a command executed right after login
|
|
|
|
.. code:: bash
|
|
|
|
http://localhost:8888/?command=pwd
|
|
|
|
Passing a terminal type
|
|
|
|
.. code:: bash
|
|
|
|
http://localhost:8888/?term=xterm-256color
|
|
|
|
Use Docker
|
|
~~~~~~~~~~
|
|
|
|
Start up the app
|
|
|
|
::
|
|
|
|
docker compose up -d
|
|
|
|
Tear down the app
|
|
|
|
::
|
|
|
|
docker compose down
|
|
|
|
The bundled compose file persists login and saved connection data in the
|
|
``webssh-data`` volume mounted at ``/data`` inside the container.
|
|
|
|
Tests
|
|
~~~~~
|
|
|
|
Requirements
|
|
|
|
::
|
|
|
|
pip install pytest pytest-cov codecov flake8 mock
|
|
|
|
Use unittest to run all tests
|
|
|
|
::
|
|
|
|
python -m unittest discover tests
|
|
|
|
Use pytest to run all tests
|
|
|
|
::
|
|
|
|
python -m pytest tests
|
|
|
|
Deployment
|
|
~~~~~~~~~~
|
|
|
|
Running behind an Nginx server
|
|
|
|
.. code:: bash
|
|
|
|
wssh --address='127.0.0.1' --port=8888 --policy=reject
|
|
|
|
.. code:: nginx
|
|
|
|
# Nginx config example
|
|
location / {
|
|
proxy_pass http://127.0.0.1:8888;
|
|
proxy_http_version 1.1;
|
|
proxy_read_timeout 300;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Host $http_host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Real-PORT $remote_port;
|
|
}
|
|
|
|
Running as a standalone server
|
|
|
|
.. code:: bash
|
|
|
|
wssh --port=8080 --sslport=4433 --certfile='cert.crt' --keyfile='cert.key' --xheaders=False --policy=reject
|
|
|
|
Tips
|
|
~~~~
|
|
|
|
- For whatever deployment choice you choose, don't forget to enable
|
|
SSL.
|
|
- By default plain http requests from a public network will be either
|
|
redirected or blocked and being redirected takes precedence over
|
|
being blocked.
|
|
- Try to use reject policy as the missing host key policy along with
|
|
your verified known\_hosts, this will prevent man-in-the-middle
|
|
attacks. The idea is that it checks the system host keys
|
|
file("~/.ssh/known\_hosts") and the application host keys
|
|
file("./known\_hosts") in order, if the ssh server's hostname is not
|
|
found or the key is not matched, the connection will be aborted.
|
|
|
|
.. |Build Status| image:: https://travis-ci.org/huashengdun/webssh.svg?branch=master
|
|
:target: https://travis-ci.org/huashengdun/webssh
|
|
.. |codecov| image:: https://codecov.io/gh/huashengdun/webssh/branch/master/graph/badge.svg
|
|
:target: https://codecov.io/gh/huashengdun/webssh
|
|
.. |PyPI - Python Version| image:: https://img.shields.io/pypi/pyversions/webssh.svg
|
|
.. |PyPI| image:: https://img.shields.io/pypi/v/webssh.svg
|
|
.. |Login| image:: https://github.com/huashengdun/webssh/raw/master/preview/login.png
|
|
.. |Terminal| image:: https://github.com/huashengdun/webssh/raw/master/preview/terminal.png
|
|
|