BinaryONe commited on
Commit
d89b239
·
1 Parent(s): 5669a3b
DockerFile ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official Ubuntu base image
2
+ FROM ubuntu:latest
3
+
4
+ # Set the maintainer label
5
+ LABEL maintainer="your-email@example.com"
6
+
7
+ # Prevent prompts during package installation
8
+ ARG DEBIAN_FRONTEND=noninteractive
9
+
10
+ RUN useradd -rm -d /home/ubuntu -s /bin/bash -g root -G sudo -u 1000 ubuntu && \
11
+ echo 'ubuntu:ubuntu' | chpasswd && \
12
+ echo 'root:password' | chpasswd
13
+
14
+ # Copy the application code to the container
15
+ COPY . /app
16
+
17
+ # Install necessary packages
18
+ RUN apt update && apt install -y \
19
+ openssh-server \
20
+ openssh\
21
+ sudo \
22
+ bash \
23
+ python3 \
24
+ python3-pip \
25
+ python3-venv \
26
+ net-tools && \
27
+ apt clean && \
28
+ rm -rf /var/lib/apt/lists/*
29
+
30
+
31
+ # SSH Configuration
32
+ RUN mkdir -p /var/run/sshd /app /app/ssh
33
+ RUN chmod -R 777 /app
34
+
35
+
36
+ # Generate SSH keys
37
+ RUN ssh-keygen -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key -N "" && \
38
+ ssh-keygen -t ecdsa -b 256 -f /etc/ssh/ssh_host_ecdsa_key -N "" && \
39
+ ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
40
+
41
+ # Secure SSH Configuration
42
+ RUN sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config && \
43
+ sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
44
+ sed -i 's/#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config && \
45
+ sed -i 's/#UsePAM yes/UsePAM no/' /etc/ssh/sshd_config && \
46
+ sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config && \
47
+ echo "AllowUsers admin" >> /etc/ssh/sshd_config
48
+
49
+ # Copy all the contents of /etc/ssh to /app/ssh
50
+ RUN mkdir -p /app/ssh && cp -r /etc/ssh/* /app/ssh
51
+
52
+
53
+ # Set the permissions for the SSH keys
54
+ RUN chmod 777 /etc/ssh/ssh_host_* && \
55
+ touch /app/ssh/ssh_known_hosts && \
56
+ chmod 777 /app/ssh/ssh_* && \
57
+ chmod 777 /home
58
+
59
+ # List contents of /etc/ssh and /app/ssh
60
+ RUN ls -l /etc/ssh/ && \
61
+ ls -l /app/ssh/
62
+
63
+ # Install WebSSH
64
+ #RUN python3 -m venv /app/venv && \
65
+ RUN pip install --no-cache-dir --upgrade pip && \
66
+ pip install --no-cache-dir -r /app/WebSSH/requirements.txt && \
67
+ pip list
68
+
69
+ # Set the working directory
70
+ WORKDIR /app
71
+
72
+ USER root
73
+
74
+ # Expose the port the app runs on
75
+ EXPOSE 7860
76
+
77
+ # Expose the port the app runs on
78
+ EXPOSE 2222
79
+
80
+ # Define the command to run the application
81
+ CMD ["/app/start.sh"]
WebSSH/Dockerfile ADDED
@@ -0,0 +1,77 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM alpine:latest
2
+
3
+ # Install necessary packages
4
+ RUN apk update && apk add --no-cache openssh openrc openssh-keygen bash sudo python3 py3-pip net-tools
5
+
6
+ # Create a non-root user (admin)
7
+ RUN adduser -D admin
8
+ RUN echo "admin:password" | chpasswd
9
+ RUN addgroup admin wheel
10
+ RUN adduser admin wheel
11
+
12
+ # SSH Configuration
13
+ RUN mkdir -p /var/run/sshd /app /app/ssh
14
+ RUN chmod -R 777 /app
15
+
16
+ # SSH Configuration
17
+ #RUN mkdir /app
18
+
19
+ # Copy all the contents of the /app folder
20
+ COPY . /app
21
+
22
+
23
+ # Generate SSH keys and print them
24
+ #RUN ssh-keygen -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key -N "" && \
25
+ # cat /etc/ssh/ssh_host_rsa_key && \
26
+ # ssh-keygen -t ecdsa -b 256 -f /etc/ssh/ssh_host_ecdsa_key -N "" && \
27
+ # cat /etc/ssh/ssh_host_ecdsa_key && \
28
+ # ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N "" && \
29
+ # cat /etc/ssh/ssh_host_ed25519_key
30
+
31
+ # Generate SSH keys
32
+ RUN ssh-keygen -t rsa -b 2048 -f /etc/ssh/ssh_host_rsa_key -N "" && \
33
+ ssh-keygen -t ecdsa -b 256 -f /etc/ssh/ssh_host_ecdsa_key -N "" && \
34
+ ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""
35
+
36
+ # Secure SSH Configuration
37
+ RUN sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config && \
38
+ sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config && \
39
+ sed -i 's/#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' /etc/ssh/sshd_config && \
40
+ sed -i 's/#UsePAM yes/UsePAM no/' /etc/ssh/sshd_config && \
41
+ sed -i 's/#Port 22/Port 2222/' /etc/ssh/sshd_config && \
42
+ echo "AllowUsers admin" >> /etc/ssh/sshd_config
43
+
44
+
45
+ # Copy all the contents of /etc/ssh to /app/ssh
46
+ RUN mkdir -p /app/ssh && cp -r /etc/ssh/* /app/ssh
47
+
48
+
49
+ # Set the permissions for the SSH keys
50
+ RUN chmod 777 /etc/ssh/ssh_host_* && \
51
+ touch /app/ssh/ssh_known_hosts && \
52
+ chmod 777 /app/ssh/ssh_* && \
53
+ chmod 777 /home
54
+
55
+ # List contents of /etc/ssh and /app/ssh
56
+ RUN ls -l /etc/ssh/ && \
57
+ ls -l /app/ssh/
58
+
59
+ # Install WebSSH
60
+ RUN python3 -m venv /app/venv && \
61
+ /app/venv/bin/pip install --no-cache-dir --upgrade pip && \
62
+ /app/venv/bin/pip install --no-cache-dir -r /app/WebSSH/requirements.txt && \
63
+ /app/venv/bin/pip list
64
+
65
+ # Expose the new SSH port
66
+ EXPOSE 2222
67
+
68
+ RUN chmod -R 777 /app
69
+
70
+ # Copy the start.sh script
71
+ #RUN chmod 777 /app/venv/lib/python3.12/site-packages/
72
+ #RUN touch /app/venv/lib/python3.12/site-packages/known_hosts
73
+ #RUN chmod 777 /app/venv/lib/python3.12/site-packages/known_hosts
74
+
75
+ EXPOSE 7860
76
+
77
+ CMD ["/app/start.sh"]
WebSSH/Fonts.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import importlib.util
3
+
4
+ # Automatically detect the path to the webssh package
5
+ spec = importlib.util.find_spec('webssh')
6
+ base_dir = os.path.dirname(spec.origin) if spec else None
7
+ font_dirs = ['static', 'css', 'fonts']
8
+ max_body_size = 1 * 1024 * 1024
9
+
10
+
11
+ class Font(object):
12
+
13
+ def __init__(self, filename, dirs):
14
+ self.family = self.get_family(filename)
15
+ self.url = self.get_url(filename, dirs)
16
+
17
+ def get_family(self, filename):
18
+ return filename.split('.')[0]
19
+
20
+ def get_url(self, filename, dirs):
21
+ return '/'.join(dirs + [filename])
22
+
23
+ def get_font_filename(font, font_dir):
24
+ filenames = {f for f in os.listdir(font_dir) if not f.startswith('.')
25
+ and os.path.isfile(os.path.join(font_dir, f))}
26
+ if font:
27
+ if font not in filenames:
28
+ raise ValueError(
29
+ 'Font file {!r} not found'.format(os.path.join(font_dir, font))
30
+ )
31
+ elif filenames:
32
+ font = filenames.pop()
33
+
34
+ return font
WebSSH/Tools.py ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import ssl
3
+ import sys
4
+ import logging
5
+ import os.path
6
+ import importlib.util
7
+
8
+ # Automatically detect the path to the webssh package
9
+ spec = importlib.util.find_spec('webssh')
10
+ base_dir = os.path.dirname(spec.origin) if spec else None
11
+
12
+ #font_dirs = ['static', 'css', 'fonts']
13
+ max_body_size = 1 * 1024 * 1024
14
+
15
+ #base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16
+ #font_dirs = ['webssh', 'static', 'css', 'fonts']
17
+
18
+ def print_version(flag):
19
+ if flag:
20
+ print(__version__)
21
+ sys.exit(0)
22
+
23
+ def is_valid_encoding(encoding):
24
+ try:
25
+ u'test'.encode(encoding)
26
+ except LookupError:
27
+ return False
28
+ except ValueError:
29
+ return False
30
+ return True
31
+
32
+ def check_encoding_setting(encoding):
33
+ if encoding and not is_valid_encoding(encoding):
34
+ raise ValueError('Unknown character encoding {!r}.'.format(encoding))
35
+
36
+ def get_server_settings(options):
37
+ settings = dict(
38
+ xheaders=options.xheaders,
39
+ max_body_size=max_body_size,
40
+ trusted_downstream=get_trusted_downstream(options.tdstream)
41
+ )
42
+ return settings
43
+
44
+ def get_trusted_downstream(tdstream):
45
+ result = set()
46
+ for ip in tdstream.split(','):
47
+ ip = ip.strip()
48
+ if ip:
49
+ to_ip_address(ip)
50
+ result.add(ip)
51
+ return result
52
+
53
+ def get_ssl_context(options):
54
+ if not options.certfile and not options.keyfile:
55
+ return None
56
+ elif not options.certfile:
57
+ raise ValueError('certfile is not provided')
58
+ elif not options.keyfile:
59
+ raise ValueError('keyfile is not provided')
60
+ elif not os.path.isfile(options.certfile):
61
+ raise ValueError('File {!r} does not exist'.format(options.certfile))
62
+ elif not os.path.isfile(options.keyfile):
63
+ raise ValueError('File {!r} does not exist'.format(options.keyfile))
64
+ else:
65
+ ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
66
+ ssl_ctx.load_cert_chain(options.certfile, options.keyfile)
67
+ return ssl_ctx
68
+
69
+
70
+
WebSSH/__init__.py ADDED
File without changes
WebSSH/__main__.py ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import webssh
3
+ import logging
4
+ import paramiko
5
+ import subprocess
6
+ import tornado.web
7
+ import tornado.ioloop
8
+ from tornado.options import define, options
9
+ from webssh.handler import IndexHandler, WsockHandler, NotFoundHandler
10
+ from .Fonts import Font, get_font_filename, base_dir, font_dirs, max_body_size
11
+ from .Tools import get_ssl_context, get_server_settings, check_encoding_setting, print_version
12
+
13
+ logging.getLogger("tornado.access").setLevel(logging.DEBUG)
14
+ logging.getLogger("tornado.application").setLevel(logging.DEBUG)
15
+ logging.getLogger("tornado.general").setLevel(logging.DEBUG)
16
+
17
+ # Define application options
18
+ define('address', default='0.0.0.0', help='Listen address')
19
+ define('port', type=int, default=7860, help='Listen port')
20
+ define('ssladdress', default='', help='SSL listen address')
21
+ define('sslport', type=int, default=4433, help='SSL listen port')
22
+ define('certfile', default='', help='SSL certificate file')
23
+ define('keyfile', default='', help='SSL private key file')
24
+ define('debug', type=bool, default=True, help='Debug mode')
25
+ define('policy', default='autoadd', help='Missing host key policy, reject|autoadd|warning')
26
+ define('hostfile', default='', help='User defined host keys file')
27
+ define('syshostfile', default='', help='System wide host keys file')
28
+ define('tdstream', default='', help='Trusted downstream, separated by comma')
29
+ define('redirect', type=bool, default=True, help='Redirecting http to https')
30
+ define('fbidhttp', type=bool, default=False, help='Forbid public plain http incoming requests')
31
+ define('xheaders', type=bool, default=False, help='Support xheaders')
32
+ define('xsrf', type=bool, default=False, help='CSRF protection')
33
+ define(
34
+ "origin",
35
+ default="*",
36
+ help="""Origin policy,
37
+ 'same': same origin policy, matches host name and port number;
38
+ 'primary': primary domain policy, matches primary domain only;
39
+ '<domains>': custom domains policy, matches any domain in the <domains> list
40
+ separated by comma;
41
+ '*': wildcard policy, matches any domain, allowed in debug mode only.""",
42
+ )
43
+ define('wpintvl', type=float, default=0, help='Websocket ping interval')
44
+ define('timeout', type=float, default=60, help='SSH connection timeout')
45
+ define('delay', type=float, default=60, help='The delay to call recycle_worker')
46
+ define('maxconn', type=int, default=5, help='Maximum live connections (ssh sessions) per client')
47
+ define('font', default='', help='custom font filename')
48
+
49
+ define(
50
+ "encoding",
51
+ default="utf-8",
52
+ help="""The default character encoding of ssh servers.
53
+ Example: --encoding='utf-8' to solve the problem with some switches&routers""",
54
+ )
55
+
56
+ define('version', type=bool, help='Show version information',callback=print_version)
57
+
58
+ # New handler for your custom page
59
+ class AppHandler(tornado.web.RequestHandler):
60
+ # Define the path to the templates directory
61
+ HandlerPath = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),'WebSSH', 'templates')
62
+ template_folder = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'WebSSH', 'templates')
63
+
64
+ def get(self):
65
+ self.render(os.path.join(self.template_folder, 'index.html'))
66
+
67
+ def post(self):
68
+ username = self.get_argument("username")
69
+ password = self.get_argument("password")
70
+
71
+ # Check if the user already exists
72
+ user_exists = subprocess.run(["id", "-u", username], capture_output=True)
73
+ if user_exists.returncode == 0:
74
+ # User exists, read the existing SSH key
75
+ ssh_dir = f"/home/{username}/.ssh"
76
+ private_key_path = f"{ssh_dir}/id_rsa"
77
+ if os.path.exists(private_key_path):
78
+ with open(private_key_path, "r") as file:
79
+ private_key = file.read()
80
+ else:
81
+ self.set_status(404)
82
+ self.write("SSH key not found for existing user.")
83
+ return
84
+ else:
85
+ """
86
+ # Create the user directory and .ssh directory manually
87
+ user_home = f"/home/{username}"
88
+ ssh_dir = f"{user_home}/.ssh"
89
+ os.makedirs(ssh_dir, exist_ok=True)
90
+
91
+ # Generate SSH key pair for the new user
92
+ subprocess.run(["ssh-keygen", "-t", "rsa", "-b", "2048", "-f", f"{ssh_dir}/id_rsa", "-N", ""])
93
+
94
+ # Read the private key
95
+ with open(f"{ssh_dir}/id_rsa", "r") as file:
96
+ private_key = file.read()
97
+ """
98
+ self.set_status(404)
99
+ self.write("SSH key not found for existing user.")
100
+ return
101
+
102
+ # Return the private key to the user
103
+ self.set_header('Content-Type', 'application/octet-stream')
104
+ self.set_header('Content-Disposition', f'attachment; filename=id_rsa')
105
+ self.write(private_key)
106
+
107
+
108
+ def make_app(loop):
109
+ # Set SSH host key policy
110
+ policy = paramiko.AutoAddPolicy() if options.policy == 'autoadd' else paramiko.RejectPolicy()
111
+ # Define host keys settings
112
+ host_keys_settings = {
113
+ 'system_host_keys': paramiko.util.load_host_keys('/app/ssh/ssh_known_hosts'),
114
+ 'host_keys': paramiko.HostKeys(),
115
+ 'host_keys_filename': None
116
+ }
117
+ template_path=os.path.join(base_dir, '', 'templates'),
118
+ static_path=os.path.join(base_dir, '', 'static'),
119
+
120
+ #print(f"* Path: {base_dir},\n* Template Path: {template_path}, \n* Static Path: {static_path}")
121
+
122
+ # Create Tornado application
123
+ return tornado.web.Application(
124
+ [
125
+ (r'/', IndexHandler, dict(loop=loop, policy=policy, host_keys_settings=host_keys_settings)),
126
+ (r'/ws', WsockHandler, dict(loop=loop)),
127
+ (r'/app', AppHandler), # Route for your new page
128
+ ],
129
+ xsrf_cookies=options.xsrf,
130
+ debug=options.debug,
131
+ font=Font(
132
+ get_font_filename(options.font, os.path.join(base_dir, *font_dirs)),
133
+ font_dirs[1:]
134
+ ),
135
+ template_path=os.path.join(base_dir, '', 'templates'),
136
+ static_path=os.path.join(base_dir, '', 'static'),
137
+ #websocket_ping_interval=options.wpintvl,
138
+ #origin_policy=get_origin_setting(options),
139
+ )
140
+
141
+ def app_listen(app, port, address, server_settings):
142
+ app.listen(port, address, **server_settings)
143
+ if not server_settings.get('ssl_options'):
144
+ server_type = 'http'
145
+ else:
146
+ server_type = 'https'
147
+ handler.redirecting = True if options.redirect else False
148
+ logging.info('Listening on {}:{} ({})'.format(address, port, server_type))
149
+
150
+
151
+ if __name__ == '__main__':
152
+ loop = tornado.ioloop.IOLoop.current()
153
+ check_encoding_setting(options.encoding)
154
+ # Parse command-line options
155
+ tornado.options.parse_command_line()
156
+ # Create and start the application
157
+ app = make_app(loop)
158
+ ssl_ctx = get_ssl_context(options)
159
+ server_settings = get_server_settings(options)
160
+ app_listen(app, options.port, options.address, server_settings)
161
+ if ssl_ctx:
162
+ server_settings.update(ssl_options=ssl_ctx)
163
+ app_listen(app, options.sslport, options.ssladdress, server_settings)
164
+
165
+ loop.start()
WebSSH/maink.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tornado.ioloop
2
+ import tornado.web
3
+ import paramiko
4
+ from webssh.handler import IndexHandler, WsockHandler
5
+ from tornado.options import define, options
6
+
7
+ # Define application options
8
+ define('address', default='0.0.0.0', help='Bind address')
9
+ define('port', default=7860, help='Port to listen on')
10
+ define('xsrf', default=False, help='Enable XSRF protection')
11
+ define('debug', default=True, help='Enable debug mode')
12
+ define('maxconn', default=4, help='Maximum number of connections')
13
+ define('policy', default='autoadd', help='SSH host key policy')
14
+ define('sslport', default=443, help='SSL port for redirect')
15
+ define('timeout', default=30, help='SSH connection timeout')
16
+ define('encoding', default='utf-8', help='Default encoding')
17
+ define('delay', default=10, help='Delay before recycling worker')
18
+ define('xheaders', default=False, help='Support X-Real-Ip and X-Forwarded-For headers')
19
+ define('fbidhttp', default=False, help='Forbid public plain HTTP requests')
20
+
21
+ # New handler for your custom page
22
+ class MyPageHandler(tornado.web.RequestHandler):
23
+ def get(self):
24
+ self.render('mypage.html') # Render the new page template
25
+
26
+ def make_app():
27
+ loop = tornado.ioloop.IOLoop.current()
28
+
29
+ # Set SSH host key policy
30
+ policy = paramiko.AutoAddPolicy() if options.policy == 'autoadd' else paramiko.RejectPolicy()
31
+
32
+ # Define host keys settings
33
+ host_keys_settings = {
34
+ 'system_host_keys': paramiko.util.load_host_keys('/app/ssh/ssh_known_hosts'),
35
+ 'host_keys': paramiko.HostKeys(),
36
+ 'host_keys_filename': None
37
+ }
38
+
39
+ # Create Tornado application
40
+ return tornado.web.Application(
41
+ [
42
+ (r'/', IndexHandler, dict(loop=loop, policy=policy, host_keys_settings=host_keys_settings)),
43
+ (r'/ws', WsockHandler, dict(loop=loop)),
44
+ (r'/mypage', MyPageHandler), # Route for your new page
45
+ ],
46
+ xsrf_cookies=options.xsrf,
47
+ debug=options.debug,
48
+ template_path='/app/WebSSH/templates', # Correct template directory
49
+ )
50
+
51
+ if __name__ == '__main__':
52
+ # Parse command-line options
53
+ tornado.options.parse_command_line()
54
+
55
+ # Create and start the application
56
+ app = make_app()
57
+ app.listen(options.port, address=options.address)
58
+ print(f"WebSSH server running on {options.address}:{options.port}")
59
+ tornado.ioloop.IOLoop.current().start()
WebSSH/requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ tornado
2
+ webssh
3
+ paramiko
4
+ Jinja2
5
+ logging
WebSSH/static/img/favicon.png ADDED
WebSSH/templates/index.html ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title> WebSSH </title>
6
+ <link href="static/img/favicon.png" rel="icon" type="image/png">
7
+ </head>
8
+ <body>
9
+ <div class="container">
10
+ <h1>Create New User</h1>
11
+ <form action="/app" method="post">
12
+ <label for="username">Username:</label>
13
+ <input type="text" id="username" name="username" required><br>
14
+ <label for="password">Password:</label>
15
+ <input type="password" id="password" name="password" required><br>
16
+ <button type="submit">Create User</button>
17
+ </form>
18
+ </div>
19
+ </body>
20
+ </html>
start.sh ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+
3
+ # Print the current hostname
4
+ echo "* The hostname of this container is: $(cat /etc/hostname)"
5
+ echo "* The host of this container is: $(cat /etc/hosts)"
6
+ echo "* ID of the user running the script: $(id -u) * Group: $(id -g) * Status of Admin : $(id admin)"
7
+
8
+ # Check if SSH host keys are present, if not generate them in a writable location
9
+ if [ ! -f /etc/ssh/ssh_host_rsa_key ]; then
10
+ echo "* Generating SSH host keys *"
11
+ mkdir -p /app/ssh
12
+ ssh-keygen -t rsa -b 2048 -f /app/ssh/ssh_host_rsa_key -N ""
13
+ ssh-keygen -t ecdsa -b 256 -f /app/ssh/ssh_host_ecdsa_key -N ""
14
+ ssh-keygen -t ed25519 -f /app/ssh/ssh_host_ed25519_key -N ""
15
+ mv /app/ssh/ssh_host_* /etc/ssh/
16
+ fi
17
+
18
+ # Check if SSH service is running
19
+ if ! pgrep -x "sshd" > /dev/null; then
20
+ echo "* Starting SSH server on port : 2222 *"
21
+ #/usr/sbin/sshd
22
+ /usr/sbin/sshd -p 2222
23
+ else
24
+ echo "* SSH server is already running. *"
25
+ fi
26
+
27
+ # Check if admin user exists
28
+ if ! id -u admin &>/dev/null; then
29
+ adduser -D admin
30
+ echo "admin:password" | chpasswd
31
+ fi
32
+
33
+ # Generate SSH keys for admin user if not already present
34
+ if [ ! -f /home/admin/.ssh/id_rsa ]; then
35
+ echo "* Generating SSH key for admin user *"
36
+ mkdir -p /home/admin/.ssh
37
+ ssh-keygen -t rsa -b 2048 -f /home/admin/.ssh/id_rsa -q -N ""
38
+ chown -R admin:admin /home/admin/.ssh
39
+ chmod 700 /home/admin/.ssh
40
+ chmod 600 /home/admin/.ssh/id_rsa
41
+ chmod 644 /home/admin/.ssh/id_rsa.pub
42
+ fi
43
+
44
+ # Add public key to authorized_keys for admin user
45
+ if [ ! -f /home/admin/.ssh/authorized_keys ]; then
46
+ cat /home/admin/.ssh/id_rsa.pub >> /home/admin/.ssh/authorized_keys
47
+ chmod 600 /home/admin/.ssh/authorized_keys
48
+ chown admin:admin /home/admin/.ssh/authorized_keys
49
+ fi
50
+
51
+ #echo "* Contents of id_rsa:"
52
+ #cat /home/admin/.ssh/id_rsa
53
+
54
+ # Test SSH login locally
55
+ #ssh -o StrictHostKeyChecking=no -i /home/admin/.ssh/id_rsa admin@127.0.0.1 -p 2222 exit
56
+
57
+ #if [ $? -eq 0 ]; then
58
+ # echo "* Admin SSH key-based login successful."
59
+ #else
60
+ # echo "* Admin SSH key-based login failed!" >&2
61
+ #fi
62
+
63
+ echo "* Status of SSH service:"
64
+ netstat -tuln
65
+
66
+ # Test if admin's credentials are correct
67
+ #echo "* Testing admin's SSH login locally *"
68
+ #ssh -o StrictHostKeyChecking=no -i /home/admin/.ssh/id_rsa admin@127.0.0.1 -p 2222 exit
69
+
70
+ #if [ $? -eq 0 ]; then
71
+ # echo "* Admin credentials are valid."
72
+ #else
73
+ # echo "* Admin login failed! Check the password for 'admin' user." >&2
74
+ #fi
75
+
76
+ # Activate virtual environment
77
+ source /app/venv/bin/activate
78
+
79
+ # Set working directory for the application
80
+ cd /app
81
+
82
+ # Print list of the contents inside this directory
83
+ echo "* Contents of /app directory: *"
84
+ ls -la /app
85
+
86
+ python -u -m WebSSH
87
+
88
+ #wssh --address='0.0.0.0' --port=7860 --xsrf=False --debug=True --maxconn=4 --policy=autoadd
89
+ #wssh --address='0.0.0.0' --port=7860 --xsrf=False --debug=True --maxconn=4 --policy=reject
90
+ #wssh --address='0.0.0.0' --port=7860 --xsrf=False --debug=True --maxconn=4 --policy=accept
91
+ # Keep the container running
92
+ tail -f /dev/null