1、在本地运行 gost

1
2
# 20000为cloudflare 回源或穿透端口
gost -D -L "relay+ws://:20000?path=/3b451552-e776-45c5-9b98-bde3ab99bf75&bind=true"

2、在远程服务器使用nodejs运行index.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
const { spawn } = require('child_process');
const http = require('http');
const crypto = require('crypto'); // 新增加密模块用于生成随机数

// 定义要运行的 GOST 命令 27866为远程服务器本地端口,31000为穿透到本地的端口
const command1 = './gost';
const args1 = ['-L=socks5://[::1]:40000?bind=true'];
const command2 = './gost';
const args2 = ['-L=rtcp://:31000/[::1]:40000', '-F', 'relay+ws://v6.li0102.site:80?path=/12aa0e60-cf59-4378-90ac-80d510e2087f&host=v6.li0102.site'];

// 使用 spawn 来运行第一个命令
const gostProcess1 = spawn(command1, args1);

// 捕获第一个命令的标准输出并显示
gostProcess1.stdout.on('data', (data) => {
const log = data.toString().trim();
if (log && !log.includes('"level":"info"')) {
console.log(`[GOST 日志] ${log}`);
}
});

// 捕获第一个命令的标准错误并显示
gostProcess1.stderr.on('data', (data) => {
const errorLog = data.toString().trim();
if (errorLog && !errorLog.includes('"level":"info"')) {
console.error(`[GOST 错误] ${errorLog}`);
}
});

// 处理第一个命令的进程退出
gostProcess1.on('close', (code) => {
console.log(`GOST 进程已退出,退出码: ${code}`);
});

// 使用 spawn 来运行第二个命令
const gostProcess2 = spawn(command2, args2);

// 捕获第二个命令的标准输出并显示
gostProcess2.stdout.on('data', (data) => {
const log = data.toString().trim();
if (log && !log.includes('"level":"info"')) {
console.log(`[GOST 日志] ${log}`);
}
});

// 捕获第二个命令的标准错误并显示
gostProcess2.stderr.on('data', (data) => {
const errorLog = data.toString().trim();
if (errorLog && !errorLog.includes('"level":"info"')) {
console.error(`[GOST 错误] ${errorLog}`);
}
});

// 处理第二个命令的进程退出
gostProcess2.on('close', (code) => {
console.log(`GOST 进程已退出,退出码: ${code}`);
});

// #######################
// ### 新增:伪装网页生成函数
// #######################
const generateFakePage = () => {
const randomToken = crypto.randomBytes(8).toString('hex');
const beijingTime = new Date().toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' });
return `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>系统维护中 - ${randomToken}</title>
<style>
.container {
width: 60%;
margin: 100px auto;
padding: 30px;
background: #f5f5f5;
border-radius: 8px;
text-align: center;
}
.notice { color: #666; }
</style>
</head>
<body>
<div class="container">
<h2>🚧 系统维护公告</h2>
<p class="notice">${beijingTime} | 会话ID: ${randomToken}</p>
<p>为提升服务质量,我们正在进行系统升级,预计持续3小时。</p>
<hr>
<p>技术支持:<span style="color:#1890ff;">400-${Math.floor(1000 + Math.random() * 9000)}</span></p>
</div>
</body>
</html>
`;
};

// #######################
// ### 新增:启动伪装网页服务
// #######################
const webServer = http.createServer((req, res) => {
// 添加请求日志
console.log(`[Web访问] ${req.method} ${req.url} from ${req.socket.remoteAddress}`);

res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8',
'Cache-Control': 'no-store' // 禁止缓存
});
res.end(generateFakePage());
});

webServer.listen(27866, '0.0.0.0', () => {
console.log(`[伪装网站] 已在端口 27866 启动,访问 http://localhost:27866 验证`);
});

webServer.on('error', (err) => {
console.error('[Web服务异常]', err.message);
if (err.code === 'EADDRINUSE') {
console.error(`⚠️ 端口 27866 已被占用,请更换端口或停止相关进程`);
}
});

console.log('GOST 已启动,正在运行...');

3、查看端口是否穿透成功

1
netstat -ntlp |grep :31000

4、package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"name": "learning",
"version": "1.0.0",
"description": "A Node.js script to manage network connections.",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"keywords": [
"network",
"service",
"utility"
],
"author": "tgg",
"license": "MIT",
"dependencies": {},
"devDependencies": {}
}

gost socks5直连服务端代码

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


// run-gost.js
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');

const LOG_DIR = path.join(__dirname, 'logs');
if (!fs.existsSync(LOG_DIR)) fs.mkdirSync(LOG_DIR, { recursive: true });

const stdoutLog = fs.createWriteStream(path.join(LOG_DIR, 'gost.out.log'), { flags: 'a' });
const stderrLog = fs.createWriteStream(path.join(LOG_DIR, 'gost.err.log'), { flags: 'a' });

// 根据你的环境设置可执行文件路径:
// - 如果 gost 位于当前目录且有可执行权限,用 './gost'
// - 如果在 Windows,通常为 'gost.exe'
const gostBinary = process.platform === 'win32' ? 'gost.exe' : './gost';

// 组装参数(与原命令一致)
const args = [
'-D',


// '-L', 'ss://chacha20-ietf-poly1305:123456%[email protected]:2164'
// '-L', 'ss+ws://chacha20-ietf-poly1305:123456%2A@:2164?path=/ws'
'-L', 'socks5://:2164?udp=true&udpBufferSize=4096'
];

// 启动子进程
const gost = spawn(gostBinary, args, {
cwd: __dirname, // 在当前目录运行,确保 ./gost 能被找到
stdio: ['ignore', 'pipe', 'pipe'], // 我们手动处理 stdout/stderr
windowsHide: true
});

// 打印启动信息
console.log(`[${new Date().toISOString()}] Starting gost: ${gostBinary} ${args.join(' ')}`);

// 处理输出:同时写入文件与控制台
gost.stdout.on('data', (data) => {
const line = data.toString();
process.stdout.write(line);
stdoutLog.write(`[${new Date().toISOString()}] ${line}`);
});

gost.stderr.on('data', (data) => {
const line = data.toString();
process.stderr.write(line);
stderrLog.write(`[${new Date().toISOString()}] ${line}`);
});

// 退出事件
gost.on('close', (code, signal) => {
const msg = `[${new Date().toISOString()}] gost exited (code=${code}, signal=${signal})\n`;
console.log(msg);
stderrLog.write(msg);
// 根据需要,决定是否自动重启
// restartGost();
});

// 错误事件(比如二进制不存在、权限不足)
gost.on('error', (err) => {
const msg = `[${new Date().toISOString()}] Failed to start gost: ${err.stack || err}\n`;
console.error(msg);
stderrLog.write(msg);
});

// 可选:简单的自动重启逻辑
function restartGost(delayMs = 3000) {
console.log(`[${new Date().toISOString()}] Restarting gost in ${delayMs}ms...`);
setTimeout(() => {
// 这里可以封装成函数重新 spawn
// 为简洁起见,你也可以用 PM2 来管理重启,见下文
process.exit(1); // 让外部进程管理器(如 PM2)重启
}, delayMs);
}

// 优雅退出:中断时关闭文件句柄与子进程
function shutdown() {
try { gost.kill('SIGINT'); } catch {}
stdoutLog.end();
stderrLog.end();
process.exit(0);
}

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

直连客户端命令

1
./gost -L=':10080' -F='socks5://45.137.70.90:2164'    ### 10080是本地转发端口,  后面的socks5地址为服务端IP+端口