-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
217 lines (198 loc) · 7.22 KB
/
index.js
File metadata and controls
217 lines (198 loc) · 7.22 KB
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
const os = require('os');
const http = require('http');
const fs = require('fs');
const axios = require('axios');
const net = require('net');
const { Buffer } = require('buffer');
const { exec, execSync } = require('child_process');
const { WebSocket, createWebSocketStream } = require('ws');
const UUID = process.env.UUID || 'de04add9-5c68-6bab-950c-08cd5320df33'; // 运行哪吒v1,在不同的平台需要改UUID,否则会被覆盖
const NEZHA_SERVER = process.env.NEZHA_SERVER || ''; // 哪吒v1填写形式:nz.abc.com:8008 哪吒v0填写形式:nz.abc.com
const NEZHA_PORT = process.env.NEZHA_PORT || ''; // 哪吒v1没有此变量,v0的agent端口为{443,8443,2096,2087,2083,2053}其中之一时开启tls
const NEZHA_KEY = process.env.NEZHA_KEY || ''; // v1的NZ_CLIENT_SECRET或v0的agent端口
const DOMAIN = process.env.DOMAIN || ''; // 填写项目域名或已反代的域名,不带前缀,建议填已反代的域名
const AUTO_ACCESS = process.env.AUTO_ACCESS || true; // 是否开启自动访问保活,false为关闭,true为开启,需同时填写DOMAIN变量
const SUB_PATH = process.env.SUB_PATH || 'sub'; // 获取节点的订阅路径
const NAME = process.env.NAME || 'Vls'; // 节点名称
const PORT = process.env.PORT || 3000; // http和ws服务端口
const metaInfo = execSync(
'curl -s https://speed.cloudflare.com/meta | awk -F\\" \'{print $26"-"$18}\' | sed -e \'s/ /_/g\'',
{ encoding: 'utf-8' }
);
const ISP = metaInfo.trim();
const httpServer = http.createServer((req, res) => {
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World\n');
} else if (req.url === `/${SUB_PATH}`) {
const vlessURL = `vless://${UUID}@${DOMAIN}:443?encryption=none&security=tls&sni=${DOMAIN}&type=ws&host=${DOMAIN}&path=%2F#${NAME}-${ISP}`;
const base64Content = Buffer.from(vlessURL).toString('base64');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(base64Content + '\n');
} else {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not Found\n');
}
});
const wss = new WebSocket.Server({ server: httpServer });
const uuid = UUID.replace(/-/g, "");
wss.on('connection', ws => {
// console.log("Connected successfully");
ws.once('message', msg => {
const [VERSION] = msg;
const id = msg.slice(1, 17);
if (!id.every((v, i) => v == parseInt(uuid.substr(i * 2, 2), 16))) return;
let i = msg.slice(17, 18).readUInt8() + 19;
const port = msg.slice(i, i += 2).readUInt16BE(0);
const ATYP = msg.slice(i, i += 1).readUInt8();
const host = ATYP == 1 ? msg.slice(i, i += 4).join('.') :
(ATYP == 2 ? new TextDecoder().decode(msg.slice(i + 1, i += 1 + msg.slice(i, i + 1).readUInt8())) :
(ATYP == 3 ? msg.slice(i, i += 16).reduce((s, b, i, a) => (i % 2 ? s.concat(a.slice(i - 1, i + 1)) : s), []).map(b => b.readUInt16BE(0).toString(16)).join(':') : ''));
// console.log(`Connection from ${host}:${port}`);
ws.send(new Uint8Array([VERSION, 0]));
const duplex = createWebSocketStream(ws);
net.connect({ host, port }, function () {
this.write(msg.slice(i));
duplex.on('error', () => { }).pipe(this).on('error', () => { }).pipe(duplex);
}).on('error', () => { });
}).on('error', () => { });
});
const getDownloadUrl = () => {
const arch = os.arch();
if (arch === 'arm' || arch === 'arm64' || arch === 'aarch64') {
if (!NEZHA_PORT) {
return 'https://arm64.ssss.nyc.mn/v1';
} else {
return 'https://arm64.ssss.nyc.mn/agent';
}
} else {
if (!NEZHA_PORT) {
return 'https://amd64.ssss.nyc.mn/v1';
} else {
return 'https://amd64.ssss.nyc.mn/agent';
}
}
};
const downloadFile = async () => {
try {
const url = getDownloadUrl();
// console.log(`Start downloading file from ${url}`);
const response = await axios({
method: 'get',
url: url,
responseType: 'stream'
});
const writer = fs.createWriteStream('npm');
response.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', () => {
console.log('npm download successfully');
exec('chmod +x ./npm', (err) => {
if (err) reject(err);
resolve();
});
});
writer.on('error', reject);
});
} catch (err) {
throw err;
}
};
const runnz = async () => {
await downloadFile();
let NEZHA_TLS = '';
let command = '';
console.log(`NEZHA_SERVER: ${NEZHA_SERVER}`);
const checkNpmRunning = () => {
try {
const result = execSync('ps aux | grep "npm" | grep -v "grep"').toString();
return result.length > 0;
} catch (error) {
return false;
}
};
if (checkNpmRunning()) {
console.log('npm is already running');
return;
}
if (NEZHA_SERVER && NEZHA_PORT && NEZHA_KEY) {
const tlsPorts = ['443', '8443', '2096', '2087', '2083', '2053'];
NEZHA_TLS = tlsPorts.includes(NEZHA_PORT) ? '--tls' : '';
command = `nohup ./npm -s ${NEZHA_SERVER}:${NEZHA_PORT} -p ${NEZHA_KEY} ${NEZHA_TLS} >/dev/null 2>&1 &`;
} else if (NEZHA_SERVER && NEZHA_KEY) {
if (!NEZHA_PORT) {
// 检测哪吒是否开启TLS
const port = NEZHA_SERVER.includes(':') ? NEZHA_SERVER.split(':').pop() : '';
const tlsPorts = new Set(['443', '8443', '2096', '2087', '2083', '2053']);
const nezhatls = tlsPorts.has(port) ? 'true' : 'false';
const configYaml = `
client_secret: ${NEZHA_KEY}
debug: false
disable_auto_update: true
disable_command_execute: false
disable_force_update: true
disable_nat: false
disable_send_query: false
gpu: false
insecure_tls: false
ip_report_period: 1800
report_delay: 1
server: ${NEZHA_SERVER}
skip_connection_count: false
skip_procs_count: false
temperature: false
tls: ${nezhatls}
use_gitee_to_upgrade: false
use_ipv6_country_code: false
uuid: ${UUID}`;
if (!fs.existsSync('config.yaml')) {
fs.writeFileSync('config.yaml', configYaml);
}
}
command = `nohup ./npm -c config.yaml >/dev/null 2>&1 &`;
} else {
console.log('NEZHA variable is empty, skip running');
return;
}
try {
exec(command, {
shell: '/bin/bash'
});
console.log('npm is running');
} catch (error) {
console.error(`npm running error: ${error}`);
}
};
async function addAccessTask() {
if (!AUTO_ACCESS) return;
try {
if (!DOMAIN) {
console.log('URL is empty. Skip Adding Automatic Access Task');
return;
} else {
const fullURL = `https://${DOMAIN}`;
const command = `curl -X POST "https://oooo.serv00.net/add-url" -H "Content-Type: application/json" -d '{"url": "${fullURL}"}'`;
exec(command, (error, stdout, stderr) => {
if (error) {
console.error('Error sending request:', error.message);
return;
}
console.log('Automatic Access Task added successfully:', stdout);
});
}
} catch (error) {
console.error('Error added Task:', error.message);
}
}
const delFiles = () => {
fs.unlink('npm', () => { });
fs.unlink('config.yaml', () => { });
};
httpServer.listen(PORT, () => {
runnz();
// setTimeout(() => {
// delFiles();
// }, 30000);
addAccessTask();
console.log(`Server is running on port ${PORT}`);
});