背景:OpenClaw 在 v2026.3.11 版本更新后,原本依赖的 openclaw-telegram-proxy 插件(通过 Cloudflare Worker 反代)失效。该插件通过修改 grammY 库的 API 请求地址,将 api.telegram.org 替换为自定义的 Cloudflare Worker 域名(如 telegram.chuchu-z.com),从而绕过大陆网络封锁。

插件失效原因

  • OpenClaw v2026.3.11 版本对 Telegram 频道的初始化流程进行了重构
  • OpenClaw 的 Telegram 插件基于 grammY 库,启动时必须请求 Telegram API 初始化 bot
  • 插件的 hook 机制失效,无法在 grammY 初始化前修改 API 地址
  • 直接修改插件代码也无法适配新版本的内部结构

解决思路

本地 nginx 拦截 + 反代

既然无法在应用层修改 API 地址,那就在系统层透明拦截 api.telegram.org 的请求,通过本地 nginx 反代转发到可访问的境外服务器。

通过四个组件的组合,让 Node.js “以为”在访问真实的 api.telegram.org,实际上流量走境外反代服务器:

Node.js (grammY)
    ↓ 请求 https://api.telegram.org
/etc/hosts 拦截
    ↓ 127.0.0.1 api.telegram.org
本地 nginx(自签名 SSL)
    ↓ proxy_pass
https://telegram.chuchu-z.com(境外反代)
    ↓
api.telegram.org(Telegram 真实服务器)

关键技术点

  1. /etc/hostsapi.telegram.org 解析到本机 127.0.0.1
  2. 本地 nginx 监听 443,用自签名证书(CN=api.telegram.org)响应 HTTPS 请求
  3. Node.js 默认不信任自签名证书,需通过 NODE_EXTRA_CA_CERTS 环境变量让其信任
  4. nginx 将请求透明转发到 telegram.chuchu-z.com(一个可访问 Telegram 的境外反代)

解决方案

前置准备:部署 Cloudflare Worker 反向代理

虽然 openclaw-telegram-proxy 插件失效,但 Cloudflare Worker 反代本身仍然可用,只是需要通过本地 nginx 来调用。

步骤 1:创建 Cloudflare Worker
  1. 登录 Cloudflare Dashboard
  2. 进入 Workers & Pages → Create application → Create Worker
  3. 选择 Hello World 模板,命名(如 telegram-proxy
  4. 编辑 Worker,粘贴以下代码:
const ALLOWED_METHODS = ['GET', 'POST', 'PUT', 'DELETE'];

const ALLOWED_HEADERS = [
  'Content-Type', 'Authorization', 'User-Agent', 'Accept',
  'Accept-Language', 'Accept-Encoding', 'Connection',
  'Cache-Control', 'Pragma', 'X-Requested-With'
];

const REMOVE_HEADERS = [
  'host', 'cf-connecting-ip', 'cf-ray', 'cf-visitor',
  'x-forwarded-for', 'x-real-ip'
];

async function handleRequest(request) {
  try {
    if (request.method === 'OPTIONS') return handleCORS();
    if (!ALLOWED_METHODS.includes(request.method)) {
      return new Response('Method Not Allowed', { status: 405 });
    }
    const url = new URL(request.url);
    const targetUrl = `https://api.telegram.org${url.pathname}${url.search}`;
    const headers = new Headers();
    for (const h of ALLOWED_HEADERS) {
      const v = request.headers.get(h);
      if (v) headers.set(h, v);
    }
    headers.set('Host', 'api.telegram.org');
    headers.set('User-Agent', 'Cloudflare-Worker-Telegram-Proxy/1.0');
    const opts = { method: request.method, headers, redirect: 'follow' };
    if (request.method !== 'GET' && request.method !== 'HEAD') {
      opts.body = request.body;
    }
    const response = await fetch(new Request(targetUrl, opts));
    const respHeaders = new Headers();
    for (const [k, v] of response.headers.entries()) {
      if (!REMOVE_HEADERS.includes(k.toLowerCase())) respHeaders.set(k, v);
    }
    respHeaders.set('Access-Control-Allow-Origin', '*');
    respHeaders.set('Cache-Control', 'no-cache, no-store, must-revalidate');
    return new Response(response.body, {
      status: response.status, statusText: response.statusText, headers: respHeaders
    });
  } catch (e) {
    return new Response('Internal Server Error', { status: 500 });
  }
}

function handleCORS() {
  return new Response(null, {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': ALLOWED_METHODS.join(', '),
      'Access-Control-Allow-Headers': ALLOWED_HEADERS.join(', '),
      'Access-Control-Max-Age': '86400'
    }
  });
}

addEventListener('fetch', event => {
  const url = new URL(event.request.url);
  if (url.pathname === '/health' || url.pathname === '/status') {
    event.respondWith(new Response(JSON.stringify({ status: 'ok' }), {
      headers: { 'Content-Type': 'application/json' }
    }));
    return;
  }
  event.respondWith(handleRequest(event.request));
});
  1. 保存并部署
步骤 2:绑定自定义域名(关键)

