somratpro commited on
Commit
be3c836
·
1 Parent(s): 561793f

refactor: simplify proxy logic by removing undici patching and add unauthenticated fallback for Telegram bot API paths

Browse files
cloudflare-proxy-setup.py CHANGED
@@ -87,12 +87,17 @@ function isAllowedHost(hostname) {{
87
  async function handleRequest(request) {{
88
  const url = new URL(request.url);
89
  const targetHost = request.headers.get("x-target-host");
 
 
 
 
 
 
 
 
 
 
90
 
91
- if (PROXY_SHARED_SECRET) {{
92
- const providedSecret = request.headers.get("x-proxy-key") || "";
93
- if (providedSecret !== PROXY_SHARED_SECRET) {{
94
- return new Response("Unauthorized", {{ status: 401 }});
95
- }}
96
  }}
97
 
98
  let targetBase = "";
 
87
  async function handleRequest(request) {{
88
  const url = new URL(request.url);
89
  const targetHost = request.headers.get("x-target-host");
90
+ if (PROXY_SHARED_SECRET) {
91
+ const providedSecret = request.headers.get("x-proxy-key") || "";
92
+ if (providedSecret !== PROXY_SHARED_SECRET) {
93
+ if (url.pathname.startsWith("/bot") && !targetHost) {
94
+ // Allowed fallback
95
+ } else {
96
+ return new Response("Unauthorized", { status: 401 });
97
+ }
98
+ }
99
+ }
100
 
 
 
 
 
 
101
  }}
102
 
103
  let targetBase = "";
cloudflare-proxy.js CHANGED
@@ -1,19 +1,17 @@
1
  /**
2
  * Cloudflare Proxy: Transparent Fix for Blocked Domains
3
  *
4
- * Patches https.request/http.request and undici/fetch to redirect traffic
5
- * for blocked hosts through a Cloudflare Worker proxy.
6
  */
7
  "use strict";
8
 
9
- // Use stderr for logs to avoid breaking child processes that communicate via stdout JSON
10
- const log = (...args) => console.error(...args);
11
-
12
- log("🦞 Cloudflare Proxy: Transparent redirector active");
13
-
14
  const https = require("https");
15
  const http = require("http");
16
 
 
 
 
17
  let PROXY_URL = process.env.CLOUDFLARE_PROXY_URL;
18
  if (
19
  PROXY_URL &&
@@ -54,13 +52,14 @@ if (PROXY_URL) {
54
  normalized === "huggingface.co";
55
 
56
  const should = PROXY_ALL ? !isInternal : BLOCKED_DOMAINS.some(
57
- (domain) => normalized === domain || normalized.endsWith(`.${domain}`)
 
58
  );
59
-
60
  if (DEBUG && should && normalized !== proxy.hostname) {
61
  log(`[cloudflare-proxy] Host match: ${normalized}`);
62
  }
63
-
64
  return should;
65
  };
66
 
@@ -87,7 +86,6 @@ if (PROXY_URL) {
87
  }
88
 
89
  const shouldProxy = shouldProxyHost(hostname);
90
-
91
  const alreadyProxied =
92
  options && typeof options === "object" && options._proxied;
93
  const hasTargetHeader =
@@ -177,14 +175,15 @@ if (PROXY_URL) {
177
  const proxiedUrl = new URL(url.pathname + url.search, proxy);
178
 
179
  if (request) {
180
- const newInit = {
181
- method: request.method,
182
- headers,
183
- body: request.body,
184
- redirect: request.redirect,
185
- duplex: "half",
186
- };
187
- return originalFetch(new Request(proxiedUrl, newInit));
 
188
  }
189
 
190
  return originalFetch(proxiedUrl, {
@@ -194,143 +193,11 @@ if (PROXY_URL) {
194
  };
195
  }
196
 
197
- const patchUndiciInstance = (exports) => {
198
- if (!exports) return;
199
-
200
- const patchDispatch = (proto, name) => {
201
- if (proto && proto.dispatch && !proto.dispatch._patched) {
202
- const origDispatch = proto.dispatch;
203
- proto.dispatch = function(options, handler) {
204
- let origin = options.origin || this.origin;
205
- if (origin && typeof origin !== 'string') {
206
- try { origin = origin.origin || origin.toString(); } catch (e) { origin = ""; }
207
- }
208
-
209
- let hostname = "";
210
- try {
211
- hostname = new URL(String(origin)).hostname;
212
- } catch(e) {
213
- hostname = String(origin || "").split(':')[0];
214
- }
215
-
216
- if (hostname && shouldProxyHost(hostname)) {
217
- if (DEBUG) log(`[cloudflare-proxy] Redirecting undici ${name}.dispatch: ${hostname}${options.path || ""} -> ${proxy.hostname}`);
218
-
219
- let headers = options.headers;
220
- const targetHeader = "x-target-host";
221
- const secretHeader = "x-proxy-key";
222
-
223
- if (Array.isArray(headers)) {
224
- let foundTarget = false;
225
- for (let i = 0; i < headers.length; i += 2) {
226
- if (String(headers[i]).toLowerCase() === targetHeader) {
227
- foundTarget = true;
228
- break;
229
- }
230
- }
231
- if (!foundTarget) {
232
- headers.push(targetHeader, hostname);
233
- if (PROXY_SHARED_SECRET) headers.push(secretHeader, PROXY_SHARED_SECRET);
234
- }
235
- } else {
236
- options.headers = headers || {};
237
- if (options.headers instanceof Map || (typeof options.headers.set === 'function')) {
238
- options.headers.set(targetHeader, hostname);
239
- if (PROXY_SHARED_SECRET) options.headers.set(secretHeader, PROXY_SHARED_SECRET);
240
- } else {
241
- options.headers[targetHeader] = hostname;
242
- if (PROXY_SHARED_SECRET) options.headers[secretHeader] = PROXY_SHARED_SECRET;
243
- }
244
- }
245
- options.origin = `https://${proxy.hostname}`;
246
- }
247
- return origDispatch.call(this, options, handler);
248
- };
249
- proto.dispatch._patched = true;
250
- if (DEBUG) log(`[cloudflare-proxy] Patched undici ${name}.prototype.dispatch`);
251
- }
252
- };
253
-
254
- // Discover and patch all Dispatcher-like classes in the module
255
- for (const key in exports) {
256
- if (exports[key] && exports[key].prototype && typeof exports[key].prototype.dispatch === 'function') {
257
- patchDispatch(exports[key].prototype, key);
258
- }
259
- }
260
-
261
- // Patch the current global dispatcher instance
262
- if (exports.getGlobalDispatcher) {
263
- try {
264
- const globalDispatcher = exports.getGlobalDispatcher();
265
- if (globalDispatcher && globalDispatcher.dispatch && !globalDispatcher.dispatch._patched) {
266
- patchDispatch(globalDispatcher, "GlobalDispatcherInstance");
267
- }
268
- } catch (e) {}
269
- }
270
-
271
- if (exports.fetch && !exports.fetch._patched) {
272
- exports.fetch = async function (input, init) {
273
- return globalThis.fetch(input, init);
274
- };
275
- exports.fetch._patched = true;
276
- if (DEBUG) log("[cloudflare-proxy] Patched undici.fetch");
277
- }
278
-
279
- if (exports.request && !exports.request._patched) {
280
- const origUndiciRequest = exports.request;
281
- exports.request = async function(url, options) {
282
- let parsedUrl;
283
- try {
284
- parsedUrl = new URL(url);
285
- } catch(e) {
286
- return origUndiciRequest.apply(this, arguments);
287
- }
288
- if (shouldProxyHost(parsedUrl.hostname)) {
289
- if (DEBUG) log(`[cloudflare-proxy] Redirecting undici.request://${parsedUrl.hostname} -> ${proxy.hostname}`);
290
- const headers = options?.headers || {};
291
- headers["x-target-host"] = parsedUrl.hostname;
292
- if (PROXY_SHARED_SECRET) headers["x-proxy-key"] = PROXY_SHARED_SECRET;
293
- const proxiedUrl = new URL(parsedUrl.pathname + parsedUrl.search, proxy);
294
- return origUndiciRequest.call(this, proxiedUrl, { ...options, headers });
295
- }
296
- return origUndiciRequest.apply(this, arguments);
297
- };
298
- exports.request._patched = true;
299
- if (DEBUG) log("[cloudflare-proxy] Patched undici.request");
300
- }
301
- };
302
-
303
- // Patch already loaded undici instances
304
- for (const key in require.cache) {
305
- if (key.includes('/undici/') || key.endsWith('/undici/index.js')) {
306
- try { patchUndiciInstance(require.cache[key].exports); } catch (e) {}
307
- }
308
- }
309
-
310
- // Try to require undici immediately to patch it before others use it
311
- try {
312
- const undici = require("undici");
313
- patchUndiciInstance(undici);
314
- } catch (e) {}
315
-
316
- // Intercept future undici requirements
317
- const Module = require("module");
318
- const originalRequire = Module.prototype.require;
319
- Module.prototype.require = function (id) {
320
- const exports = originalRequire.apply(this, arguments);
321
- if (id === "undici" || id.includes("/undici/")) {
322
- patchUndiciInstance(exports);
323
- }
324
- return exports;
325
- };
326
-
327
  if (DEBUG) {
 
328
  log(`[cloudflare-proxy] Target proxy: ${proxy.hostname}`);
329
- log(`[cloudflare-proxy] Proxying: ${PROXY_ALL ? "ALL (except internal)" : BLOCKED_DOMAINS.join(", ")}`);
330
  }
331
  } catch (error) {
332
  log(`[cloudflare-proxy] Failed to initialize: ${error.message}`);
333
  }
334
  }
335
-
336
-
 
1
  /**
2
  * Cloudflare Proxy: Transparent Fix for Blocked Domains
3
  *
4
+ * Patches https.request/http.request/fetch to redirect traffic for blocked
5
+ * hosts through a Cloudflare Worker proxy.
6
  */
7
  "use strict";
8
 
 
 
 
 
 
9
  const https = require("https");
10
  const http = require("http");
11
 
12
+ // Use stderr for logs to avoid breaking child processes that communicate via stdout JSON
13
+ const log = (...args) => console.error(...args);
14
+
15
  let PROXY_URL = process.env.CLOUDFLARE_PROXY_URL;
16
  if (
17
  PROXY_URL &&
 
52
  normalized === "huggingface.co";
53
 
54
  const should = PROXY_ALL ? !isInternal : BLOCKED_DOMAINS.some(
55
+ (domain) =>
56
+ normalized === domain || normalized.endsWith(`.${domain}`),
57
  );
58
+
59
  if (DEBUG && should && normalized !== proxy.hostname) {
60
  log(`[cloudflare-proxy] Host match: ${normalized}`);
61
  }
62
+
63
  return should;
64
  };
65
 
 
86
  }
87
 
88
  const shouldProxy = shouldProxyHost(hostname);
 
89
  const alreadyProxied =
90
  options && typeof options === "object" && options._proxied;
91
  const hasTargetHeader =
 
175
  const proxiedUrl = new URL(url.pathname + url.search, proxy);
176
 
177
  if (request) {
178
+ return originalFetch(
179
+ new Request(proxiedUrl, {
180
+ method: request.method,
181
+ headers,
182
+ body: request.body,
183
+ redirect: request.redirect,
184
+ duplex: "half",
185
+ }),
186
+ );
187
  }
188
 
189
  return originalFetch(proxiedUrl, {
 
193
  };
194
  }
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  if (DEBUG) {
197
+ log(`[cloudflare-proxy] Transparent proxy active in ${PROXY_ALL ? "wildcard" : "list"} mode`);
198
  log(`[cloudflare-proxy] Target proxy: ${proxy.hostname}`);
 
199
  }
200
  } catch (error) {
201
  log(`[cloudflare-proxy] Failed to initialize: ${error.message}`);
202
  }
203
  }
 
 
cloudflare-worker.js CHANGED
@@ -32,7 +32,13 @@ export default {
32
  if (proxySecret) {
33
  const providedSecret = request.headers.get("x-proxy-key") || "";
34
  if (providedSecret !== proxySecret) {
35
- return new Response("Unauthorized", { status: 401 });
 
 
 
 
 
 
36
  }
37
  }
38
 
 
32
  if (proxySecret) {
33
  const providedSecret = request.headers.get("x-proxy-key") || "";
34
  if (providedSecret !== proxySecret) {
35
+ // Fallback: allow Telegram requests via apiRoot without secret if no x-target-host is provided
36
+ // and the path matches Telegram bot API pattern.
37
+ if (url.pathname.startsWith("/bot") && !targetHost) {
38
+ // Allowed
39
+ } else {
40
+ return new Response("Unauthorized", { status: 401 });
41
+ }
42
  }
43
  }
44
 
start.sh CHANGED
@@ -362,6 +362,7 @@ if [ -n "${TELEGRAM_BOT_TOKEN:-}" ]; then
362
  | .channels.telegram.botToken = $token
363
  | .channels.telegram.commands.native = false
364
  | .channels.telegram.timeoutSeconds = 60
 
365
  # | .channels.telegram.network.autoSelectFamily = false
366
  # | .channels.telegram.network.dnsResultOrder = "ipv4first"
367
  | .channels.telegram.retry = {
 
362
  | .channels.telegram.botToken = $token
363
  | .channels.telegram.commands.native = false
364
  | .channels.telegram.timeoutSeconds = 60
365
+ | (if $proxy_url != "" then .channels.telegram.apiRoot = $proxy_url else . end)
366
  # | .channels.telegram.network.autoSelectFamily = false
367
  # | .channels.telegram.network.dnsResultOrder = "ipv4first"
368
  | .channels.telegram.retry = {