144 lines
3.8 KiB
JavaScript
Executable File
144 lines
3.8 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
||
/**
|
||
* Reads scripts/onion-nodes.json and writes:
|
||
* lib/onionRoutes.generated.ts
|
||
* tor/cyberlux-nodes.conf
|
||
* scripts/generated/tor-dirs.txt
|
||
* scripts/generated/onion-labels.tsv
|
||
* scripts/generated/onion-port-range.txt
|
||
*/
|
||
"use strict";
|
||
|
||
const fs = require("fs");
|
||
const path = require("path");
|
||
|
||
const REPO = path.join(__dirname, "..");
|
||
const jsonPath = path.join(__dirname, "onion-nodes.json");
|
||
const data = JSON.parse(fs.readFileSync(jsonPath, "utf8"));
|
||
const nodes = data.nodes;
|
||
const TOR_INTRO_DOS_RATE_PER_SEC = 12;
|
||
const TOR_INTRO_DOS_BURST_PER_SEC = 80;
|
||
const KNOWN_APP_ENTRIES = [
|
||
"hub",
|
||
"wiki",
|
||
"w",
|
||
"account",
|
||
"arb-academy",
|
||
"awards",
|
||
"barter",
|
||
"chatter",
|
||
"checkout",
|
||
"comparison",
|
||
"conspiracies",
|
||
"darknet-atlas",
|
||
"dashboard",
|
||
"directory",
|
||
"drop-box",
|
||
"drops",
|
||
"easter-eggs",
|
||
"exchange",
|
||
"forum",
|
||
"game",
|
||
"hidden-wiki",
|
||
"inner-circle",
|
||
"links",
|
||
"market",
|
||
"messages",
|
||
"mixer",
|
||
"presswire",
|
||
"raffle",
|
||
"red-room",
|
||
"reviews",
|
||
"sanctuary",
|
||
"search",
|
||
"secret-layer",
|
||
"security-analysis",
|
||
"sign-in",
|
||
"sign-up",
|
||
"support",
|
||
"syndicate",
|
||
"testimonials",
|
||
"trees",
|
||
"trust",
|
||
"vault",
|
||
"vendors",
|
||
"wallets",
|
||
"webring",
|
||
];
|
||
|
||
function torBlock(dir, port) {
|
||
return `
|
||
HiddenServiceDir /var/lib/tor/${dir}
|
||
HiddenServicePort 80 127.0.0.1:${port}
|
||
HiddenServiceEnableIntroDoSDefense 1
|
||
HiddenServiceEnableIntroDoSRatePerSec ${TOR_INTRO_DOS_RATE_PER_SEC}
|
||
HiddenServiceEnableIntroDoSBurstPerSec ${TOR_INTRO_DOS_BURST_PER_SEC}`;
|
||
}
|
||
|
||
const ports = nodes.map((n) => n.port);
|
||
const minP = Math.min(...ports);
|
||
const maxP = Math.max(...ports);
|
||
|
||
const dedicated = {};
|
||
for (const n of nodes) {
|
||
if (n.kind === "dedicated") dedicated[n.entry] = n.path;
|
||
}
|
||
|
||
const uniqueEntries = Array.from(new Set([...KNOWN_APP_ENTRIES, ...Object.keys(dedicated)])).sort((a, b) => {
|
||
if (a === "hub") return -1;
|
||
if (b === "hub") return 1;
|
||
return a.localeCompare(b);
|
||
});
|
||
|
||
const drLines = Object.keys(dedicated)
|
||
.sort()
|
||
.map((k) => ` ${JSON.stringify(k)}: ${JSON.stringify(dedicated[k])},`)
|
||
.join("\n");
|
||
|
||
const ts = `// AUTO-GENERATED by scripts/generate-onion-config.cjs — do not edit
|
||
|
||
export const CYBERLUX_ENTRY_VALUES = [
|
||
${uniqueEntries.map((e) => ` ${JSON.stringify(e)},`).join("\n")}
|
||
] as const;
|
||
|
||
export type CyberluxEntry = (typeof CYBERLUX_ENTRY_VALUES)[number];
|
||
|
||
export const DEDICATED_ROOT = {
|
||
${drLines}
|
||
} as const;
|
||
`;
|
||
|
||
let torConf =
|
||
"# CyberLux — generated v3 onion services (include from torrc)\n#\n# Tor ≥ 0.4.7: DoS lines follow each HiddenServiceDir/Port pair.\n";
|
||
|
||
for (const n of nodes) {
|
||
torConf += torBlock(n.torDir, n.port);
|
||
}
|
||
|
||
const genDir = path.join(REPO, "scripts", "generated");
|
||
fs.mkdirSync(genDir, { recursive: true });
|
||
|
||
const torDirs = nodes.map((n) => n.torDir);
|
||
fs.writeFileSync(path.join(genDir, "tor-dirs.txt"), torDirs.join("\n") + "\n");
|
||
|
||
const labels = [];
|
||
for (const n of nodes) {
|
||
let desc = "";
|
||
if (n.kind === "hub") desc = "Hub — full storefront";
|
||
else if (n.kind === "wiki") desc = "Wiki — / → /hidden-wiki";
|
||
else if (n.kind === "w") desc = "Shadow nodes — / → /syndicate, /x → /w/x";
|
||
else desc = `${n.entry} — / → ${n.path}`;
|
||
labels.push(`${n.torDir}\t${desc}`);
|
||
}
|
||
fs.writeFileSync(path.join(genDir, "onion-labels.tsv"), labels.join("\n") + "\n");
|
||
fs.writeFileSync(path.join(genDir, "onion-port-range.txt"), `${minP} ${maxP}\n`);
|
||
|
||
fs.writeFileSync(path.join(REPO, "lib", "onionRoutes.generated.ts"), ts);
|
||
fs.writeFileSync(path.join(REPO, "tor", "cyberlux-nodes.conf"), torConf.trim() + "\n");
|
||
|
||
const onionLabel = nodes.length === 1 ? "onion" : "onions";
|
||
const loopbackLabel = minP === maxP ? `${minP}` : `${minP}–${maxP}`;
|
||
console.log(
|
||
`[generate-onion-config] ${nodes.length} ${onionLabel}, nginx loopback ${loopbackLabel}, TS entries: ${uniqueEntries.length}`,
|
||
);
|