@eooce/idx 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -1339
  2. package/index.js +80 -29
  3. package/package.json +12 -9
  4. package/README.md +0 -64
package/index.js CHANGED
@@ -12,10 +12,10 @@ const { execSync } = require('child_process');
12
12
  const UPLOAD_URL = process.env.UPLOAD_URL || ''; // 订阅或节点自动上传地址,需填写部署Merge-sub项目后的首页地址,例如:https://merge.ct8.pl
13
13
  const PROJECT_URL = process.env.PROJECT_URL || ''; // 需要上传订阅或保活时需填写项目分配的url,例如:https://google.com
14
14
  const AUTO_ACCESS = process.env.AUTO_ACCESS || false; // false关闭自动保活,true开启,需同时填写PROJECT_URL变量
15
- const YT_WARPOUT = process.env.YT_WARPOUT || true; // 设置为true时强制使用warp出站访问youtube,false时自动检测是否设置warp出站
16
- const FILE_PATH = process.env.FILE_PATH || './.npm'; // sub.txt订阅文件路径
15
+ const YT_WARPOUT = process.env.YT_WARPOUT || false; // 设置为true时强制使用warp出站访问youtube,false时自动检测是否设置warp出站
16
+ const FILE_PATH = process.env.FILE_PATH || '.npm'; // sub.txt订阅文件路径
17
17
  const SUB_PATH = process.env.SUB_PATH || 'sub'; // 订阅sub路径,默认为sub,例如:https://google.com/sub
18
- const UUID = process.env.UUID || 'f8e6d3d3-dad7-427e-8a72-8ca1f03a59e2'; // 在不同的平台运行了v1哪吒请修改UUID,否则会覆盖
18
+ const UUID = process.env.UUID || '0a6568ff-ea3c-4271-9020-450560e10d63'; // 在不同的平台运行了v1哪吒请修改UUID,否则会覆盖
19
19
  const NEZHA_SERVER = process.env.NEZHA_SERVER || ''; // 哪吒面板地址,v1形式:nz.serv00.net:8008 v0形式:nz.serv00.net
20
20
  const NEZHA_PORT = process.env.NEZHA_PORT || ''; // v1哪吒请留空,v0 agent端口,当端口为{443,8443,2087,2083,2053,2096}时,自动开启tls
21
21
  const NEZHA_KEY = process.env.NEZHA_KEY || ''; // v1的NZ_CLIENT_SECRET或v0 agwnt密钥
@@ -25,10 +25,10 @@ const ARGO_PORT = process.env.ARGO_PORT || 8001; // argo固定隧道
25
25
  const TUIC_PORT = process.env.TUIC_PORT || ''; // tuic端口,支持多端口的可以填写,否则留空
26
26
  const HY2_PORT = process.env.HY2_PORT || ''; // hy2端口,支持多端口的可以填写,否则留空
27
27
  const REALITY_PORT = process.env.REALITY_PORT || ''; // reality端口,支持多端口的可以填写,否则留空
28
- const CFIP = process.env.CFIP || 'cf.877774.xyz'; // 优选域名或优选IP
28
+ const CFIP = process.env.CFIP || 'cdns.doon.eu.org'; // 优选域名或优选IP
29
29
  const CFPORT = process.env.CFPORT || 443; // 优选域名或优选IP对应端口
30
30
  const PORT = process.env.PORT || 3000; // http订阅端口
31
- const NAME = process.env.NAME || 'Idx'; // 节点名称
31
+ const NAME = process.env.NAME || ''; // 节点名称
32
32
  const CHAT_ID = process.env.CHAT_ID || ''; // Telegram chat_id 两个变量不全不推送节点到TG
33
33
  const BOT_TOKEN = process.env.BOT_TOKEN || ''; // Telegram bot_token 两个变量不全不推送节点到TG
34
34
 
