@eooce/xhttp
Version:
A serverless xhttp server
965 lines (852 loc) • 31.1 kB
JavaScript
require('dotenv').config();
const os = require('os');
const fs = require('fs');
const net = require('net');
const http = require('http');
const axios = require('axios');
const { Buffer } = require('buffer');
const { exec, execSync } = require('child_process');
// 环境变量
const UUID = process.env.UUID || 'a2056d0d-c98e-4aeb-9aab-37f64edd5710'; // 使用哪吒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 AUTO_ACCESS = process.env.AUTO_ACCESS || false; // 是否开启自动访问保活,false为关闭,true为开启,需同时填写DOMAIN变量
const XPATH = process.env.XPATH || UUID.slice(0, 8); // xhttp路径,自动获取uuid前8位
const SUB_PATH = process.env.SUB_PATH || 'sub'; // 节点订阅路径
const DOMAIN = process.env.DOMAIN || ''; // 域名或ip,留空将自动获取服务器ip
const NAME = process.env.NAME || 'Vls'; // 节点名称
const PORT = process.env.PORT || 3000; // http服务
// 核心配置
const SETTINGS = {
['UUID']: UUID,
['LOG_LEVEL']: 'none', // 日志级别,调试使用,none,info,warn,error
['BUFFER_SIZE']: '2048', // 增加缓冲区大小
['XPATH']: `%2F${XPATH}`, // xhttp路径
['MAX_BUFFERED_POSTS']: 30, // 最大缓存POST请求数
['MAX_POST_SIZE']: 1000000, // 每个POST最大字节数(1MB)
['SESSION_TIMEOUT']: 30000, // 会话超时时间(30秒)
['CHUNK_SIZE']: 1024 * 1024, // 1024KB 的数据块大小
['TCP_NODELAY']: true, // 启用 TCP_NODELAY
['TCP_KEEPALIVE']: true, // 启用 TCP keepalive
}
function validate_uuid(left, right) {
for (let i = 0; i < 16; i++) {
if (left[i] !== right[i]) return false
}
return true
}
function concat_typed_arrays(first, ...args) {
if (!args || args.length < 1) return first
let len = first.length
for (let a of args) len += a.length
const r = new first.constructor(len)
r.set(first, 0)
len = first.length
for (let a of args) {
r.set(a, len)
len += a.length
}
return r
}
// 扩展日志函数
function log(type, ...args) {
if (SETTINGS.LOG_LEVEL === 'none') return;
const levels = {
'debug': 0,
'info': 1,
'warn': 2,
'error': 3
};
const colors = {
'debug': '\x1b[36m', // 青色
'info': '\x1b[32m', // 绿色
'warn': '\x1b[33m', // 黄色
'error': '\x1b[31m', // 红色
'reset': '\x1b[0m' // 重置
};
const configLevel = levels[SETTINGS.LOG_LEVEL] || 1;
const messageLevel = levels[type] || 0;
if (messageLevel >= configLevel) {
const time = new Date().toISOString();
const color = colors[type] || colors.reset;
console.log(`${color}[${time}] [${type}]`, ...args, colors.reset);
}
}
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 () => {
if (!NEZHA_KEY) return;
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 = '';
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) {
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}`;
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 !== true) return;
try {
if (!DOMAIN) return;
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);
}
}
// VLESS 协议解析
function parse_uuid(uuid) {
uuid = uuid.replaceAll('-', '')
const r = []
for (let index = 0; index < 16; index++) {
r.push(parseInt(uuid.substr(index * 2, 2), 16))
}
return r
}
async function read_vless_header(reader, cfg_uuid_str) {
let readed_len = 0
let header = new Uint8Array()
let read_result = { value: header, done: false }
async function inner_read_until(offset) {
if (read_result.done) {
throw new Error('header length too short')
}
const len = offset - readed_len
if (len < 1) {
return
}
read_result = await read_atleast(reader, len)
readed_len += read_result.value.length
header = concat_typed_arrays(header, read_result.value)
}
await inner_read_until(1 + 16 + 1)
const version = header[0]
const uuid = header.slice(1, 1 + 16)
const cfg_uuid = parse_uuid(cfg_uuid_str)
if (!validate_uuid(uuid, cfg_uuid)) {
throw new Error(`invalid UUID`)
}
const pb_len = header[1 + 16]
const addr_plus1 = 1 + 16 + 1 + pb_len + 1 + 2 + 1
await inner_read_until(addr_plus1 + 1)
const cmd = header[1 + 16 + 1 + pb_len]
const COMMAND_TYPE_TCP = 1
if (cmd !== COMMAND_TYPE_TCP) {
throw new Error(`unsupported command: ${cmd}`)
}
const port = (header[addr_plus1 - 1 - 2] << 8) + header[addr_plus1 - 1 - 1]
const atype = header[addr_plus1 - 1]
const ADDRESS_TYPE_IPV4 = 1
const ADDRESS_TYPE_STRING = 2
const ADDRESS_TYPE_IPV6 = 3
let header_len = -1
if (atype === ADDRESS_TYPE_IPV4) {
header_len = addr_plus1 + 4
} else if (atype === ADDRESS_TYPE_IPV6) {
header_len = addr_plus1 + 16
} else if (atype === ADDRESS_TYPE_STRING) {
header_len = addr_plus1 + 1 + header[addr_plus1]
}
if (header_len < 0) {
throw new Error('read address type failed')
}
await inner_read_until(header_len)
const idx = addr_plus1
let hostname = ''
if (atype === ADDRESS_TYPE_IPV4) {
hostname = header.slice(idx, idx + 4).join('.')
} else if (atype === ADDRESS_TYPE_STRING) {
hostname = new TextDecoder().decode(
header.slice(idx + 1, idx + 1 + header[idx]),
)
} else if (atype === ADDRESS_TYPE_IPV6) {
hostname = header
.slice(idx, idx + 16)
.reduce(
(s, b2, i2, a) =>
i2 % 2 ? s.concat(((a[i2 - 1] << 8) + b2).toString(16)) : s,
[],
)
.join(':')
}
if (!hostname) {
log('error', 'Failed to parse hostname');
throw new Error('parse hostname failed')
}
log('info', `VLESS connection to ${hostname}:${port}`);
return {
hostname,
port,
data: header.slice(header_len),
resp: new Uint8Array([version, 0]),
}
}
// read_atleast 函数
async function read_atleast(reader, n) {
const buffs = []
let done = false
while (n > 0 && !done) {
const r = await reader.read()
if (r.value) {
const b = new Uint8Array(r.value)
buffs.push(b)
n -= b.length
}
done = r.done
}
if (n > 0) {
throw new Error(`not enough data to read`)
}
return {
value: concat_typed_arrays(...buffs),
done,
}
}
// parse_header 函数
async function parse_header(uuid_str, client) {
log('debug', 'Starting to parse VLESS header');
const reader = client.readable.getReader()
try {
const vless = await read_vless_header(reader, uuid_str)
log('debug', 'VLESS header parsed successfully');
return vless
} catch (err) {
log('error', `VLESS header parse error: ${err.message}`);
throw new Error(`read vless header error: ${err.message}`)
} finally {
reader.releaseLock()
}
}
// connect_remote 函数
async function connect_remote(hostname, port) {
const timeout = 8000;
try {
const conn = await timed_connect(hostname, port, timeout);
// 优化 TCP 连接
conn.setNoDelay(true); // 启用 TCP_NODELAY
conn.setKeepAlive(true, 1000); // 启用 TCP keepalive
// 设置缓冲区大小
conn.bufferSize = parseInt(SETTINGS.BUFFER_SIZE) * 1024;
log('info', `Connected to ${hostname}:${port}`);
return conn;
} catch (err) {
log('error', `Connection failed: ${err.message}`);
throw err;
}
}
// timed_connect 函数
function timed_connect(hostname, port, ms) {
return new Promise((resolve, reject) => {
const conn = net.createConnection({ host: hostname, port: port })
const handle = setTimeout(() => {
reject(new Error(`connect timeout`))
}, ms)
conn.on('connect', () => {
clearTimeout(handle)
resolve(conn)
})
conn.on('error', (err) => {
clearTimeout(handle)
reject(err)
})
})
}
// 网络传输
function pipe_relay() {
async function pump(src, dest, first_packet) {
const chunkSize = parseInt(SETTINGS.CHUNK_SIZE);
if (first_packet.length > 0) {
if (dest.write) {
dest.cork(); // 合并多个小数据包
dest.write(first_packet);
process.nextTick(() => dest.uncork());
} else {
const writer = dest.writable.getWriter();
try {
await writer.write(first_packet);
} finally {
writer.releaseLock();
}
}
}
try {
if (src.pipe) {
// 优化 Node.js Stream
src.pause();
src.pipe(dest, {
end: true,
highWaterMark: chunkSize
});
src.resume();
} else {
// 优化 Web Stream
await src.readable.pipeTo(dest.writable, {
preventClose: false,
preventAbort: false,
preventCancel: false,
signal: AbortSignal.timeout(SETTINGS.SESSION_TIMEOUT)
});
}
} catch (err) {
if (!err.message.includes('aborted')) {
log('error', 'Relay error:', err.message);
}
throw err;
}
}
return pump;
}
// socketToWebStream 函数
function socketToWebStream(socket) {
let readController;
let writeController;
socket.on('error', (err) => {
log('error', 'Socket error:', err.message);
readController?.error(err);
writeController?.error(err);
});
return {
readable: new ReadableStream({
start(controller) {
readController = controller;
socket.on('data', (chunk) => {
try {
controller.enqueue(chunk);
} catch (err) {
log('error', 'Read controller error:', err.message);
}
});
socket.on('end', () => {
try {
controller.close();
} catch (err) {
log('error', 'Read controller close error:', err.message);
}
});
},
cancel() {
socket.destroy();
}
}),
writable: new WritableStream({
start(controller) {
writeController = controller;
},
write(chunk) {
return new Promise((resolve, reject) => {
if (socket.destroyed) {
reject(new Error('Socket is destroyed'));
return;
}
socket.write(chunk, (err) => {
if (err) reject(err);
else resolve();
});
});
},
close() {
if (!socket.destroyed) {
socket.end();
}
},
abort(err) {
socket.destroy(err);
}
})
};
}
// relay 函数
function relay(cfg, client, remote, vless) {
const pump = pipe_relay();
let isClosing = false;
const remoteStream = socketToWebStream(remote);
function cleanup() {
if (!isClosing) {
isClosing = true;
try {
remote.destroy();
} catch (err) {
// 忽略常规断开错误
if (!err.message.includes('aborted') &&
!err.message.includes('socket hang up')) {
log('error', `Cleanup error: ${err.message}`);
}
}
}
}
const uploader = pump(client, remoteStream, vless.data)
.catch(err => {
// 只记录非预期错误
if (!err.message.includes('aborted') &&
!err.message.includes('socket hang up')) {
log('error', `Upload error: ${err.message}`);
}
})
.finally(() => {
client.reading_done && client.reading_done();
});
const downloader = pump(remoteStream, client, vless.resp)
.catch(err => {
// 只记录非预期错误
if (!err.message.includes('aborted') &&
!err.message.includes('socket hang up')) {
log('error', `Download error: ${err.message}`);
}
});
downloader
.finally(() => uploader)
.finally(cleanup);
}
// 会话管理
const sessions = new Map();
class Session {
constructor(uuid) {
this.uuid = uuid;
this.nextSeq = 0;
this.downstreamStarted = false;
this.lastActivity = Date.now();
this.vlessHeader = null;
this.remote = null;
this.initialized = false;
this.responseHeader = null;
this.headerSent = false;
this.bufferedData = new Map();
this.cleaned = false;
this.pendingPackets = []; // 存储待处理的数据包
this.currentStreamRes = null; // 当前下行流响应
this.pendingBuffers = new Map(); // 存储未按序到达的数据包
log('debug', `Created new session with UUID: ${uuid}`);
}
async initializeVLESS(firstPacket) {
if (this.initialized) return true;
try {
log('debug', 'Initializing VLESS connection from first packet');
// 创建可读流来解析VLESS头
const readable = new ReadableStream({
start(controller) {
controller.enqueue(firstPacket);
controller.close();
}
});
const client = {
readable: readable,
writable: new WritableStream()
};
this.vlessHeader = await parse_header(SETTINGS.UUID, client);
log('info', `VLESS header parsed: ${this.vlessHeader.hostname}:${this.vlessHeader.port}`);
// 建立远程连接
this.remote = await connect_remote(this.vlessHeader.hostname, this.vlessHeader.port);
log('info', 'Remote connection established');
this.initialized = true;
return true;
} catch (err) {
log('error', `Failed to initialize VLESS: ${err.message}`);
return false;
}
}
async processPacket(seq, data) {
try {
// 保存数据到pendingBuffers
this.pendingBuffers.set(seq, data);
log('debug', `Buffered packet seq=${seq}, size=${data.length}`);
// 按序处理数据包
while (this.pendingBuffers.has(this.nextSeq)) {
const nextData = this.pendingBuffers.get(this.nextSeq);
this.pendingBuffers.delete(this.nextSeq);
// 只有第一个包需要初始化VLESS
if (!this.initialized && this.nextSeq === 0) {
if (!await this.initializeVLESS(nextData)) {
throw new Error('Failed to initialize VLESS connection');
}
// 存储响应头
this.responseHeader = Buffer.from(this.vlessHeader.resp);
// 写入VLESS头部数据到远程
await this._writeToRemote(this.vlessHeader.data);
// 如果有待处理的下游连接,立即发送响应
if (this.currentStreamRes) {
this._startDownstreamResponse();
}
} else {
// 后续数据包直接发送
if (!this.initialized) {
log('warn', `Received out of order packet seq=${seq} before initialization`);
continue;
}
await this._writeToRemote(nextData);
}
this.nextSeq++;
log('debug', `Processed packet seq=${this.nextSeq-1}`);
}
// 检查缓存大小
if (this.pendingBuffers.size > SETTINGS.MAX_BUFFERED_POSTS) {
throw new Error('Too many buffered packets');
}
return true;
} catch (err) {
log('error', `Process packet error: ${err.message}`);
throw err;
}
}
_startDownstreamResponse() {
if (!this.currentStreamRes || !this.responseHeader) return;
try {
const protocol = this.currentStreamRes.socket?.alpnProtocol || 'http/1.1';
const isH2 = protocol === 'h2';
if (!this.headerSent) {
log('debug', `Sending VLESS response header (${protocol}): ${this.responseHeader.length} bytes`);
this.currentStreamRes.write(this.responseHeader);
this.headerSent = true;
}
// 根据协议使用不同的传输策略
if (isH2) {
// HTTP/2 优化
this.currentStreamRes.socket.setNoDelay(true);
// 使用 Transform 流进行数据分块
const transform = new require('stream').Transform({
transform(chunk, encoding, callback) {
const size = 16384; // 16KB chunks
for (let i = 0; i < chunk.length; i += size) {
this.push(chunk.slice(i, i + size));
}
callback();
}
});
this.remote.pipe(transform).pipe(this.currentStreamRes);
} else {
// HTTP/1.1 直接传输
this.remote.pipe(this.currentStreamRes);
}
// 处理关闭事件
this.remote.on('end', () => {
if (!this.currentStreamRes.writableEnded) {
this.currentStreamRes.end();
}
});
this.remote.on('error', (err) => {
log('error', `Remote error: ${err.message}`);
if (!this.currentStreamRes.writableEnded) {
this.currentStreamRes.end();
}
});
} catch (err) {
log('error', `Error starting downstream: ${err.message}`);
this.cleanup();
}
}
startDownstream(res, headers) {
if (!res.headersSent) {
res.writeHead(200, headers);
}
this.currentStreamRes = res;
if (this.initialized && this.responseHeader) {
this._startDownstreamResponse();
}
res.on('close', () => {
log('info', 'Client connection closed');
this.cleanup();
});
return true;
}
async _writeToRemote(data) {
if (!this.remote || this.remote.destroyed) {
throw new Error('Remote connection not available');
}
return new Promise((resolve, reject) => {
this.remote.write(data, (err) => {
if (err) {
log('error', `Failed to write to remote: ${err.message}`);
reject(err);
} else {
resolve();
}
});
});
}
_startDownstreamResponse() {
if (!this.currentStreamRes || !this.responseHeader) return;
try {
if (!this.headerSent) {
this.currentStreamRes.write(this.responseHeader);
this.headerSent = true;
}
this.remote.pipe(this.currentStreamRes);
this.remote.on('end', () => {
if (!this.currentStreamRes.writableEnded) {
this.currentStreamRes.end();
}
});
this.remote.on('error', (err) => {
log('error', `Remote error: ${err.message}`);
if (!this.currentStreamRes.writableEnded) {
this.currentStreamRes.end();
}
});
} catch (err) {
log('error', `Error starting downstream: ${err.message}`);
this.cleanup();
}
}
cleanup() {
if (!this.cleaned) {
this.cleaned = true;
log('debug', `Cleaning up session ${this.uuid}`);
if (this.remote) {
this.remote.destroy();
this.remote = null;
}
this.initialized = false;
this.headerSent = false;
}
}
}
// 获取ISP信息
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();
let IP = DOMAIN;
if (!DOMAIN) {
try {
// 首先尝试获取 IPv4
IP = execSync('curl -s --max-time 2 ipv4.ip.sb', { encoding: 'utf-8' }).trim();
} catch (err) {
try {
IP = `[${execSync('curl -s --max-time 1 ipv6.ip.sb', { encoding: 'utf-8' }).trim()}]`;
} catch (ipv6Err) {
log('error', 'Failed to get IP address:', ipv6Err.message);
IP = 'localhost';
}
}
}
// 创建http服务
const server = http.createServer((req, res) => {
const headers = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST',
'Cache-Control': 'no-store',
'X-Accel-Buffering': 'no',
'X-Padding': generatePadding(100, 1000),
};
// 根路径和订阅路径
if (req.url === '/') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World\n');
return;
}
if (req.url === `/${SUB_PATH}`) {
const vlessURL = `vless://${UUID}@${IP}:443?encryption=none&security=tls&sni=${IP}&fp=chrome&allowInsecure=1&type=xhttp&host=${IP}&path=${SETTINGS.XPATH}&mode=packet-up#${NAME}-${ISP}`;
const base64Content = Buffer.from(vlessURL).toString('base64');
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(base64Content + '\n');
return;
}
// VLESS 请求处理
const pathMatch = req.url.match(new RegExp(`${XPATH}/([^/]+)(?:/([0-9]+))?$`));
if (!pathMatch) {
res.writeHead(404);
res.end();
return;
}
const uuid = pathMatch[1];
const seq = pathMatch[2] ? parseInt(pathMatch[2]) : null;
if (req.method === 'GET' && !seq) {
headers['Content-Type'] = 'application/octet-stream';
headers['Transfer-Encoding'] = 'chunked';
let session = sessions.get(uuid);
if (!session) {
session = new Session(uuid);
sessions.set(uuid, session);
log('info', `Created new session for GET: ${uuid}`);
}
session.downstreamStarted = true;
if (!session.startDownstream(res, headers)) {
log('error', `Failed to start downstream for session: ${uuid}`);
if (!res.headersSent) {
res.writeHead(500);
res.end();
}
session.cleanup();
sessions.delete(uuid);
}
return;
}
// 处理上行流
if (req.method === 'POST' && seq !== null) {
let session = sessions.get(uuid);
if (!session) {
session = new Session(uuid);
sessions.set(uuid, session);
log('info', `Created new session for POST: ${uuid}`);
setTimeout(() => {
const currentSession = sessions.get(uuid);
if (currentSession && !currentSession.downstreamStarted) {
log('warn', `Session ${uuid} timed out without downstream`);
currentSession.cleanup();
sessions.delete(uuid);
}
}, SETTINGS.SESSION_TIMEOUT);
}
let data = [];
let size = 0;
let headersSent = false; // 添加标志位
req.on('data', chunk => {
size += chunk.length;
if (size > SETTINGS.MAX_POST_SIZE) {
if (!headersSent) {
res.writeHead(413);
res.end();
headersSent = true;
}
return;
}
data.push(chunk);
});
req.on('end', async () => {
if (headersSent) return; // 如果已经发送过响应头就直接返回
try {
const buffer = Buffer.concat(data);
log('info', `Processing packet: seq=${seq}, size=${buffer.length}`);
await session.processPacket(seq, buffer);
if (!headersSent) {
res.writeHead(200, headers);
headersSent = true;
}
res.end();
} catch (err) {
log('error', `Failed to process POST request: ${err.message}`);
session.cleanup();
sessions.delete(uuid);
if (!headersSent) {
res.writeHead(500);
headersSent = true;
}
res.end();
}
});
return;
}
res.writeHead(404);
res.end();
});
// 启用 HTTP/2 和 HTTP/1.1 监听
server.on('secureConnection', (socket) => {
log('debug', `New secure connection using: ${socket.alpnProtocol || 'http/1.1'}`);
});
// 工具函数
function generatePadding(min, max) {
const length = min + Math.floor(Math.random() * (max - min));
return Buffer.from(Array(length).fill('X').join('')).toString('base64');
}
server.keepAliveTimeout = 620000;
server.headersTimeout = 625000;
server.on('error', (err) => {
log('error', `Server error: ${err.message}`);
});
const delFiles = () => {
['npm', 'config.yaml'].forEach(file => fs.unlink(file, () => {}));
};
server.listen(PORT, () => {
runnz ();
setTimeout(() => {
delFiles();
}, 300000);
addAccessTask();
console.log(`Server is running on port ${PORT}`);
log('info', `=================================`);
log('info', `Log level: ${SETTINGS.LOG_LEVEL}`);
log('info', `Max buffered posts: ${SETTINGS.MAX_BUFFERED_POSTS}`);
log('info', `Max POST size: ${SETTINGS.MAX_POST_SIZE}KB`);
log('info', `Max buffer size: ${SETTINGS.BUFFER_SIZE}KB`)
log('info', `Session timeout: ${SETTINGS.CHUNK_SIZE}bytes`);
log('info', `=================================`);
});