1.

1
nano hy2.js

2.

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
#!/usr/bin/env node
/**
* Hysteria2 一键部署脚本 – Pterodactyl 完美运行版
* 支持 amd64 + arm64,永别 EACCES,零语法错误
*/

const { execSync, spawn } = require('child_process');
const fs = require('fs');
const https = require('https');
const path = require('path');

// ==================== 配置区 ====================
const HYSTERIA_VERSION = 'v2.6.5';
const DEFAULT_PORT = 25937;
const AUTH_PASSWORD = 'abcuser2025'; // 务必改成自己的密码!
const SNI = 'www.bing.com';
const ALPN = 'h3';
// ===============================================

const SERVER_PORT = process.argv[2] || DEFAULT_PORT;
console.log(`\nHysteria2 将监听端口: ${SERVER_PORT}\n`);

// ---------- 架构检测 ----------
function getArch() {
const arch = process.arch;
if (arch === 'arm64') return 'arm64';
if (arch === 'x64') return 'amd64';
return '';
}
const ARCH = getArch();
if (!ARCH) {
console.error('无法识别 CPU 架构:', process.arch);
process.exit(1);
}

const BIN_NAME = `hysteria-linux-${ARCH}`;
const BIN_PATH = path.join(__dirname, BIN_NAME);

// ---------- 检查 openssl ----------
function checkOpenSSL() {
try {
execSync('openssl version', { stdio: 'ignore' });
} catch {
console.error('未检测到 openssl,请执行:apt update && apt install openssl -y');
process.exit(1);
}
}

// ---------- 下载二进制 ----------
async function downloadBinary() {
if (fs.existsSync(BIN_PATH)) {
console.log('二进制已存在,跳过下载');
fs.chmodSync(BIN_PATH, 0o755);
return;
}

const url = `https://gh.nxnow.top/https://github.com/apernet/hysteria/releases/download/app/${HYSTERIA_VERSION}/hysteria-linux-${ARCH}`;
console.log(`正在下载 ${ARCH} 版本: ${url}`);

await new Promise((resolve, reject) => {
const file = fs.createWriteStream(BIN_PATH);
https.get(url, { timeout: 30000 }, res => {
if (res.statusCode === 404) {
return reject(new Error(`未找到 ${ARCH} 版本,请检查 Hysteria 是否已发布该架构`));
}
if (res.statusCode !== 200) {
return reject(new Error(`下载失败,状态码: ${res.statusCode}`));
}

res.pipe(file);
file.on('finish', () => {
file.close();
fs.chmodSync(BIN_PATH, 0o755);
console.log('下载完成,已添加执行权限');
resolve();
});
}).on('error', err => {
if (fs.existsSync(BIN_PATH)) fs.unlinkSync(BIN_PATH);
reject(err);
});
});
}

// ---------- 生成证书 ----------
function ensureCert() {
if (fs.existsSync('cert.pem') && fs.existsSync('key.pem')) {
console.log('已有证书,跳过生成');
return;
}
console.log('正在生成自签证书(10年)...');
execSync(`openssl req -x509 -nodes -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -days 3650 -keyout key.pem -out cert.pem -subj "/CN=${SNI}"`);
console.log('证书生成成功');
}

// ---------- 写配置 ----------
function writeConfig() {
const config = `
listen: ":${SERVER_PORT}"

tls:
cert: ${path.resolve('cert.pem')}
key: ${path.resolve('key.pem')}

auth:
type: password
password: "${AUTH_PASSWORD}"

alpn:
- "${ALPN}"

bandwidth:
up: 200 mbps
down: 200 mbps

quic:
initStreamReceiveWindow: 8388608
maxStreamReceiveWindow: 8388608
initConnReceiveWindow: 20971520
maxConnReceiveWindow: 20971520
maxIdleTimeout: 30s

masquerade:
type: proxy
proxy:
url: https://news.ycombinator.com/
rewriteHost: true
`.trim();

fs.writeFileSync('server.yaml', config);
console.log('server.yaml 已写入');
}

// ---------- 获取公网IP ----------
async function getIP() {
return new Promise(resolve => {
https.get('https://api.ipify.org', res => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(data.trim() || 'YOUR_IP'));
}).on('error', () => resolve('YOUR_IP'));
});
}

// ---------- 主流程 ----------
(async () => {
console.log('开始部署 Hysteria2...\n');

checkOpenSSL();
await downloadBinary();
ensureCert();
writeConfig();

const ip = await getIP();

console.log('\n部署成功!节点信息:\n');
console.log('════════════════════════════════════');
console.log(`IP : ${ip}`);
console.log(`端口 : ${SERVER_PORT}`);
console.log(`密码 : ${AUTH_PASSWORD}`);
console.log(`SNI : ${SNI}`);
console.log(`链接 : hysteria2://${AUTH_PASSWORD}@${ip}:${SERVER_PORT}/?sni=${SNI}&alpn=${ALPN}&insecure=1#Hy2-weirdhost`);
console.log('════════════════════════════════════\n');

// 最后再加一次权限
fs.chmodSync(BIN_PATH, 0o755);

console.log('启动 Hysteria2 服务端...\n');
spawn(BIN_PATH, ['server', '-c', 'server.yaml'], { stdio: 'inherit' });

// 防止 Node 退出
process.on('SIGINT', () => process.exit());
process.on('SIGTERM', () => process.exit());
})();

3.package.json

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"name": "hy2-deploy",
"version": "1.0.0",
"description": "Hy2 极简部署脚本(Node.js 版)",
"main": "hy2.js",
"scripts": {
"start": "node hy2.js"
},
"author": "",
"license": "MIT",
"dependencies": {}
}