Install WebSSH with Python Tornado Framework on CentOS 7 - NETSEC

Latest

Learning, Sharing, Creating

Cybersecurity Memo

Monday, July 6, 2020

Install WebSSH with Python Tornado Framework on CentOS 7

WebSSH is 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. This post is to record all steps from scratch to set WebSSH up in a CentOS 7 machine.



Install Python

1  Install / Check Python version

[root@centos-7-vnc ~]# yum install python
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftpmirror.your.org
 * epel: ord.mirror.rackspace.com
 * extras: mirror.twinlakes.net
 * updates: mirror.den01.meanservers.net
Package python-2.7.5-88.el7.x86_64 already installed and latest version
Nothing to do
[root@centos-7-vnc ~]# python -V
Python 2.7.5

2  install PIP

PIP is a package manager for Python packages, or modules if you like.

[root@centos-7-vnc ~]# wget https://bootstrap.pypa.io/get-pip.py
--2020-07-06 15:21:52--  https://bootstrap.pypa.io/get-pip.py
Resolving bootstrap.pypa.io (bootstrap.pypa.io)... 151.101.0.175, 151.101.64.175, 151.101.128.175, ...
Connecting to bootstrap.pypa.io (bootstrap.pypa.io)|151.101.0.175|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1869136 (1.8M) [text/x-python]
Saving to: ‘get-pip.py’

100%[==========================================================================>] 1,869,136   11.7MB/s   in 0.2s   

2020-07-06 15:21:52 (11.7 MB/s) - ‘get-pip.py’ saved [1869136/1869136]

[root@centos-7-vnc ~]# python get-pip.py
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting pip
  Downloading pip-20.1.1-py2.py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 3.0 MB/s 
Collecting setuptools
  Downloading setuptools-44.1.1-py2.py3-none-any.whl (583 kB)
     |████████████████████████████████| 583 kB 78.6 MB/s 
Collecting wheel
  Downloading wheel-0.34.2-py2.py3-none-any.whl (26 kB)
Installing collected packages: pip, setuptools, wheel
Successfully installed pip-20.1.1 setuptools-44.1.1 wheel-0.34.2
[root@centos-7-vnc ~]# 


3  Install Tornado
https://www.tornadoweb.org/en/stable/
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, WebSockets, and other applications that require a long-lived connection to each user.

[root@centos-7-vnc ~]# pip install tornado
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting tornado
  Downloading tornado-5.1.1.tar.gz (516 kB)
     |████████████████████████████████| 516 kB 3.3 MB/s 
Collecting futures
  Downloading futures-3.3.0-py2-none-any.whl (16 kB)
Collecting singledispatch
  Downloading singledispatch-3.4.0.3-py2.py3-none-any.whl (12 kB)
Collecting backports_abc>=0.4
  Downloading backports_abc-0.5-py2.py3-none-any.whl (5.2 kB)
Collecting six
  Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
Building wheels for collected packages: tornado
  Building wheel for tornado (setup.py) ... done
  Created wheel for tornado: filename=tornado-5.1.1-cp27-cp27mu-linux_x86_64.whl size=449883 sha256=86011dbe7d092c247ac5ebbbd5acbeb766a24f76b19a5f0c1e4cddf88a0affd8
  Stored in directory: /root/.cache/pip/wheels/d8/83/af/e0dc6afbf3a2c51af8d6e3f9fbe790d0c581c2de05bc5d50f5
Successfully built tornado
Installing collected packages: futures, six, singledispatch, backports-abc, tornado
Successfully installed backports-abc-0.5 futures-3.3.0 singledispatch-3.4.0.3 six-1.15.0 tornado-5.1.1
[root@centos-7-vnc ~]# 



Generate Self-Signed SSH Key and Cert on CentOS 7 Server

1  Create a new Self-Signed SSL Certificate, use the openssl req command:

openssl req -newkey rsa:4096 \
            -x509 \
            -sha256 \
            -days 3650 \
            -nodes \
            -out example.crt \
            -keyout example.key


Each option means:
  • -newkey rsa:4096 - Creates a new certificate request and 4096 bit RSA key. The default one is 2048 bits.
  • -x509 - Creates a X.509 Certificate.
  • -sha256 - Use 265-bit SHA (Secure Hash Algorithm).
  • -days 3650 - The number of days to certify the certificate for. 3650 is ten years. You can use any positive integer.
  • -nodes - Creates a key without a passphrase.
  • -out example.crt - Specifies the filename to write the newly created certificate to. You can specify any file name.
  • -keyout example.key - Specifies the filename to write the newly created private key to. You can specify any file name.

Install WebSSH

1  Requirements
  • Python 2.7/3.4+
2  Quickstart
  • Install this app, run command pip install webssh
  • Start a webserver, run command wssh
  • Open your browser, navigate to 127.0.0.1:8888
  • Input your data, submit the form.


3  start a https server, certfile and keyfile must be passed

wssh --certfile='/root/example.crt' --keyfile='/root/example.key' --sslport=8000 --port=80

