Files
3X-UI_autoVPS/tests/matrix/matrix-gen.js
T
Claude 0a19858efa 1.1: подписанное автообновление, kit backup и --restore, случайная заглушка
- kit update ставит только релизы, у которых SHA256SUMS подписан ключом автора
  (ssh-keygen -Y verify), версия внутри подписи совпадает, файлы сошлись с хешами;
  откат на старую версию запрещён; после обновления проверяется подписка, иначе возврат
- автообновление: systemd-таймер раз в сутки ночью со случайной задержкой,
  kit update --manual / --auto, журнал /var/log/kit-update.log
- hy2 update тоже проверяет подпись
- tools/release.sh: проверка версий и хеша установщика 3X-UI, SHA256SUMS и подпись
- kit backup и 3x-ui.sh --restore: архив 600, строгая проверка архива, конфиги nginx
  и kit-sub собираются заново, смена IP в подключениях
- сайт-заглушка: случайный из шести шаблонов внутри скрипта
- zashboard закреплён на v3.29.1, короткие тире и 192.168.x.x в текстах и картинках
- CI: ключ подписи одинаковый в kit и hy2, проверка подписи релиза
- CHANGELOG, README, инструкция, SECURITY.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q7GrBSRPVXhrz3RAprWDnt
2026-09-30 19:15:19 +00:00

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'));