Files
CFspider/obfuscate.js
2026-01-24 10:47:54 +08:00

310 lines
9.9 KiB
JavaScript

const Terser = require('terser');
const fs = require('fs');
async function obfuscate() {
let code = fs.readFileSync('workers.js', 'utf8');
// 第一步:将所有中文变量名替换为英文
const replacements = [
// 变量名替换
['config_JSON', 'cfgData'],
['反代IP', 'proxyIp'],
['启用SOCKS5反代', 'enableSocks5'],
['启用SOCKS5全局反代', 'globalSocks5'],
['我的SOCKS5账号', 'socks5Account'],
['parsedSocks5Address', 'parsedS5Addr'],
['缓存反代IP', 'cachedProxyIp'],
['缓存反代解析数组', 'cachedProxyArr'],
['缓存反代数组索引', 'cachedProxyIdx'],
['启用反代兜底', 'enableFallback'],
['ECH_DOH', 'echDoh'],
['SOCKS5白名单', 'socks5Whitelist'],
['Pages静态页面', 'staticPages'],
['管理员密码', 'adminPass'],
['加密秘钥', 'encKey'],
['userIDMD5', 'uidMd5'],
['uuidRegex', 'uidRegex'],
['envUUID', 'envUid'],
['userID', 'uid'],
['访问IP', 'clientIp'],
['upgradeHeader', 'upHeader'],
// 函数名替换
['整理成数组', 'toArray'],
['MD5MD5', 'hashMd5'],
['解析SOCKS5地址', 'parseSocks5'],
['获取配置', 'getConfig'],
['获取随机IP', 'getRandIp'],
['解析订阅地址', 'parseSub'],
['记录日志', 'logRecord'],
['脱敏', 'maskStr'],
['获取CF用量', 'getCfUsage'],
['检测SOCKS5', 'checkSocks5'],
['处理websocket', 'handleWs'],
['处理TCP出站', 'handleTcp'],
['处理UDP', 'handleUdp'],
['关闭ws连接', 'closeWs'],
['写入ws流', 'writeToWs'],
['是否禁止地址', 'isBlocked'],
['SOCKS5出站', 'socks5Out'],
['HTTP代理出站', 'httpProxyOut'],
// 其他变量
['双层代理', 'twoProxy'],
['地址', 'addr'],
['端口', 'port'],
['主机名', 'hostname'],
['用户名', 'username'],
['密码', 'password'],
['协议', 'protocol'],
['路径', 'path'],
['域名', 'domain'],
['响应', 'response'],
['请求', 'request'],
['链接', 'link'],
['配置', 'config'],
['错误', 'error'],
['成功', 'success'],
['失败', 'failed'],
['开始', 'start'],
['结束', 'end'],
['时间', 'time'],
['日期', 'date'],
['消息', 'message'],
['数据', 'data'],
['结果', 'result'],
['状态', 'status'],
['类型', 'type'],
['长度', 'length'],
['索引', 'index'],
['数组', 'array'],
['对象', 'object'],
['字符串', 'string'],
['数字', 'number'],
['布尔', 'boolean'],
['函数', 'func'],
['方法', 'method'],
['属性', 'prop'],
['参数', 'param'],
['返回', 'ret'],
['继续', 'cont'],
['跳过', 'skip'],
['等待', 'wait'],
['加载', 'load'],
['保存', 'save'],
['删除', 'del'],
['更新', 'update'],
['读取', 'read'],
['写入', 'write'],
['发送', 'send'],
['接收', 'recv'],
['连接', 'connect'],
['断开', 'disconnect'],
['启动', 'launch'],
['停止', 'stop'],
['初始化', 'init'],
['销毁', 'destroy'],
['创建', 'create'],
['获取', 'get'],
['设置', 'set'],
['检查', 'check'],
['验证', 'verify'],
['解析', 'parse'],
['格式化', 'format'],
['转换', 'convert'],
['编码', 'encode'],
['解码', 'decode'],
['加密', 'encrypt'],
['解密', 'decrypt'],
['压缩', 'compress'],
['解压', 'decompress'],
['排序', 'sort'],
['过滤', 'filter'],
['映射', 'map'],
['查找', 'find'],
['替换', 'replace'],
['分割', 'split'],
['合并', 'merge'],
['复制', 'copy'],
['移动', 'move'],
['交换', 'swap'],
['比较', 'compare'],
['计算', 'calc'],
['统计', 'stat'],
['生成', 'gen'],
['随机', 'rand'],
['默认', 'def'],
['自定义', 'custom'],
['系统', 'system'],
['用户', 'user'],
['管理', 'manage'],
['权限', 'permission'],
['角色', 'role'],
['组', 'group'],
['文件', 'file'],
['目录', 'dir'],
['网络', 'network'],
['服务', 'service'],
['客户端', 'client'],
['服务器', 'server'],
['代理', 'proxy'],
['转发', 'forward'],
['重定向', 'redirect'],
['缓存', 'cache'],
['存储', 'storage'],
['数据库', 'database'],
['表', 'table'],
['记录', 'record'],
['字段', 'field'],
['键', 'key'],
['值', 'value'],
['选项', 'option'],
['设定', 'setting'],
['模式', 'mode'],
['版本', 'version'],
['环境', 'env'],
['调试', 'debug'],
['测试', 'test'],
['生产', 'prod'],
['开发', 'dev'],
['正式', 'release'],
['草稿', 'draft'],
['发布', 'publish'],
['订阅', 'subscribe'],
['取消', 'cancel'],
['确认', 'confirm'],
['提交', 'submit'],
['重置', 'reset'],
['刷新', 'refresh'],
['同步', 'sync'],
['异步', 'async'],
['超时', 'timeout'],
['重试', 'retry'],
['限制', 'limit'],
['最大', 'max'],
['最小', 'min'],
['平均', 'avg'],
['总计', 'total'],
['当前', 'current'],
['上一个', 'prev'],
['下一个', 'next'],
['第一个', 'first'],
['最后一个', 'last'],
['全部', 'all'],
['部分', 'part'],
['其他', 'other'],
['未知', 'unknown'],
['空', 'empty'],
['非空', 'notEmpty'],
['有效', 'valid'],
['无效', 'invalid'],
['启用', 'enabled'],
['禁用', 'disabled'],
['是', 'yes'],
['否', 'no'],
['真', 'trueVal'],
['假', 'falseVal'],
['输入', 'input'],
['输出', 'output'],
['来源', 'source'],
['目标', 'target'],
['原始', 'raw'],
['处理后', 'processed'],
['临时', 'temp'],
['永久', 'permanent'],
['公开', 'pub'],
['私有', 'priv'],
['共享', 'shared'],
['独占', 'exclusive'],
['只读', 'readOnly'],
['可写', 'writable'],
['可执行', 'executable'],
['隐藏', 'hidden'],
['显示', 'visible'],
['激活', 'active'],
['不活动', 'inactive'],
['在线', 'online'],
['离线', 'offline'],
['忙碌', 'busy'],
['空闲', 'idle'],
['等待中', 'waiting'],
['运行中', 'running'],
['已完成', 'completed'],
['已取消', 'cancelled'],
['已失败', 'failedStatus'],
['已暂停', 'paused'],
['已恢复', 'resumed'],
['公开模式', 'publicMode'],
['荷兰节点', 'nlNode'],
['香港节点', 'hkNode'],
['联通优选', 'cuOptimal'],
['移动优选', 'cmccOptimal'],
['电信优选', 'ctOptimal'],
['官方优选', 'cfOptimal'],
['请求次数', 'reqCount'],
['流量', 'traffic'],
['位置', 'location'],
['地区', 'region'],
['国家', 'country'],
['城市', 'city'],
['速度', 'speed'],
['延迟', 'latency'],
['节点', 'node'],
['订阅链接', 'subLink'],
['配置文件', 'configFile'],
['日志', 'log'],
['通知', 'notify'],
['告警', 'alert'],
['警告', 'warn'],
['信息', 'info'],
];
// 按长度排序(长的先替换,避免部分匹配问题)
replacements.sort((a, b) => b[0].length - a[0].length);
for (const [cn, en] of replacements) {
// 使用正则匹配完整词,避免部分替换
const regex = new RegExp(cn.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
code = code.replace(regex, en);
}
// 第二步:使用 Terser 进行混淆和压缩
const result = await Terser.minify(code, {
compress: {
dead_code: true,
drop_console: false, // 保留 console.log 便于调试
drop_debugger: true,
passes: 2,
},
mangle: {
toplevel: true,
reserved: ['fetch', 'Request', 'Response', 'Headers', 'URL', 'WebSocket', 'WebSocketPair', 'crypto', 'atob', 'btoa', 'TextEncoder', 'TextDecoder', 'ReadableStream', 'WritableStream', 'DataView', 'Uint8Array', 'ArrayBuffer', 'JSON', 'Math', 'Date', 'Promise', 'Error', 'console', 'performance', 'globalThis', 'AbortController'],
},
format: {
comments: false,
},
module: true,
});
if (result.error) {
console.error('Terser error:', result.error);
process.exit(1);
}
// 写入输出文件
fs.writeFileSync('破皮版workers.js', result.code, 'utf8');
const originalSize = Buffer.byteLength(fs.readFileSync('workers.js', 'utf8'), 'utf8');
const outputSize = Buffer.byteLength(result.code, 'utf8');
console.log(`Original size: ${(originalSize / 1024).toFixed(1)} KB`);
console.log(`Obfuscated size: ${(outputSize / 1024).toFixed(1)} KB`);
console.log(`Compression ratio: ${((1 - outputSize / originalSize) * 100).toFixed(1)}%`);
console.log('Done! Output: 破皮版workers.js');
}
obfuscate().catch(err => {
console.error('Error:', err);
process.exit(1);
});