root@instance-1-test:~# wssh --certfile='/root/example.crt' --keyfile='/root/example.key' --sslport=8000 --port=80
[I 200706 16:45:32 settings:125] WarningPolicy
[I 200706 16:45:32 main:39] Listening on :80 (http)
[I 200706 16:45:32 main:39] Listening on :8000 (https)
[W 200706 16:50:58 handler:262] Public plain http request is forbidden.
[W 200706 16:50:58 web:2162] 403 GET / (160.32.192.89) 0.87ms
[W 200706 16:51:04 iostream:1518] SSL Error on 13 ('160.32.192.89', 7079): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[W 200706 16:51:04 iostream:1518] SSL Error on 14 ('160.32.192.89', 7078): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[W 200706 16:51:05 iostream:1518] SSL Error on 15 ('160.32.192.89', 7080): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[I 200706 16:51:05 web:2162] 200 GET / (160.32.192.89) 4.26ms
[I 200706 16:51:05 web:2162] 200 GET /static/css/xterm.min.css (160.32.192.89) 0.73ms
[I 200706 16:51:05 web:2162] 200 GET /static/css/fullscreen.min.css (160.32.192.89) 0.78ms
[W 200706 16:51:05 iostream:1518] SSL Error on 16 ('160.32.192.89', 7083): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[W 200706 16:51:05 iostream:1518] SSL Error on 17 ('160.32.192.89', 7084): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[I 200706 16:51:05 web:2162] 200 GET /static/css/bootstrap.min.css (160.32.192.89) 121.73ms
[W 200706 16:51:05 iostream:1518] SSL Error on 18 ('160.32.192.89', 7085): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[W 200706 16:51:05 iostream:1518] SSL Error on 16 ('160.32.192.89', 7086): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[I 200706 16:51:05 web:2162] 200 GET /static/js/xterm-addon-fit.min.js (160.32.192.89) 0.84ms
[W 200706 16:51:05 iostream:1518] SSL Error on 15 ('160.32.192.89', 7087): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[W 200706 16:51:05 iostream:1518] SSL Error on 16 ('160.32.192.89', 7088): [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:727)
[I 200706 16:51:05 web:2162] 200 GET /static/js/jquery.min.js (160.32.192.89) 1.29ms
[I 200706 16:51:05 web:2162] 200 GET /static/js/popper.min.js (160.32.192.89) 0.87ms
[I 200706 16:51:05 web:2162] 200 GET /static/js/bootstrap.min.js (160.32.192.89) 1.00ms
[I 200706 16:51:05 web:2162] 200 GET /static/js/main.js (160.32.192.89) 0.90ms
[I 200706 16:51:05 web:2162] 200 GET /static/js/xterm.min.js (160.32.192.89) 115.71ms
Browse the website to http://<public ip> , but public plain http request is forbidden. You will get 403 Forbidden error.

Since we enabled https on port 8000, we can use https://<publ ip>:8000 to browse it



Deploy WebSSH using a docker image

Docker Image: https://hub.docker.com/r/snsyzb/webssh
To start a container from this image:
$ docker run -d -p 8080:8080 snsyzb/webssh
The container will start a web application on 8080 port, so you can visit your own ssh client web application via openning localhost:8080 in your browser. Or you could use command parameter in docker run to identify the address and port:
$ docker run -d -p 10000:10000 snsyzb/webssh wssh --address=0.0.0.0 --port=10000
The command above will start running a container listening the port 10000
[node1] (local) [email protected] ~
docker run -d -p 8080:8080 snsyzb/webssh
Unable to find image 'snsyzb/webssh:latest' locally
latest: Pulling from snsyzb/webssh
124c757242f8: Pull complete 
9d866f8bde2a: Pull complete 
fa3f2f277e67: Pull complete 
398d32b153e8: Pull complete 
afde35469481: Pull complete 
d68c56e3e37c: Pull complete 
d563634ee4b5: Pull complete 
Digest: sha256:52fec21d4e4489d4f0557802b9c989cc72119a8bca032a7e5582a999cd5a875f
Status: Downloaded newer image for snsyzb/webssh:latest
beea2334682b7ba74ae887b9a88a4fc333ef9261d3a5ae02fc21f710047c81e4
[node1] (local) [email protected] ~
$ 

If you decided to put your WebSSH application behind Nginx service. Here is the Nginx configuration file:


root@5fbe841d1f40:/# cd /etc/nginx/conf.d
root@5fbe841d1f40:/etc/nginx/conf.d# cat webssh.conf 
server {
    listen       80;
    server_name  webssh.51sec.org;

location / {
    proxy_pass       http://132.145.98.41:8080;
    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;
           }
}
root@5fbe841d1f40:/etc/nginx/conf.d# service nginx restart

Make WebSSH as a system service


1  First create a  custom script to be run at system boot automatically.

# vi /usr/local/webssh.sh
#!/bin/bash
wssh --certfile='/root/example.crt' --keyfile='/root/example.key' --sslport=8000 --port=80
2   Add execute permission
# chmod +x /usr/local/webssh.sh

3  Create a new service unit file at /etc/systemd/system/WebSSH.service with below content. The name of the service unit is user defined and can be any name of your choice.
# vi /etc/systemd/system/webssh.service
[Unit]
Description=Description for sample script goes here
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/webssh.sh
TimeoutStartSec=0

[Install]
WantedBy=default.target
Here,
After= : If the script needs any other system facilities (networking, etc), modify the [Unit] section to include appropriate After=, Wants=, or Requires= directives.
Type= : Switch Type=simple for Type=idle in the [Service] section to delay execution of the script until all other jobs are dispatched
WantedBy= : target to run the sample script in

4  Reload the systemd process to consider newly created sample.service OR every time when sample.service gets modified.

# systemctl daemon-reload
5  Enable this service to start after reboot automatically.
# systemctl enable sample.service
6  Start the service.
# systemctl start sample.service
7  Reboot the host to verify whether the scripts are starting as expected during system boot.
# systemctl reboot


YouTube Video:











No comments:

Post a Comment