mirror of
https://github.com/PhyreApps/PhyrePanel.git
synced 2024-11-21 15:10:25 +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
|
||||
/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