Upload via GUI (202 Dateien)

This commit is contained in:
2026-10-11 07:05:41 +00:00
parent 4a7a619f35
commit c56b41de34
6 changed files with 35 additions and 5 deletions
+27 -3
View File
@@ -1,6 +1,7 @@
'use strict';
const http = require('http');
const crypto = require('crypto');
const { Readable } = require('stream');
const KEY = (process.env.CF_API_KEY || '').trim();
@@ -35,6 +36,17 @@ if (!KEY) {
process.exit(1);
}
// Ohne Token wäre der Dienst für jeden offen, der die Adresse kennt – und damit
// auch der API-Key und das Download-Kontingent dahinter. Deshalb startet er
// ohne CF_PROXY_TOKEN gar nicht erst. Wer ihn bewusst offen betreiben will
// (z. B. nur im eigenen Netz), muss das ausdrücklich sagen: CF_PROXY_OFFEN=1.
const OFFEN_ERLAUBT = process.env.CF_PROXY_OFFEN === '1';
if (!TOKENS.size && !OFFEN_ERLAUBT) {
console.error('CF_PROXY_TOKEN fehlt. Ohne Token könnte jeder den Dienst (und deinen API-Key) benutzen.');
console.error('Token setzen (siehe .env.example) – oder, nur für ein abgeschottetes Netz, CF_PROXY_OFFEN=1.');
process.exit(1);
}
// ---------------------------------------------------------------------------
// Ratenbegrenzung: einfaches Zeitfenster je Absender
// ---------------------------------------------------------------------------
@@ -88,9 +100,21 @@ function sendeJson(res, code, daten) {
res.end(koerper);
}
// Vergleich in gleichbleibender Zeit, damit sich ein Token nicht Zeichen für
// Zeichen über die Antwortdauer erraten lässt
function gleich(a, b) {
const x = crypto.createHash('sha256').update(a).digest();
const y = crypto.createHash('sha256').update(b).digest();
return crypto.timingSafeEqual(x, y);
}
function tokenOk(req) {
if (!TOKENS.size) return true;
return TOKENS.has(String(req.headers['x-aeromc-token'] || '').trim());
if (!TOKENS.size) return OFFEN_ERLAUBT; // ohne Token nur mit ausdrücklicher Freigabe
const erhalten = String(req.headers['x-aeromc-token'] || '').trim();
if (!erhalten) return false;
let ok = false;
for (const t of TOKENS) if (gleich(t, erhalten)) ok = true;
return ok;
}
function leseKoerper(req, maxBytes = 1_000_000) {
@@ -308,7 +332,7 @@ server.listen(PORT, HOST, () => {
console.log(`AeroMC CurseForge-Weiterleitung läuft auf ${HOST}:${PORT}`);
console.log(` Ratenbegrenzung: ${LIMIT_PRO_MIN > 0 ? LIMIT_PRO_MIN + '/Minute je Absender' : 'aus'}`);
// niemals die Token selbst ausgeben – Protokolle wandern schnell woanders hin
console.log(` Token verlangt : ${TOKENS.size ? 'ja (' + TOKENS.size + ' gültige)' : 'nein'}`);
console.log(` Token verlangt : ${TOKENS.size ? 'ja (' + TOKENS.size + ' gültige)' : 'NEIN – offen für jeden (CF_PROXY_OFFEN=1)'}`);
console.log(` Proxy-Stufen : ${PROXY_STUFEN} (${PROXY_STUFEN ? 'Absender aus X-Forwarded-For' : 'Absender aus der Verbindung'})`);
});