somratpro commited on
Commit
1a290be
Β·
1 Parent(s): 3deb622

fix: Telegram+Discord TLS/SNI bypass via Cloudflare Worker proxy

Browse files

- Confirmed HF blocks Telegram via TLS/SNI inspection (60s timeout, ECONNRESET)
- Moved NODE_OPTIONS to Dockerfile ENV (after COPY) so dns-fix.js loads in n8n
- Added keep-alive=false patch to prevent stale socket ECONNRESET on Node 22
- Removed diagnostic code from dns-fix.js
- Updated README and guide to cover both Discord and Telegram proxy workaround
- Guide now includes Telegram Base URL field instructions for n8n credential

Files changed (3) hide show
  1. DISCORD_PROXY_GUIDE.md +45 -23
  2. README.md +3 -3
  3. dns-fix.js +1 -24
DISCORD_PROXY_GUIDE.md CHANGED
@@ -1,45 +1,67 @@
1
- # πŸ› οΈ How to Create a Free Discord Proxy
2
 
3
- Hugging Face officially blocks outgoing connections to Discord's IP addresses on Free Tier Spaces to prevent spam. While our built-in DNS script cleanly bypasses blocks for Telegram and WhatsApp, Discord is blocked at the physical IP firewall level.
4
 
5
- This means the native n8n "Discord" node will always hang and fail with a "Connection closed unexpectedly" error.
6
 
7
- To work around this, you can easily create your own private Discord proxy using Cloudflare Workers. It takes about 2 minutes and is 100% free (allowing up to 100,000 requests per day).
 
 
8
 
9
- ## Step-by-Step Guide
10
 
11
  ### Step 1: Create a Cloudflare Worker
