ok
Browse files- Dockerfile +28 -34
- app.js +22 -42
- package.json +1 -2
- start.sh +4 -34
Dockerfile
CHANGED
@@ -1,53 +1,47 @@
|
|
|
|
1 |
FROM node:20
|
2 |
|
3 |
-
|
4 |
-
|
5 |
|
|
|
6 |
RUN apt-get update && apt-get install -y \
|
7 |
-
|
8 |
-
python3-pip \
|
9 |
-
wget \
|
10 |
-
curl \
|
11 |
-
gnupg \
|
12 |
-
build-essential \
|
13 |
-
zlib1g-dev \
|
14 |
-
iproute2 \
|
15 |
-
&& apt-get clean \
|
16 |
&& rm -rf /var/lib/apt/lists/*
|
17 |
|
18 |
-
|
19 |
-
|
|
|
20 |
|
21 |
-
|
22 |
-
|
23 |
-
&& cd dropbear-2024.85 \
|
24 |
-
&& ./configure \
|
25 |
-
&& make \
|
26 |
-
&& make install \
|
27 |
-
&& cd .. \
|
28 |
-
&& rm -rf dropbear-2024.85 dropbear-2024.85.tar.bz2
|
29 |
|
30 |
-
#
|
|
|
|
|
|
|
31 |
RUN if id 1000 >/dev/null 2>&1; then \
|
32 |
userdel -f $(id -nu 1000); \
|
33 |
fi \
|
34 |
&& useradd -u 1000 -m -s /bin/bash user \
|
35 |
&& echo 'user:password' | chpasswd
|
36 |
|
37 |
-
#
|
38 |
-
|
|
|
39 |
|
40 |
-
|
|
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
COPY . .
|
46 |
|
47 |
-
|
48 |
-
|
49 |
-
&& chown -R user:user /etc/dropbear
|
50 |
|
51 |
-
|
|
|
|
|
52 |
|
53 |
-
|
|
|
|
1 |
+
# 使用 Node.js 20 作为基础镜像
|
2 |
FROM node:20
|
3 |
|
4 |
+
# 设置工作目录
|
5 |
+
WORKDIR /app
|
6 |
|
7 |
+
# 安装必要的工具和 Dropbear
|
8 |
RUN apt-get update && apt-get install -y \
|
9 |
+
dropbear \
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
&& rm -rf /var/lib/apt/lists/*
|
11 |
|
12 |
+
# 复制 package.json 和 package-lock.json(如果存在)
|
13 |
+
COPY package*.json ./
|
14 |
+
|
15 |
|
16 |
+
# 安装依赖,包括 ssh2
|
17 |
+
RUN npm install ssh2
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
+
# 复制其余的源代码
|
20 |
+
COPY . .
|
21 |
+
|
22 |
+
# 创建一个新用户,UID 为 1000
|
23 |
RUN if id 1000 >/dev/null 2>&1; then \
|
24 |
userdel -f $(id -nu 1000); \
|
25 |
fi \
|
26 |
&& useradd -u 1000 -m -s /bin/bash user \
|
27 |
&& echo 'user:password' | chpasswd
|
28 |
|
29 |
+
# 设置 Dropbear
|
30 |
+
RUN mkdir -p /etc/dropbear
|
31 |
+
RUN dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
|
32 |
|
33 |
+
# 更改目录所有权
|
34 |
+
RUN chown -R user:user /app /etc/dropbear
|
35 |
|
36 |
+
# 切换到新用户
|
37 |
+
USER user
|
|
|
|
|
38 |
|
39 |
+
# 暴露 Web 应用端口和 Dropbear SSH 端口
|
40 |
+
EXPOSE 7860 2202
|
|
|
41 |
|
42 |
+
# 启动脚本
|
43 |
+
COPY start.sh /start.sh
|
44 |
+
RUN chmod +x /start.sh
|
45 |
|
46 |
+
# 使用启动脚本
|
47 |
+
CMD ["/start.sh"]
|
app.js
CHANGED
@@ -1,53 +1,33 @@
|
|
1 |
const express = require('express');
|
2 |
const { Client } = require('ssh2');
|
3 |
-
const fs = require('fs').promises;
|
4 |
-
|
5 |
const app = express();
|
6 |
-
const port =
|
7 |
|
8 |
app.use(express.json());
|
9 |
|
10 |
-
app.post('/
|
11 |
-
const
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
if (err) {
|
24 |
-
conn.end();
|
25 |
-
return res.status(500).json({ error: 'Failed to execute command' });
|
26 |
-
}
|
27 |
-
|
28 |
-
let output = '';
|
29 |
-
stream.on('close', (code, signal) => {
|
30 |
-
conn.end();
|
31 |
-
res.json({ output: output.trim(), code });
|
32 |
-
}).on('data', (data) => {
|
33 |
-
output += data;
|
34 |
-
}).stderr.on('data', (data) => {
|
35 |
-
output += data;
|
36 |
-
});
|
37 |
});
|
38 |
-
}).on('error', (err) => {
|
39 |
-
res.status(500).json({ error: 'SSH connection failed', details: err.message });
|
40 |
-
}).connect({
|
41 |
-
host: 'localhost',
|
42 |
-
port: 2222,
|
43 |
-
username: 'user',
|
44 |
-
privateKey
|
45 |
});
|
46 |
-
}
|
47 |
-
|
48 |
-
|
|
|
|
|
|
|
49 |
});
|
50 |
|
51 |
-
app.listen(port,
|
52 |
-
console.log(`
|
53 |
});
|
|
|
1 |
const express = require('express');
|
2 |
const { Client } = require('ssh2');
|
|
|
|
|
3 |
const app = express();
|
4 |
+
const port = 7860;
|
5 |
|
6 |
app.use(express.json());
|
7 |
|
8 |
+
app.post('/ssh', (req, res) => {
|
9 |
+
const conn = new Client();
|
10 |
+
conn.on('ready', () => {
|
11 |
+
conn.exec(req.body.command, (err, stream) => {
|
12 |
+
if (err) throw err;
|
13 |
+
let data = '';
|
14 |
+
stream.on('close', (code, signal) => {
|
15 |
+
conn.end();
|
16 |
+
res.send(data);
|
17 |
+
}).on('data', (chunk) => {
|
18 |
+
data += chunk;
|
19 |
+
}).stderr.on('data', (chunk) => {
|
20 |
+
data += chunk;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
});
|
23 |
+
}).connect({
|
24 |
+
host: 'localhost',
|
25 |
+
port: 2202,
|
26 |
+
username: 'user',
|
27 |
+
password: 'password'
|
28 |
+
});
|
29 |
});
|
30 |
|
31 |
+
app.listen(port, () => {
|
32 |
+
console.log(`Web SSH app listening at http://localhost:${port}`);
|
33 |
});
|
package.json
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
{
|
2 |
-
"name": "ssh-
|
3 |
"version": "1.0.0",
|
4 |
-
"description": "Web app to execute commands via SSH",
|
5 |
"main": "app.js",
|
6 |
"scripts": {
|
7 |
"start": "node app.js"
|
|
|
1 |
{
|
2 |
+
"name": "web-ssh-app",
|
3 |
"version": "1.0.0",
|
|
|
4 |
"main": "app.js",
|
5 |
"scripts": {
|
6 |
"start": "node app.js"
|
start.sh
CHANGED
@@ -1,37 +1,7 @@
|
|
1 |
#!/bin/bash
|
2 |
|
3 |
-
|
4 |
-
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
fi
|
9 |
-
|
10 |
-
if [ ! -f ~/.ssh/id_rsa ]; then
|
11 |
-
mkdir -p ~/.ssh
|
12 |
-
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
|
13 |
-
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
|
14 |
-
chmod 600 ~/.ssh/authorized_keys
|
15 |
-
fi
|
16 |
-
|
17 |
-
/usr/local/sbin/dropbear -R -F -E -p 2222 &
|
18 |
-
|
19 |
-
sleep 2
|
20 |
-
|
21 |
-
echo "测试SSH连接..."
|
22 |
-
if ssh -o StrictHostKeyChecking=no -p 2222 localhost 'echo SSH连接成功'; then
|
23 |
-
echo "SSH连接测试成功"
|
24 |
-
else
|
25 |
-
echo "SSH连接测试失败"
|
26 |
-
exit 1
|
27 |
-
fi
|
28 |
-
|
29 |
-
npm start &
|
30 |
-
|
31 |
-
echo "当前用户: $(whoami)"
|
32 |
-
echo "Dropbear 进程: $(pgrep dropbear)"
|
33 |
-
echo "Node.js 进程: $(pgrep node)"
|
34 |
-
echo "2222 端口监听状态: $(ss -tuln | grep 2222)"
|
35 |
-
echo "3000 端口监听状态: $(ss -tuln | grep 3000)"
|
36 |
-
|
37 |
-
wait
|
|
|
1 |
#!/bin/bash
|
2 |
|
3 |
+
# 启动 Dropbear,使用 2202 端口
|
4 |
+
dropbear -R -p 2202
|
5 |
|
6 |
+
# 启动 Node.js 应用
|
7 |
+
npm start
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|