mirror of
https://github.com/PhyreApps/PhyrePanel.git
synced 2024-11-25 00:50:32 +00:00
update
This commit is contained in:
parent
a9d5fc38a1
commit
c54d1956d3
10 changed files with 283 additions and 2 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,4 +1,2 @@
|
||||||
web/storage/installed
|
web/storage/installed
|
||||||
/docker/e2e-tests/node_modules/
|
/docker/e2e-tests/node_modules/
|
||||||
compilators/
|
|
||||||
web/thirdparty/
|
|
||||||
|
|
9
compilators/debian/web-terminal/.eslintrc.cjs
Normal file
9
compilators/debian/web-terminal/.eslintrc.cjs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: false,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'no-console': 'off',
|
||||||
|
},
|
||||||
|
};
|
9
compilators/debian/web-terminal/control
Normal file
9
compilators/debian/web-terminal/control
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
Source: phyre-web-terminal
|
||||||
|
Package: phyre-web-terminal
|
||||||
|
Priority: optional
|
||||||
|
Version: 1.0.0
|
||||||
|
Section: admin
|
||||||
|
Maintainer: PhyrePanel <info@phyrepanel.com>
|
||||||
|
Homepage: https://www.phyrepanel.com
|
||||||
|
Architecture: amd64
|
||||||
|
Description: Phyre Web Terminal
|
29
compilators/debian/web-terminal/copyright
Normal file
29
compilators/debian/web-terminal/copyright
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: phyre
|
||||||
|
Source: https://www.phyrepanel.com
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2018-2023, Phyre Control Panel <info@phyrepanel.com>
|
||||||
|
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 <http://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.
|
||||||
|
|
||||||
|
# Please also look if there are files or directories which have a
|
||||||
|
# different copyright/license attached and list them here.
|
||||||
|
# Please avoid to pick license terms that are more restrictive than the
|
||||||
|
# packaged work, as it may make Debian's contributions unacceptable upstream.
|
17
compilators/debian/web-terminal/package.json
Normal file
17
compilators/debian/web-terminal/package.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "cloudvisionapps/phyre-web-terminal-ws",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node server.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"node-pty": "^1.0.0",
|
||||||
|
"ws": "^8.16.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/ws": "^8.5.10",
|
||||||
|
"@types/node": "^20.12.5"
|
||||||
|
}
|
||||||
|
}
|
16
compilators/debian/web-terminal/phyre-web-terminal.service
Normal file
16
compilators/debian/web-terminal/phyre-web-terminal.service
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Phyre Web Terminal
|
||||||
|
Documentation=https://phyrepanel.com/docs/
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=root
|
||||||
|
Group=phyre-users
|
||||||
|
Environment=NODE_ENV=production
|
||||||
|
Environment=PHYRE=/usr/local/phyre
|
||||||
|
ExecStart=/usr/local/phyre/web-terminal/server.js
|
||||||
|
ExecStop=/bin/kill -s TERM $MAINPID
|
||||||
|
Restart=on-failure
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
30
compilators/debian/web-terminal/postinst
Normal file
30
compilators/debian/web-terminal/postinst
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "$1" != "configure" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run triggers below only on updates
|
||||||
|
if [ ! -e "/usr/local/phyre/data/users/admin" ]; then
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
###############################################################
|
||||||
|
# Initialize functions/variables #
|
||||||
|
###############################################################
|
||||||
|
|
||||||
|
if [ -z "$PHYRE" ]; then
|
||||||
|
export PHYRE='/usr/local/phyre'
|
||||||
|
PATH=$PATH:/usr/local/phyre/bin
|
||||||
|
export PATH
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restart hestia-web-terminal service if enabled
|
||||||
|
if [ -f "/etc/systemd/system/phyre-web-terminal.service" ]; then
|
||||||
|
systemctl daemon-reload > /dev/null 2>&1
|
||||||
|
if systemctl is-enabled phyre-web-terminal > /dev/null 2>&1; then
|
||||||
|
systemctl restart phyre-web-terminal
|
||||||
|
fi
|
||||||
|
fi
|
2
compilators/debian/web-terminal/postrm
Normal file
2
compilators/debian/web-terminal/postrm
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
121
compilators/debian/web-terminal/server.js
Normal file
121
compilators/debian/web-terminal/server.js
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import { execSync } from 'node:child_process';
|
||||||
|
import { readFileSync } from 'node:fs';
|
||||||
|
import { spawn } from 'node-pty';
|
||||||
|
import { WebSocketServer } from 'ws';
|
||||||
|
|
||||||
|
const sessionName = 'PHYRESID';
|
||||||
|
const hostname = execSync('hostname', { silent: true }).toString().trim();
|
||||||
|
// const systemIPs = JSON.parse(
|
||||||
|
// execSync(`${process.env.PHYRE}/bin/v-list-sys-ips json`, { silent: true }).toString(),
|
||||||
|
// );
|
||||||
|
const systemIPs = [];
|
||||||
|
// const { config } = JSON.parse(
|
||||||
|
// execSync(`${process.env.PHYRE}/bin/v-list-sys-config json`, { silent: true }).toString(),
|
||||||
|
// );
|
||||||
|
const config = {
|
||||||
|
WEB_TERMINAL_PORT: 3000,
|
||||||
|
BACKEND_PORT: 8083,
|
||||||
|
};
|
||||||
|
|
||||||
|
const wss = new WebSocketServer({
|
||||||
|
port: parseInt(config.WEB_TERMINAL_PORT, 10),
|
||||||
|
verifyClient: async (info, cb) => {
|
||||||
|
if (!info.req.headers.cookie.includes(sessionName)) {
|
||||||
|
cb(false, 401, 'Unauthorized');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const origin = info.origin || info.req.headers.origin;
|
||||||
|
let matches = origin === `https://${hostname}:${config.BACKEND_PORT}`;
|
||||||
|
|
||||||
|
if (!matches) {
|
||||||
|
for (const ip of Object.keys(systemIPs)) {
|
||||||
|
if (origin === `https://${ip}:${config.BACKEND_PORT}`) {
|
||||||
|
matches = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches) {
|
||||||
|
cb(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cb(false, 403, 'Forbidden');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wss.on('connection', (ws, req) => {
|
||||||
|
wss.clients.add(ws);
|
||||||
|
|
||||||
|
const remoteIP = req.headers['x-real-ip'] || req.socket.remoteAddress;
|
||||||
|
|
||||||
|
// Check if session is valid
|
||||||
|
const sessionID = req.headers.cookie.split(`${sessionName}=`)[1].split(';')[0];
|
||||||
|
console.log(`New connection from ${remoteIP} (${sessionID})`);
|
||||||
|
|
||||||
|
const file = readFileSync(`${process.env.HESTIA}/data/sessions/sess_${sessionID}`);
|
||||||
|
if (!file) {
|
||||||
|
console.error(`Invalid session ID ${sessionID}, refusing connection`);
|
||||||
|
ws.close(1000, 'Your session has expired.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const session = file.toString();
|
||||||
|
|
||||||
|
// Get username
|
||||||
|
const login = session.split('user|s:')[1].split('"')[1];
|
||||||
|
const impersonating = session.split('look|s:')[1].split('"')[1];
|
||||||
|
const username = impersonating.length > 0 ? impersonating : login;
|
||||||
|
|
||||||
|
// Get user info
|
||||||
|
const passwd = readFileSync('/etc/passwd').toString();
|
||||||
|
const userline = passwd.split('\n').find((line) => line.startsWith(`${username}:`));
|
||||||
|
if (!userline) {
|
||||||
|
console.error(`User ${username} not found, refusing connection`);
|
||||||
|
ws.close(1000, 'You are not allowed to access this server.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [, , uid, gid, , homedir, shell] = userline.split(':');
|
||||||
|
|
||||||
|
if (shell.endsWith('nologin')) {
|
||||||
|
console.error(`User ${username} has no shell, refusing connection`);
|
||||||
|
ws.close(1000, 'You have no shell access.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn shell as logged in user
|
||||||
|
const pty = spawn(shell, [], {
|
||||||
|
name: 'xterm-color',
|
||||||
|
uid: parseInt(uid, 10),
|
||||||
|
gid: parseInt(gid, 10),
|
||||||
|
cwd: homedir,
|
||||||
|
env: {
|
||||||
|
SHELL: shell,
|
||||||
|
TERM: 'xterm-color',
|
||||||
|
USER: username,
|
||||||
|
HOME: homedir,
|
||||||
|
PWD: homedir,
|
||||||
|
PHYRE: process.env.PHYRE,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log(`New pty (${pty.pid}): ${shell} as ${username} (${uid}:${gid}) in ${homedir}`);
|
||||||
|
|
||||||
|
// Send/receive data from websocket/pty
|
||||||
|
pty.on('data', (data) => ws.send(data));
|
||||||
|
ws.on('message', (data) => pty.write(data));
|
||||||
|
|
||||||
|
// Ensure pty is killed when websocket is closed and vice versa
|
||||||
|
pty.on('exit', () => {
|
||||||
|
console.log(`Ended pty (${pty.pid})`);
|
||||||
|
if (ws.OPEN) {
|
||||||
|
ws.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ws.on('close', () => {
|
||||||
|
console.log(`Ended connection from ${remoteIP} (${sessionID})`);
|
||||||
|
pty.kill();
|
||||||
|
wss.clients.delete(ws);
|
||||||
|
});
|
||||||
|
});
|
50
compilators/debian/web-terminal/web-terminal-compile.sh
Normal file
50
compilators/debian/web-terminal/web-terminal-compile.sh
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
MAIN_DIR=$(pwd)
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y build-essential dpkg-dev debhelper autotools-dev libgeoip-dev libssl-dev libpcre3-dev zlib1g-dev
|
||||||
|
|
||||||
|
sudo apt-get install -y npm nodejs
|
||||||
|
|
||||||
|
# Package main dir is the path of the clean debian package
|
||||||
|
# In PACKAGE_MAIN_DIR must exist only the directories that will be copied to the final debian package
|
||||||
|
|
||||||
|
sudo mkdir $MAIN_DIR/phyre-web-terminal-0.0.1
|
||||||
|
PACKAGE_MAIN_DIR=$MAIN_DIR/phyre-web-terminal-0.0.1
|
||||||
|
|
||||||
|
# Create debian package directories
|
||||||
|
sudo mkdir -p $PACKAGE_MAIN_DIR/DEBIAN
|
||||||
|
sudo mkdir -p $PACKAGE_MAIN_DIR/usr/local/phyre/web-terminal
|
||||||
|
|
||||||
|
# Copy web-terminal files
|
||||||
|
sudo cp $MAIN_DIR/.eslintrc.cjs $PACKAGE_MAIN_DIR/usr/local/phyre/web-terminal
|
||||||
|
sudo cp $MAIN_DIR/server.js $PACKAGE_MAIN_DIR/usr/local/phyre/web-terminal
|
||||||
|
sudo cp $MAIN_DIR/package.json $PACKAGE_MAIN_DIR/usr/local/phyre/web-terminal
|
||||||
|
|
||||||
|
cd $PACKAGE_MAIN_DIR/usr/local/phyre/web-terminal
|
||||||
|
sudo chmod +x $PACKAGE_MAIN_DIR/usr/local/phyre/web-terminal/server.js
|
||||||
|
|
||||||
|
# Compile web-terminal
|
||||||
|
cd $PACKAGE_MAIN_DIR/usr/local/phyre/web-terminal
|
||||||
|
sudo npm install
|
||||||
|
|
||||||
|
# Copy debian package META file
|
||||||
|
sudo cp $MAIN_DIR/control $PACKAGE_MAIN_DIR/DEBIAN
|
||||||
|
sudo cp $MAIN_DIR/postinst $PACKAGE_MAIN_DIR/DEBIAN
|
||||||
|
sudo cp $MAIN_DIR/postrm $PACKAGE_MAIN_DIR/DEBIAN
|
||||||
|
|
||||||
|
# Set debian package post files permissions
|
||||||
|
sudo chmod +x $PACKAGE_MAIN_DIR/DEBIAN/postinst
|
||||||
|
sudo chmod +x $PACKAGE_MAIN_DIR/DEBIAN/postrm
|
||||||
|
|
||||||
|
|
||||||
|
# Make debian package
|
||||||
|
sudo dpkg-deb --build $PACKAGE_MAIN_DIR
|
||||||
|
sudo dpkg --info $MAIN_DIR/phyre-web-terminal-0.0.1.deb
|
||||||
|
sudo dpkg --contents $MAIN_DIR/phyre-web-terminal-0.0.1.deb
|
||||||
|
|
||||||
|
# Move debian package to dist folder
|
||||||
|
sudo mkdir -p $MAIN_DIR/dist
|
||||||
|
sudo mv $MAIN_DIR/phyre-web-terminal-0.0.1.deb $MAIN_DIR/dist
|
Loading…
Reference in a new issue