- REALITY, Hysteria2, XHTTP, VLESS/VMess WS, Trojan gRPC, Shadowsocks 2022, TUIC, WireGuard, AmneziaWG (классика и 3.1, обфускация генерируется), MTProto - Все подключения пользователя с общим subId — 3X-UI собирает одну подписку; Clash/Mihomo-клиенты получают готовый конфиг, остальные — ссылки - Свой сертификат: --cert/--key; без Let's Encrypt — самоподписанный, отпечаток в ссылках (pcs) - --protocols для выбора протоколов, повторный запуск досоздаёт недостающее - Генератор Mihomo: AmneziaWG 3.1 с правильными именами параметров и version: 3 - Инструкция и матрица обновлены: подписка проверена на Xray, Mihomo и sing-box
35 lines
2.2 KiB
JavaScript
35 lines
2.2 KiB
JavaScript
// Генерирует конфиги клиентов для каждой пары «протокол × клиент».
|
|
const fs = require('fs'), path = require('path');
|
|
const [lib, linksFile, out] = process.argv.slice(2);
|
|
const PIN = process.env.PIN || ''; // отпечаток тестового сертификата сервера
|
|
const L = require(lib + '/links.js'), X = require(lib + '/xray.js'), M = require(lib + '/mihomo.js'), SB = require(lib + '/singbox.js');
|
|
const { proxies } = L.parseText(fs.readFileSync(linksFile, 'utf8'));
|
|
fs.rmSync(out, { recursive: true, force: true });
|
|
const rows = [];
|
|
proxies.filter((p) => p.type !== 'mtproto').forEach((p, i) => {
|
|
// Тестовый сервер с самоподписанным сертификатом — разрешаем клиентам его принять.
|
|
if (PIN && p.tls && p.tls.security === "tls") { p.tls.insecure = true; p.tls.pin = PIN; }
|
|
if (PIN && (p.type === "hysteria2" || p.type === "tuic")) p.insecure = true;
|
|
if (PIN && p.type === "hysteria2") p.pinSHA256 = PIN;
|
|
const id = String(i).padStart(2, '0') + '-' + p.name.replace(/[^a-z0-9-]/gi, '').slice(0, 24);
|
|
const dir = path.join(out, id);
|
|
fs.mkdirSync(dir, { recursive: true });
|
|
const res = { id, type: p.type, name: p.name };
|
|
try {
|
|
const x = X.buildXray([p], { finalProxy: true });
|
|
const o = x.files['04_outbounds.json'];
|
|
o.inbounds = [{ listen: '127.0.0.1', port: 1080, protocol: 'socks', settings: { udp: true } }];
|
|
o.log = { loglevel: 'warning' };
|
|
fs.writeFileSync(path.join(dir, 'xray.json'), JSON.stringify(o));
|
|
} catch (e) { res.xray = 'n/a: ' + e.message; }
|
|
try {
|
|
fs.writeFileSync(path.join(dir, 'mihomo.yaml'), M.buildMihomo([p], { finalProxy: true, secret: 't', services: [] }).yaml + 'mixed-port: 1081\n');
|
|
} catch (e) { res.mihomo = 'n/a: ' + e.message; }
|
|
try {
|
|
fs.writeFileSync(path.join(dir, 'singbox.json'), JSON.stringify(SB.buildSingbox([p], { inbound: { port: 1082 } }).config));
|
|
} catch (e) { res.singbox = 'n/a: ' + e.message; }
|
|
rows.push(res);
|
|
});
|
|
fs.writeFileSync(path.join(out, 'index.json'), JSON.stringify(rows, null, 1));
|
|
console.log(rows.map((r) => r.id + (r.xray ? ' [xray ' + r.xray + ']' : '') + (r.singbox ? ' [sb ' + r.singbox + ']' : '')).join('\n'));
|