forked from k0baya/X-for-serv00
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
189 lines (171 loc) · 5.22 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
const username = process.env.WEB_USERNAME || "admin";
const password = process.env.WEB_PASSWORD || "password";
const port = process.env.WEBPORT;
const UUID = process.env.UUID;
const express = require("express");
const fs = require('fs');
const app = express();
var exec = require("child_process").exec;
const { createProxyMiddleware } = require("http-proxy-middleware");
const auth = require("basic-auth");
function getFourthLine(filename, callback) {
fs.readFile(filename, 'utf8', function(err, data) {
if (err) {
return callback(err);
}
const lines = data.split('\n');
if (lines.length >= 4) {
callback(null, lines[3]);
} else {
callback(new Error('Subscribution does not have four lines.'));
}
});
}
app.get("/", function (req, res) {
res.send("hello world");
});
// 设置路由
app.get(`/${UUID}/vm`, (req, res) => {
getFourthLine('list', (err, sub) => {
if (err) {
return res.status(500).send('Error reading file.');
}
res.send(sub);
});
});
// 页面访问密码
app.use((req, res, next) => {
const user = auth(req);
if (user && user.name === username && user.pass === password) {
return next();
}
res.set("WWW-Authenticate", 'Basic realm="Node"');
return res.status(401).send();
});
app.get("/status", function (req, res) {
let cmdStr =
"ps -ef";
exec(cmdStr, function (err, stdout, stderr) {
if (err) {
res.type("html").send("<pre>命令行执行错误:\n" + err + "</pre>");
} else {
res.type("html").send("<pre>获取系统进程表:\n" + stdout + "</pre>");
}
});
});
//获取节点数据
app.get("/list", async function (req, res) {
let cmdStr = "cat list";
const sub = UUID;
const fileExists = (path) => {
return new Promise((resolve, reject) => {
fs.access(path, fs.constants.F_OK, (err) => {
resolve(!err);
});
});
};
const waitForFile = async (path, retries, interval) => {
for (let i = 0; i < retries; i++) {
if (await fileExists(path)) {
return true;
}
await new Promise(resolve => setTimeout(resolve, interval));
}
return false;
};
const fileReady = await waitForFile('list', 30, 1000);
if (!fileReady) {
res.type("html").send("<pre>文件未生成</pre>");
return;
}
exec(cmdStr, function (err, stdout, stderr) {
if (err) {
res.type("html").send("<pre>命令行执行错误:\n" + err + "</pre>");
} else {
const fullUrl = `${req.protocol}://${req.get('host')}/${sub}/vm`;
res.type("html").send("<pre>V2ray订阅地址:" + fullUrl + "\n\n节点数据:\n\n" + stdout + "</pre>");
}
});
});
// keepalive begin
//web保活
function keep_web_alive() {
exec("pgrep -laf web.js", function (err, stdout, stderr) {
// 1.查后台系统进程,保持唤醒
if (stdout.includes("./web.js -c ./config.json")) {
console.log("web 正在运行");
} else {
//web 未运行,命令行调起
exec(
"chmod +x web.js && ./web.js -c ./config.json >/dev/null 2>&1 &",
function (err, stdout, stderr) {
if (err) {
console.log("保活-调起web-命令行执行错误:" + err);
} else {
console.log("保活-调起web-命令行执行成功!");
}
}
);
}
});
}
setInterval(keep_web_alive, 10 * 1000);
//Argo保活
function keep_argo_alive() {
exec("pgrep -laf cloudflared", function (err, stdout, stderr) {
// 1.查后台系统进程,保持唤醒
if (stdout.includes("./cloudflared tunnel")) {
console.log("Argo 正在运行");
} else {
//Argo 未运行,命令行调起
exec("bash argo.sh 2>&1 &", function (err, stdout, stderr) {
if (err) {
console.log("保活-调起Argo-命令行执行错误:" + err);
} else {
console.log("保活-调起Argo-命令行执行成功!");
}
});
}
});
}
setInterval(keep_argo_alive, 30 * 1000);
app.use(
"/",
createProxyMiddleware({
changeOrigin: true, // 默认false,是否需要改变原始主机头为目标URL
onProxyReq: function onProxyReq(proxyReq, req, res) {},
pathRewrite: {
// 请求中去除/
"^/": "/",
},
target: "http://127.0.0.1:${PORT1}/", // 需要跨域处理的请求地址
ws: true, // 是否代理websockets
})
);
function download_web(callback) {
let cmdStr = "mkdir -p tmp && cd tmp && wget https://github.com/XTLS/Xray-core/releases/latest/download/Xray-freebsd-64.zip && unzip Xray-freebsd-64.zip && cd .. && mv -f ./tmp/xray ./web.js && rm -rf tmp && chmod +x web.js";
exec(cmdStr, function (err, stdout, stderr) {
if (err) {
console.log("初始化-下载web文件失败:" + err);
} else {
console.log("初始化-下载web文件成功!");
}
});
}
download_web((err) => {
if (err) {
console.log("初始化-下载web文件失败");
}
else {
console.log("初始化-下载web文件成功");
}
});
// 启动核心脚本运行web和argo
exec("bash entrypoint.sh", function (err, stdout, stderr) {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
app.listen(port, () => console.log(`Example app listening on port ${port}!`));