@@ -44,10 +44,28 @@ if (!fs.existsSync(FILE_PATH)) {
44
44
 
45
45
  let privateKey = '';
46
46
  let publicKey = '';
47
- let npmPath = path.join(FILE_PATH, 'npm');
48
- let phpPath = path.join(FILE_PATH, 'php');
49
- let webPath = path.join(FILE_PATH, 'web');
50
- let botPath = path.join(FILE_PATH, 'bot');
47
+
48
+ // 生成随机6位字符函数
49
+ function generateRandomName() {
50
+ const chars = 'abcdefghijklmnopqrstuvwxyz';
51
+ let result = '';
52
+ for (let i = 0; i < 6; i++) {
53
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
54
+ }
55
+ return result;
56
+ }
57
+
58
+ // 生成随机名称
59
+ const npmRandomName = generateRandomName();
60
+ const webRandomName = generateRandomName();
61
+ const botRandomName = generateRandomName();
62
+ const phpRandomName = generateRandomName();
63
+
64
+ // 使用随机文件名定义路径
65
+ let npmPath = path.join(FILE_PATH, npmRandomName);
66
+ let phpPath = path.join(FILE_PATH, phpRandomName);
67
+ let webPath = path.join(FILE_PATH, webRandomName);
68
+ let botPath = path.join(FILE_PATH, botRandomName);
51
69
  let subPath = path.join(FILE_PATH, 'sub.txt');
52
70
  let listPath = path.join(FILE_PATH, 'list.txt');
53
71
  let bootLogPath = path.join(FILE_PATH, 'boot.log');
@@ -102,7 +120,7 @@ function isValidPort(port) {
102
120
  }
103
121
 
104
122
  //清理历史文件
105
- const pathsToDelete = [ 'web', 'bot', 'npm', 'boot.log', 'list.txt'];
123
+ const pathsToDelete = [ webRandomName, botRandomName, npmRandomName, 'boot.log', 'list.txt'];
106
124
  function cleanupOldFiles() {
107
125
  pathsToDelete.forEach(file => {
108
126
  const filePath = path.join(FILE_PATH, file);
@@ -196,7 +214,24 @@ async function downloadFilesAndRun() {
196
214
  return;
197
215
  }
198
216
 
199
- const downloadPromises = filesToDownload.map(fileInfo => {
217
+ // 修改文件名映射为使用随机名称
218
+ const renamedFiles = filesToDownload.map(file => {
219
+ let newFileName;
220
+ if (file.fileName === 'npm') {
221
+ newFileName = npmRandomName;
222
+ } else if (file.fileName === 'web') {
223
+ newFileName = webRandomName;
224
+ } else if (file.fileName === 'bot') {
225
+ newFileName = botRandomName;
226
+ } else if (file.fileName === 'php') {
227
+ newFileName = phpRandomName;
228
+ } else {
229
+ newFileName = file.fileName;
230
+ }
231
+ return { ...file, fileName: newFileName };
232
+ });
233
+
234
+ const downloadPromises = renamedFiles.map(fileInfo => {
200
235
  return new Promise((resolve, reject) => {
201
236
  downloadFile(fileInfo.fileName, fileInfo.fileUrl, (err, fileName) => {
202
237
  if (err) {
@@ -231,13 +266,14 @@ async function downloadFilesAndRun() {
231
266
  }
232
267
  });
233
268
  }
234
- const filesToAuthorize = NEZHA_PORT ? ['./npm', './web', './bot'] : ['./php', './web', './bot'];
269
+ // 修改授权文件列表以使用随机名称
270
+ const filesToAuthorize = NEZHA_PORT ? [npmRandomName, webRandomName, botRandomName] : [phpRandomName, webRandomName, botRandomName];
235
271
  authorizeFiles(filesToAuthorize);
236
272
 
237
273
  // 检测哪吒是否开启TLS
238
274
  const port = NEZHA_SERVER.includes(':') ? NEZHA_SERVER.split(':').pop() : '';
239
275
  const tlsPorts = new Set(['443', '8443', '2096', '2087', '2083', '2053']);
240
- const nezhatls = tlsPorts.has(port) ? 'tls' : 'false';
276
+ const nezhatls = tlsPorts.has(port) ? 'true' : 'false';
241
277
 
242
278
  //运行ne-zha
243
279
  if (NEZHA_SERVER && NEZHA_KEY) {
@@ -252,12 +288,12 @@ disable_force_update: true
252
288
  disable_nat: false
253
289
  disable_send_query: false
254
290
  gpu: false
255
- insecure_tls: false
291
+ insecure_tls: true
256
292
  ip_report_period: 1800
257
293
  report_delay: 4
258
294
  server: ${NEZHA_SERVER}
259
- skip_connection_count: false
260
- skip_procs_count: false
295
+ skip_connection_count: true
296
+ skip_procs_count: true
261
297
  temperature: false
262
298
  tls: ${nezhatls}
263
299
  use_gitee_to_upgrade: false
@@ -289,7 +325,8 @@ uuid: ${UUID}`;
289
325
 
290
326
  continueExecution();
291
327
  } else {
292
- exec(`${path.join(FILE_PATH, 'web')} generate reality-keypair`, async (err, stdout, stderr) => {
328
+ // 修改执行命令以使用随机文件名
329
+ exec(`${path.join(FILE_PATH, webRandomName)} generate reality-keypair`, async (err, stdout, stderr) => {
293
330
  if (err) {
294
331
  console.error(`Error generating reality-keypair: ${err.message}`);
295
332
  return;
@@ -647,7 +684,7 @@ eQ6OFb9LbLYL9f+sAiAffoMbi4y/0YUSlTtz7as9S8/lciBF5VCUoVIKS+vX2g==
647
684
  } else {
648
685
  NEZHA_TLS = '';
649
686
  }
650
- const command = `nohup ${path.join(FILE_PATH, 'npm')} -s ${NEZHA_SERVER}:${NEZHA_PORT} -p ${NEZHA_KEY} ${NEZHA_TLS} >/dev/null 2>&1 &`;
687
+ const command = `nohup ${path.join(FILE_PATH, npmRandomName)} -s ${NEZHA_SERVER}:${NEZHA_PORT} -p ${NEZHA_KEY} ${NEZHA_TLS} --disable-auto-update --report-delay 4 --skip-conn --skip-procs >/dev/null 2>&1 &`;
651
688
  try {
652
689
  await execPromise(command);
653
690
  console.log('npm is running');
@@ -657,7 +694,7 @@ eQ6OFb9LbLYL9f+sAiAffoMbi4y/0YUSlTtz7as9S8/lciBF5VCUoVIKS+vX2g==
657
694
  }
658
695
  } else if (NEZHA_SERVER && NEZHA_KEY) {
659
696
  // 运行 V1
660
- const command = `nohup ${FILE_PATH}/php -c "${FILE_PATH}/config.yaml" >/dev/null 2>&1 &`;
697
+ const command = `nohup ${FILE_PATH}/${phpRandomName} -c "${FILE_PATH}/config.yaml" >/dev/null 2>&1 &`;
661
698
  try {
662
699
  await exec(command);
663
700
  console.log('php is running');
@@ -670,7 +707,8 @@ eQ6OFb9LbLYL9f+sAiAffoMbi4y/0YUSlTtz7as9S8/lciBF5VCUoVIKS+vX2g==
670
707
  }
671
708
 
672
709
  // 运行sbX
673
- const command1 = `nohup ${path.join(FILE_PATH, 'web')} run -c ${path.join(FILE_PATH, 'config.json')} >/dev/null 2>&1 &`;
710
+ // 修改执行命令以使用随机文件名
711
+ const command1 = `nohup ${path.join(FILE_PATH, webRandomName)} run -c ${path.join(FILE_PATH, 'config.json')} >/dev/null 2>&1 &`;
674
712
  try {
675
713
  await execPromise(command1);
676
714
  console.log('web is running');
@@ -680,7 +718,8 @@ eQ6OFb9LbLYL9f+sAiAffoMbi4y/0YUSlTtz7as9S8/lciBF5VCUoVIKS+vX2g==
680
718
  }
681
719
 
682
720
  // 运行cloud-fared
683
- if (fs.existsSync(path.join(FILE_PATH, 'bot'))) {
721
+ // 修改检查和执行命令以使用随机文件名
722
+ if (fs.existsSync(path.join(FILE_PATH, botRandomName))) {
684
723
  let args;
685
724
 
686
725
  if (ARGO_AUTH.match(/^[A-Z0-9a-z=]{120,250}$/)) {
@@ -692,7 +731,7 @@ eQ6OFb9LbLYL9f+sAiAffoMbi4y/0YUSlTtz7as9S8/lciBF5VCUoVIKS+vX2g==
692
731
  }
693
732
 
694
733
  try {
695
- await execPromise(`nohup ${path.join(FILE_PATH, 'bot')} ${args} >/dev/null 2>&1 &`);
734
+ await execPromise(`nohup ${path.join(FILE_PATH, botRandomName)} ${args} >/dev/null 2>&1 &`);
696
735
  console.log('bot is running');
697
736
  await new Promise((resolve) => setTimeout(resolve, 2000));
698
737
  } catch (error) {
@@ -789,7 +828,7 @@ async function extractDomains() {
789
828
  fs.unlinkSync(path.join(FILE_PATH, 'boot.log'));
790
829
  async function killBotProcess() {
791
830
  try {
792
- await exec('pkill -f "[b]ot" > /dev/null 2>&1');
831
+ await exec(`pkill -f "${botRandomName}" > /dev/null 2>&1`);
793
832
  } catch (error) {
794
833
  return null;
795
834
  // 忽略输出
@@ -799,7 +838,7 @@ async function extractDomains() {
799
838
  await new Promise((resolve) => setTimeout(resolve, 1000));
800
839
  const args = `tunnel --edge-ip-version auto --no-autoupdate --protocol http2 --logfile ${FILE_PATH}/boot.log --loglevel info --url http://localhost:${ARGO_PORT}`;
801
840
  try {
802
- await exec(`nohup ${path.join(FILE_PATH, 'bot')} ${args} >/dev/null 2>&1 &`);
841
+ await exec(`nohup ${path.join(FILE_PATH, botRandomName)} ${args} >/dev/null 2>&1 &`);
803
842
  console.log('bot is running.');
804
843
  await new Promise((resolve) => setTimeout(resolve, 6000)); // 等待6秒
805
844
  await extractDomains(); // 重新提取域名
@@ -832,27 +871,29 @@ async function extractDomains() {
832
871
  );
833
872
  const ISP = metaInfo.trim();
834
873
 
874
+ const nodeName = NAME ? `${NAME}-${ISP}` : ISP;
875
+
835
876
  return new Promise((resolve) => {
836
877
  setTimeout(() => {
837
- const vmessNode = `vmess://${Buffer.from(JSON.stringify({ v: '2', ps: `${NAME}-${ISP}`, add: CFIP, port: CFPORT, id: UUID, aid: '0', scy: 'none', net: 'ws', type: 'none', host: argoDomain, path: '/vmess-argo?ed=2560', tls: 'tls', sni: argoDomain, alpn: '', fp: 'chrome'})).toString('base64')}`;
878
+ const vmessNode = `vmess://${Buffer.from(JSON.stringify({ v: '2', ps: `${nodeName}`, add: CFIP, port: CFPORT, id: UUID, aid: '0', scy: 'none', net: 'ws', type: 'none', host: argoDomain, path: '/vmess-argo?ed=2560', tls: 'tls', sni: argoDomain, alpn: '', fp: 'firefox'})).toString('base64')}`;
838
879
 
839
880
  let subTxt = vmessNode; // 始终生成vmess节点
840
881
 
841
882
  // TUIC_PORT是有效端口号时生成tuic节点
842
883
  if (isValidPort(TUIC_PORT)) {
843
- const tuicNode = `\ntuic://${UUID}:@${SERVER_IP}:${TUIC_PORT}?sni=www.bing.com&congestion_control=bbr&udp_relay_mode=native&alpn=h3&allow_insecure=1#${NAME}-${ISP}`;
884
+ const tuicNode = `\ntuic://${UUID}:@${SERVER_IP}:${TUIC_PORT}?sni=www.bing.com&congestion_control=bbr&udp_relay_mode=native&alpn=h3&allow_insecure=1#${nodeName}`;
844
885
  subTxt += tuicNode;
845
886
  }
846
887
 
847
888
  // HY2_PORT是有效端口号时生成hysteria2节点
848
889
  if (isValidPort(HY2_PORT)) {
849
- const hysteriaNode = `\nhysteria2://${UUID}@${SERVER_IP}:${HY2_PORT}/?sni=www.bing.com&insecure=1&alpn=h3&obfs=none#${NAME}-${ISP}`;
890
+ const hysteriaNode = `\nhysteria2://${UUID}@${SERVER_IP}:${HY2_PORT}/?sni=www.bing.com&insecure=1&alpn=h3&obfs=none#${nodeName}`;
850
891
  subTxt += hysteriaNode;
851
892
  }
852
893
 
853
894
  // REALITY_PORT是有效端口号时生成reality节点
854
895
  if (isValidPort(REALITY_PORT)) {
855
- const vlessNode = `\nvless://${UUID}@${SERVER_IP}:${REALITY_PORT}?encryption=none&flow=xtls-rprx-vision&security=reality&sni=www.iij.ad.jp&fp=chrome&pbk=${publicKey}&type=tcp&headerType=none#${NAME}-${ISP}`;
896
+ const vlessNode = `\nvless://${UUID}@${SERVER_IP}:${REALITY_PORT}?encryption=none&flow=xtls-rprx-vision&security=reality&sni=www.iij.ad.jp&fp=firefox&pbk=${publicKey}&type=tcp&headerType=none#${nodeName}`;
856
897
  subTxt += vlessNode;
857
898
  }
858
899
 
@@ -885,7 +926,17 @@ function cleanFiles() {
885
926
  filesToDelete.push(phpPath);
886
927
  }
887
928
 
888
- exec(`rm -rf ${filesToDelete.join(' ')} >/dev/null 2>&1`, (error) => {
929
+ // 修改为使用随机文件名删除文件
930
+ const filePathsToDelete = filesToDelete.map(file => {
931
+ // 对于已经使用随机路径的变量,直接使用
932
+ if ([webPath, botPath, phpPath, npmPath].includes(file)) {
933
+ return file;
934
+ }
935
+ // 对于其他文件,使用原始路径
936
+ return path.join(FILE_PATH, path.basename(file));
937
+ });
938
+
939
+ exec(`rm -rf ${filePathsToDelete.join(' ')} >/dev/null 2>&1`, (error) => {
889
940
  console.clear();
890
941
  console.log('App is running');
891
942
  console.log('Thank you for using this script, enjoy!');
package/package.json CHANGED
@@ -1,17 +1,20 @@
1
1
  {
2
2
  "name": "@eooce/idx",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "@eooce/idx",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "@eooce/idx": "./index.js"
8
8
  },
9
9
  "keywords": [
10
+ "vmess",
11
+ "vless",
12
+ "hysteria2",
13
+ "tuic",
14
+ "reality",
15
+ "argo",
10
16
  "tunnel",
11
- "nezha",
12
- "deployment",
13
- "paas",
14
- "vps"
17
+ "nezha"
15
18
  ],
16
19
  "author": "eooce",
17
20
  "repository": {
@@ -22,7 +25,7 @@
22
25
  "url": "https://github.com/eooce/Sing-box/issues"
23
26
  },
24
27
  "homepage": "https://github.com/eooce/Sing-box#readme",
25
- "license": "AGPL-3.0-only",
28
+ "license": "MIT",
26
29
  "private": false,
27
30
  "scripts": {
28
31
  "start": "node index.js",
@@ -30,9 +33,9 @@
30
33
  "test": "echo \"Error: no test specified\" && exit 1"
31
34
  },
32
35
  "dependencies": {
33
- "axios": "latest",
34
- "express": "latest",
35
- "dotenv": "latest"
36
+ "axios": "^1.12.2",
37
+ "express": "^5.1.0",
38
+ "dotenv": "^17.2.3"
36
39
  },
37
40
  "engines": {
38
41
  "node": ">=14"
package/README.md DELETED
@@ -1,64 +0,0 @@
1
- # @eooce/idx
2
-
3
- A lightweight Node.js project for executing backend services or network requests tasks with support for HTTP requests, environment variable management, and basic web services.
4
-
5
- ## Features
6
-
7
- - Start local Node.js service (via express)
8
- - Send HTTP requests (via axios)
9
- - Load environment configuration files (via dotenv)
10
- - Support for Node.js 14 and above
11
- - Quick start with `npm start`
12
-
13
- ## Installation
14
-
15
- ```bash
16
- npm install @eooce/idx
17
- ```
18
-
19
- ## Usage
20
-
21
- ```javascript
22
- // Require the package
23
- const idx = require('@eooce/idx');
24
-
25
- // Start the service
26
- idx.start();
27
- ```
28
-
29
- Or run directly from the command line:
30
-
31
- ```bash
32
- npx @eooce/idx
33
- ```
34
-
35
- ## Environment Variables
36
-
37
- The following environment variables can be configured:
38
-
39
- - `UPLOAD_URL`: Subscription or node auto-upload address
40
- - `PROJECT_URL`: Project assigned URL for subscription upload or keep-alive
41
- - `AUTO_ACCESS`: false to disable auto keep-alive, true to enable
42
- - `YT_WARPOUT`: true to force WARP outbound for YouTube, false for auto-detection
43
- - `FILE_PATH`: Subscription file path (default: './.npm')
44
- - `SUB_PATH`: Subscription path (default: 'sub')
45
- - `UUID`: UUID for different platform operation (default: 'f8e6d3d3-dad7-427e-8a72-8ca1f03a59e2')
46
- - `NEZHA_SERVER`: Nezha panel address
47
- - `NEZHA_PORT`: Nezha agent port
48
- - `NEZHA_KEY`: Nezha client secret or agent key
49
- - `ARGO_DOMAIN`: Argo tunnel domain
50
- - `ARGO_AUTH`: Argo tunnel token or JSON
51
- - `ARGO_PORT`: Argo tunnel port (default: 8001)
52
- - `TUIC_PORT`: TUIC port
53
- - `HY2_PORT`: Hysteria2 port
54
- - `REALITY_PORT`: Reality port
55
- - `CFIP`: Preferred domain or IP (default: 'cf.877774.xyz')
56
- - `CFPORT`: Preferred domain or IP port (default: 443)
57
- - `PORT`: HTTP subscription port (default: 3000)
58
- - `NAME`: Node name (default: 'Idx')
59
- - `CHAT_ID`: Telegram chat_id
60
- - `BOT_TOKEN`: Telegram bot_token
61
-
62
- ## License
63
-
64
- AGPL-3.0-only