workers.dev 域名在国内被墙,必须绑定自定义域名走 Cloudflare CDN。

前提:域名 NS 托管在 Cloudflare(如 chuchu-z.com,NS 为 *.ns.cloudflare.com

  1. Workers & Pages → 选择你的 Worker → Settings → Domains & Routes
  2. Add → Custom Domain → 填入子域名(如 telegram.chuchu-z.com
  3. Cloudflare 自动创建 DNS 记录并签发 SSL 证书
  4. 等待状态变为 Active
步骤 3:验证 Worker 代理
curl https://telegram.chuchu-z.com/botINVALID/getMe
# 期望输出: {"ok":false,"error_code":404,"description":"Not Found"}

返回 Telegram API 的 JSON 响应即代理正常。


核心方案:本地 nginx 反代

步骤 1:生成自签名证书
openssl req -x509 -nodes -newkey rsa:2048 \
  -keyout /etc/ssl/private/telegram-proxy.key \
  -out /usr/local/share/ca-certificates/telegram-proxy.crt \
  -days 3650 \
  -subj "/CN=api.telegram.org" \
  -addext "subjectAltName=DNS:api.telegram.org"

# 同时复制一份到 /etc/ssl/certs(供 NODE_EXTRA_CA_CERTS 使用)
cp /usr/local/share/ca-certificates/telegram-proxy.crt /etc/ssl/certs/telegram-proxy.crt

# 加入系统 CA(可选,供系统工具如 curl 使用)
/usr/sbin/update-ca-certificates
步骤 2:配置 nginx 反代

创建 /etc/nginx/sites-available/telegram-proxy

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name api.telegram.org;

    ssl_certificate /etc/ssl/certs/telegram-proxy.crt;
    ssl_certificate_key /etc/ssl/private/telegram-proxy.key;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    location / {
        resolver 8.8.8.8 ipv6=off;
        proxy_pass https://telegram.chuchu-z.com;
        proxy_ssl_server_name on;
        proxy_set_header Host telegram.chuchu-z.com;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_connect_timeout 30s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
    }

    access_log /var/log/nginx/telegram-proxy.access.log;
    error_log /var/log/nginx/telegram-proxy.error.log;
}

启用配置并重载 nginx:

ln -sf /etc/nginx/sites-available/telegram-proxy /etc/nginx/sites-enabled/telegram-proxy
/usr/sbin/nginx -t && /usr/sbin/nginx -s reload
步骤 3:修改 /etc/hosts
echo "127.0.0.1 api.telegram.org" >> /etc/hosts
步骤 4:让 Node.js 信任自签名证书

编辑 ~/.config/systemd/user/openclaw-gateway.service,在 [Service] 块末尾添加:

Environment=NODE_EXTRA_CA_CERTS=/etc/ssl/certs/telegram-proxy.crt
步骤 5:完整重启 OpenClaw
systemctl --user daemon-reload
systemctl --user restart openclaw-gateway.service

⚠️ 重要NODE_EXTRA_CA_CERTS 是进程启动时读取的环境变量,使用 openclaw gateway restart(SIGUSR1 热重启)不会重新加载环境变量,必须通过 systemd 完整重启服务。

步骤 6:验证
# 测试本地代理是否正常(应返回 Telegram API 的 JSON 响应)
curl -sk --resolve "api.telegram.org:443:127.0.0.1" \
  "https://api.telegram.org/botINVALID/getMe"

# 期望输出(说明代理工作正常):
# {"ok":false,"error_code":404,"description":"Not Found"}

发送测试消息到 Telegram bot,确认推送功能恢复正常。

涉及的文件

文件 说明
/etc/ssl/certs/telegram-proxy.crt 自签名证书(公钥)
/etc/ssl/private/telegram-proxy.key 私钥
/usr/local/share/ca-certificates/telegram-proxy.crt 系统 CA 信任源
/etc/nginx/sites-available/telegram-proxy nginx 反代配置
/etc/nginx/sites-enabled/telegram-proxy 软链接(启用)
/etc/hosts 添加 127.0.0.1 api.telegram.org
~/.config/systemd/user/openclaw-gateway.service 添加 NODE_EXTRA_CA_CERTS 环境变量

方案对比

方案 优点 缺点 适用场景
Cloudflare Worker + 插件 配置简单,无需修改系统 插件失效后不可用 OpenClaw v2026.3.11 之前
本地 nginx 反代 不依赖插件,系统层透明拦截 需要修改 /etc/hosts 和 systemd 配置 OpenClaw v2026.3.11 及之后

故障排查

  • Worker 代理不通curl https://telegram.chuchu-z.com/health 检查 Worker 状态
  • 本地 nginx 不通:检查 nginx 日志 /var/log/nginx/telegram-proxy.error.log
  • 证书不信任:确认 NODE_EXTRA_CA_CERTS 环境变量已生效(systemctl --user show-environment openclaw-gateway.service | grep NODE_EXTRA_CA_CERTS
  • systemd 重启无效:确认使用 systemctl --user restart,而非 openclaw gateway restart
  • 429 错误:Cloudflare Workers 免费版有请求限额(10万次/天),超限需升级