12
- 1. Log into [Cloudflare](https://dash.cloudflare.com/) (create an account if you don't have one).
13
- 2. On the left sidebar, go to **Workers & Pages**.
14
- 3. Click **Create Worker** -> **Start with Hello World!**.
15
- 4. Name it something memorable, like `discord-proxy`, and click **Deploy**.
16
 
17
  ### Step 2: Add the Proxy Code
18
- 1. Once deployed, click the **Edit Code** button.
19
- 2. In the online code editor, delete the existing code and replace it entirely with this 6-line snippet:
 
20
 
21
  ```javascript
22
  export default {
23
  async fetch(request) {
24
  const url = new URL(request.url);
25
- url.hostname = 'discord.com';
26
  return fetch(new Request(url, request));
27
  }
28
  }
29
  ```
30
 
31
- 3. Click **Save and Deploy** in the top right corner. Cloudflare will generate a unique URL for you (e.g., `https://discord-proxy.yourname.workers.dev`).
 
 
 
 
 
 
 
32
 
33
- ### Step 3: Use the Proxy in n8n
34
- Because the native Discord Node hardcodes connections to `discord.com` when using Bot tokens, you must use the **Webhook** method.
35
 
36
- 1. Add the standard **Discord** node to your n8n workflow.
37
- 2. Under "Authentication", select **Webhook**.
38
- 3. Take your normal Discord Webhook URL and replace `discord.com` with your new worker domain.
39
- * *Original:* `https://discord.com/api/webhooks/123456/abcdef`
40
- * *New:* `https://discord-proxy.yourname.workers.dev/api/webhooks/123456/abcdef`
41
- 4. Create a new Discord Webhook Credential in n8n and paste that **New URL** into the "Webhook URL" field.
42
- 5. Setup your message (e.g., set the text to "Hello World") and click **Execute Node**. Your message will instantly appear in Discord!
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
  ---
45
- *Note: If you ever upgrade your Hugging Face Space to a paid hardware tier, the outgoing firewall restriction is removed, and you can go back to using the native n8n Discord node directly!*
 
 
1
+ # πŸ› οΈ Bypassing Hugging Face Network Restrictions
2
 
3
+ Hugging Face Free Tier Spaces block outgoing connections to certain messaging platforms (**Discord** and **Telegram**) via **TLS/SNI inspection**. This means the TCP connection is allowed, but the TLS handshake is silently dropped as soon as HF detects the target hostname (e.g., `discord.com`, `api.telegram.org`) in the SNI field.
4
 
5
+ The fix is to route your traffic through a **Cloudflare Worker proxy** with a neutral hostname. Since the SNI in the TLS handshake will show `your-proxy.workers.dev` instead of the blocked hostname, HF's filter won't block it. Cloudflare Workers are **100% free** (100,000 requests/day).
6
 
7
+ ---
8
+
9
+ ## Setting Up a Cloudflare Worker Proxy
10
 
11
+ This process takes about 2 minutes and works for both Discord and Telegram.
12
 
13
  ### Step 1: Create a Cloudflare Worker
14
+ 1. Log into [Cloudflare](https://dash.cloudflare.com/) (create a free account if needed).
15
+ 2. Go to **Workers & Pages** in the left sidebar.
16
+ 3. Click **Create Worker** β†’ **Start with Hello World!**.
17
+ 4. Give it a name (e.g., `discord-proxy` or `telegram-proxy`) and click **Deploy**.
18
 
19
  ### Step 2: Add the Proxy Code
20
+ 1. Click **Edit Code**.
21
+ 2. Delete all existing code and paste the following snippet.
22
+ 3. Replace `TARGET_HOSTNAME` with the service you want to proxy (see table below).
23
 
24
  ```javascript
25
  export default {
26
  async fetch(request) {
27
  const url = new URL(request.url);
28
+ url.hostname = 'TARGET_HOSTNAME';
29
  return fetch(new Request(url, request));
30
  }
31
  }
32
  ```
33
 
34
+ | Service | Replace `TARGET_HOSTNAME` with |
35
+ | :--- | :--- |
36
+ | Discord | `discord.com` |
37
+ | Telegram | `api.telegram.org` |
38
+
39
+ 4. Click **Save and Deploy**. Cloudflare gives you a URL like `https://your-proxy.yourname.workers.dev`.
40
+
41
+ ---
42
 
43
+ ## Using the Proxy in n8n
 
44
 
45
+ ### Discord
46
+ The native n8n Discord node uses Bot tokens that hardcode `discord.com`. Use the **Webhook** authentication method instead:
47
+
48
+ 1. Add a **Discord** node and set the **Credential** to use **Webhook** authentication.
49
+ 2. Create a new Discord Webhook credential.
50
+ 3. Take your Discord Webhook URL and replace `discord.com` with your Worker domain:
51
+ - *Original:* `https://discord.com/api/webhooks/123456/abcdef`
52
+ - *Proxied:* `https://discord-proxy.yourname.workers.dev/api/webhooks/123456/abcdef`
53
+ 4. Paste the proxied URL in the **Webhook URL** field.
54
+
55
+ ### Telegram
56
+ The n8n Telegram credential has a **Base URL** field that can be changed:
57
+
58
+ 1. Go to **Credentials** β†’ add or edit a **Telegram** credential.
59
+ 2. Enter your Bot Token as usual.
60
+ 3. In the **Base URL** field, replace `https://api.telegram.org` with your Worker URL:
61
+ - *Original:* `https://api.telegram.org`
62
+ - *Proxied:* `https://telegram-proxy.yourname.workers.dev`
63
+ 4. Click **Save** and then **Test** β€” it should connect instantly.
64
 
65
  ---
66
+
67
+ *Note: Upgrading your Hugging Face Space to a paid hardware tier removes these network restrictions entirely, allowing you to use all n8n nodes natively without a proxy.*
README.md CHANGED
@@ -68,10 +68,10 @@ Hugging8n automatically creates and maintains a private dataset in your Hugging
68
 
69
  ## ⚠️ Known Limitations & Workarounds
70
 
71
- **Discord Webhooks**
72
- Hugging Face officially blocks outgoing connections to Discord on Free Tier Spaces. To use the Discord node, you must route your traffic through a simple, free proxy.
73
 
74
- πŸ‘‰ **[Read the Guide: How to Create a Free Discord Proxy in 2 minutes](./DISCORD_PROXY_GUIDE.md)**
75
  *(Upgrading to a paid Space removes this firewall restriction entirely).*
76
 
77
  ## πŸ—οΈ Architecture
 
68
 
69
  ## ⚠️ Known Limitations & Workarounds
70
 
71
+ **Discord & Telegram Webhooks Blocked by Hugging Face**
72
+ Hugging Face blocks outgoing connections to Discord and Telegram on Free Tier Spaces via TLS/SNI inspection β€” the TCP connection opens but the TLS handshake is silently dropped when the target hostname is detected. To use these services, you must route traffic through a proxy with a different hostname.
73
 
74
+ πŸ‘‰ **[Read the Guide: How to Create a Free Cloudflare Proxy in 2 minutes](./DISCORD_PROXY_GUIDE.md)**
75
  *(Upgrading to a paid Space removes this firewall restriction entirely).*
76
 
77
  ## πŸ—οΈ Architecture
dns-fix.js CHANGED
@@ -11,7 +11,7 @@
11
  */
12
  "use strict";
13
 
14
- console.error("[DNS-FIX] dns-fix.js preload script loaded successfully.");
15
 
16
  const dns = require("dns");
17
  const http = require("http");
@@ -22,29 +22,6 @@ http.globalAgent = new http.Agent({ keepAlive: false });
22
  https.globalAgent = new https.Agent({ keepAlive: false });
23
  // ─────────────────────────────────────────────────────────────────────────────
24
 
25
- // ── TCP Connection Diagnostics ────────────────────────────────────────────────
26
- // Temporarily patch net.createConnection to log all outgoing TCP connections
27
- // and their errors so we can identify the exact IP and failure mode.
28
- const net = require("net");
29
- const _origConnect = net.createConnection.bind(net);
30
- net.createConnection = function (options, ...args) {
31
- const host = options.host || options;
32
- const port = options.port;
33
- // Only log external connections (skip loopback)
34
- if (host && host !== "127.0.0.1" && host !== "localhost" && host !== "::1") {
35
- console.error(`[DNS-FIX] TCP connect β†’ ${host}:${port}`);
36
- const sock = _origConnect(options, ...args);
37
- sock.on("connect", () =>
38
- console.error(`[DNS-FIX] TCP connected βœ“ ${host}:${port}`),
39
- );
40
- sock.on("error", (err) =>
41
- console.error(`[DNS-FIX] TCP error βœ— ${host}:${port} β€” ${err.code}: ${err.message}`),
42
- );
43
- return sock;
44
- }
45
- return _origConnect(options, ...args);
46
- };
47
- // ─────────────────────────────────────────────────────────────────────────────
48
 
49
  // In-memory cache for runtime DoH resolutions
50
  const runtimeCache = new Map(); // hostname -> { ip, expiry }
 
11
  */
12
  "use strict";
13
 
14
+ console.error("[DNS-FIX] Loaded β€” DoH-first resolver + keep-alive patch active.");
15
 
16
  const dns = require("dns");
17
  const http = require("http");
 
22
  https.globalAgent = new https.Agent({ keepAlive: false });
23
  // ─────────────────────────────────────────────────────────────────────────────
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
  // In-memory cache for runtime DoH resolutions
27
  const runtimeCache = new Map(); // hostname -> { ip, expiry }