ok
Browse files- Dockerfile +1 -55
- app.js +9 -46
- public/index.html +1 -1
Dockerfile
CHANGED
@@ -1,67 +1,13 @@
|
|
1 |
-
# 使用 Node.js 20 作为基础镜像
|
2 |
FROM node:20
|
3 |
|
4 |
-
# 设置工作目录
|
5 |
WORKDIR /app
|
6 |
|
7 |
-
# 安装必要的工具和依赖
|
8 |
-
RUN apt-get update && apt-get install -y \
|
9 |
-
build-essential \
|
10 |
-
zlib1g-dev \
|
11 |
-
libssl-dev \
|
12 |
-
wget \
|
13 |
-
net-tools \
|
14 |
-
iproute2 \
|
15 |
-
curl \
|
16 |
-
&& rm -rf /var/lib/apt/lists/*
|
17 |
-
|
18 |
-
# 下载并安装最新版本的 Dropbear
|
19 |
-
RUN wget https://matt.ucc.asn.au/dropbear/dropbear-2024.85.tar.bz2 \
|
20 |
-
&& tar xjf dropbear-2024.85.tar.bz2 \
|
21 |
-
&& cd dropbear-2024.85 \
|
22 |
-
&& ./configure \
|
23 |
-
&& make \
|
24 |
-
&& make install \
|
25 |
-
&& cd .. \
|
26 |
-
&& rm -rf dropbear-2024.85*
|
27 |
-
|
28 |
-
# 复制 package.json 和 package-lock.json(如果存在)
|
29 |
COPY package*.json ./
|
30 |
|
31 |
-
|
32 |
-
# 安装依赖,包括 ssh2
|
33 |
RUN npm install
|
34 |
|
35 |
-
# 复制其余的源代码和公共文件
|
36 |
COPY . .
|
37 |
|
38 |
-
ENV SSH_PASSWORD=password
|
39 |
-
|
40 |
-
# 检查 UID 1000 是否存在,如果存在则删除,然后创建新用户
|
41 |
-
RUN if id 1000 >/dev/null 2>&1; then \
|
42 |
-
userdel -f $(id -nu 1000); \
|
43 |
-
fi \
|
44 |
-
&& useradd -u 1000 -m -s /bin/bash user \
|
45 |
-
&& echo "user:${SSH_PASSWORD}" | chpasswd
|
46 |
-
|
47 |
-
# 设置 Dropbear
|
48 |
-
RUN mkdir -p /etc/dropbear \
|
49 |
-
&& chown -R user:user /etc/dropbear
|
50 |
-
|
51 |
-
# 更改目录所有权
|
52 |
-
RUN chown -R user:user /app /etc/dropbear \
|
53 |
-
&& chmod 700 /etc/dropbear
|
54 |
-
|
55 |
-
|
56 |
-
# 暴露 Web 应用端口和 Dropbear SSH 端口
|
57 |
EXPOSE 7860
|
58 |
|
59 |
-
|
60 |
-
COPY start.sh /start.sh
|
61 |
-
RUN chmod +x /start.sh
|
62 |
-
|
63 |
-
# 切换到新用户
|
64 |
-
USER user
|
65 |
-
|
66 |
-
# 使用启动脚本
|
67 |
-
CMD ["/start.sh"]
|
|
|
|
|
1 |
FROM node:20
|
2 |
|
|
|
3 |
WORKDIR /app
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
COPY package*.json ./
|
6 |
|
|
|
|
|
7 |
RUN npm install
|
8 |
|
|
|
9 |
COPY . .
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
EXPOSE 7860
|
12 |
|
13 |
+
CMD ["node", "app.js"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.js
CHANGED
@@ -1,62 +1,25 @@
|
|
1 |
const express = require('express');
|
2 |
-
const {
|
3 |
const app = express();
|
4 |
const port = 7860;
|
5 |
|
6 |
app.use(express.json());
|
7 |
app.use(express.static('public'));
|
8 |
|
9 |
-
// 根路径处理
|
10 |
app.get('/', (req, res) => {
|
11 |
res.sendFile(__dirname + '/public/index.html');
|
12 |
});
|
13 |
|
14 |
-
app.
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
try {
|
22 |
-
await new Promise((resolve, reject) => {
|
23 |
-
conn.on('ready', resolve)
|
24 |
-
.on('error', reject)
|
25 |
-
.connect({
|
26 |
-
host: 'localhost',
|
27 |
-
port: 2202,
|
28 |
-
username: 'user',
|
29 |
-
password: process.env.SSH_PASSWORD || 'password',
|
30 |
-
readyTimeout: 5000,
|
31 |
-
debug: console.log,
|
32 |
-
tryKeyboard: true
|
33 |
-
});
|
34 |
-
});
|
35 |
-
|
36 |
-
console.log('SSH Connection established');
|
37 |
-
|
38 |
-
const { stdout, stderr } = await new Promise((resolve, reject) => {
|
39 |
-
conn.exec(req.body.command, (err, stream) => {
|
40 |
-
if (err) reject(err);
|
41 |
-
let stdout = '', stderr = '';
|
42 |
-
stream.on('close', (code, signal) => {
|
43 |
-
resolve({ stdout, stderr, code, signal });
|
44 |
-
}).on('data', (data) => {
|
45 |
-
stdout += data;
|
46 |
-
}).stderr.on('data', (data) => {
|
47 |
-
stderr += data;
|
48 |
-
});
|
49 |
-
});
|
50 |
-
});
|
51 |
-
|
52 |
-
conn.end();
|
53 |
res.json({ output: stdout, error: stderr });
|
54 |
-
}
|
55 |
-
console.error('SSH error:', error);
|
56 |
-
res.status(500).json({ error: error.message });
|
57 |
-
}
|
58 |
});
|
59 |
|
60 |
app.listen(port, () => {
|
61 |
-
console.log(`Web
|
62 |
});
|
|
|
1 |
const express = require('express');
|
2 |
+
const { exec } = require('child_process');
|
3 |
const app = express();
|
4 |
const port = 7860;
|
5 |
|
6 |
app.use(express.json());
|
7 |
app.use(express.static('public'));
|
8 |
|
|
|
9 |
app.get('/', (req, res) => {
|
10 |
res.sendFile(__dirname + '/public/index.html');
|
11 |
});
|
12 |
|
13 |
+
app.post('/execute', (req, res) => {
|
14 |
+
exec(req.body.command, (error, stdout, stderr) => {
|
15 |
+
if (error) {
|
16 |
+
console.error(`执行错误: ${error}`);
|
17 |
+
return res.status(500).json({ error: error.message });
|
18 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
res.json({ output: stdout, error: stderr });
|
20 |
+
});
|
|
|
|
|
|
|
21 |
});
|
22 |
|
23 |
app.listen(port, () => {
|
24 |
+
console.log(`Web 命令执行应用正在监听 http://localhost:${port}`);
|
25 |
});
|
public/index.html
CHANGED
@@ -25,7 +25,7 @@
|
|
25 |
output.textContent = 'Executing command...';
|
26 |
|
27 |
try {
|
28 |
-
const response = await fetch('/
|
29 |
method: 'POST',
|
30 |
headers: { 'Content-Type': 'application/json' },
|
31 |
body: JSON.stringify({ command })
|
|
|
25 |
output.textContent = 'Executing command...';
|
26 |
|
27 |
try {
|
28 |
+
const response = await fetch('/execute', {
|
29 |
method: 'POST',
|
30 |
headers: { 'Content-Type': 'application/json' },
|
31 |
body: JSON.stringify({ command })
|