| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| export default { |
| async fetch(request, env, ctx) { |
| const url = new URL(request.url); |
| const targetHost = request.headers.get("x-target-host"); |
| const proxySecret = ( |
| env.CLOUDFLARE_PROXY_SECRET || |
| env.PROXY_SHARED_SECRET || |
| "" |
| ).trim(); |
|
|
| |
| if (proxySecret) { |
| const providedSecret = request.headers.get("x-proxy-key") || ""; |
| if (providedSecret !== proxySecret) { |
| return new Response("Unauthorized", { status: 401 }); |
| } |
| } |
|
|
| const allowedTargetsRaw = ( |
| env.ALLOWED_TARGETS || |
| "api.telegram.org,discord.com,discordapp.com,gateway.discord.gg,status.discord.com" |
| ).trim(); |
| const allowProxyAll = |
| String(env.ALLOW_PROXY_ALL || "false").toLowerCase() === "true"; |
| const allowedTargets = allowedTargetsRaw |
| .split(",") |
| .map((value) => value.trim().toLowerCase()) |
| .filter(Boolean); |
|
|
| const isAllowedHost = (hostname) => { |
| if (!hostname) return false; |
| const normalized = String(hostname).trim().toLowerCase(); |
| if (!normalized) return false; |
| if (allowProxyAll) return true; |
| return allowedTargets.some( |
| (domain) => normalized === domain || normalized.endsWith(`.${domain}`), |
| ); |
| }; |
|
|
| let targetBase = ""; |
|
|
| if (targetHost) { |
| |
| if (!isAllowedHost(targetHost)) { |
| return new Response("Target host is not allowed.", { status: 403 }); |
| } |
| targetBase = `https://${targetHost}`; |
| } else { |
| |
| if (url.pathname.startsWith("/bot")) { |
| targetBase = "https://api.telegram.org"; |
| } else if ( |
| url.pathname.startsWith("/api/webhooks") || |
| url.pathname.startsWith("/api/v") |
| ) { |
| targetBase = "https://discord.com"; |
| } else { |
| return new Response( |
| "Invalid request. 'x-target-host' header missing and target not recognized via path.", |
| { status: 400 }, |
| ); |
| } |
| } |
|
|
| const targetUrl = targetBase + url.pathname + url.search; |
|
|
| |
| const headers = new Headers(request.headers); |
| headers.delete("cf-connecting-ip"); |
| headers.delete("cf-ray"); |
| headers.delete("cf-visitor"); |
| headers.delete("x-real-ip"); |
| headers.delete("x-target-host"); |
|
|
| const modifiedRequest = new Request(targetUrl, { |
| method: request.method, |
| headers: headers, |
| body: request.body, |
| redirect: "follow", |
| }); |
|
|
| try { |
| const response = await fetch(modifiedRequest); |
|
|
| |
| |
|
|
| return response; |
| } catch (e) { |
| return new Response(`Proxy Error: ${e.message}`, { status: 502 }); |
| } |
| }, |
| }; |
|
|