从 499 到 200:解决 Telegram Webhook 经过 WireGuard 隧道的超时与黑洞问题
2026年1月22日 · 610 字 · 2 分钟
问题现象
在通过 Nginx 转发 Telegram Webhook 到家庭内部服务器(通过 WireGuard 连接)时,遇到了以下奇怪的现象:
- Nginx 日志频繁报错:出现大量 499 Client Closed Request 和 504 Gateway Timeout。
- Curl 测试具有欺骗性:使用简单的 curl 发送测试小包时响应极快,但真实的 Telegram 请求却始终无法到达后端 Python 程序。
- Webhook 积压:使用 getWebhookInfo 接口查询发现 pending_update_count 持续增加。
深度分析:MTU 黑洞
经过排查,问题的根源在于 MTU (Maximum Transmission Unit) 不匹配导致的“黑洞效应”。
- WireGuard 限制:WireGuard 协议由于增加了封装头,默认 MTU 通常为 1420。
- 数据包膨胀:Telegram 的 POST 请求数据包加上 HTTP Header 后,很容易超过 1420 字节。
- 静默丢弃:由于 TCP 请求通常带有 DF (Don’t Fragment) 标志,当 Nginx 尝试转发大包进入 wg0 接口时,数据包被内核直接丢弃。
解决方案
1. 调整网卡 MTU (服务端与客户端)
将 WireGuard 网卡的 MTU 降低到 1280。这是最保险的值,预留了足够的空间给隧道封装。
在 wg0.conf 的 [Interface] 部分添加:
[Interface]
MTU = 1280
PostUp = ip link set dev %i mtu 1280
2. Nginx 配置优化
确保 Webhook 路径不被全局的 deny 规则拦截,并开启针对超时的优化参数。
location = /tg-webhook/your-uuid-path {
allow all;
proxy_pass http://10.8.0.5:9527;
proxy_ignore_client_abort on;
proxy_read_timeout 90s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
3. 重置 Webhook 状态
网络链路修复后,必须重置 Webhook 以清空积压的错误。
# 第一步:删除 Webhook 并清空积压
curl -X POST https://api.telegram.org/bot<TOKEN>/deleteWebhook?drop_pending_updates=true
# 第二步:重新绑定 Webhook 地址
curl -X POST https://api.telegram.org/bot<TOKEN>/setWebhook \
-d "url=https://https://yourdomain.com/tg-webhook/your-uuid-path" \
-d "drop_pending_updates=true"
验证方法
在 Nginx 服务器上执行禁止分片的大包 Ping 测试:
# 如果 mtu 已锁定为 1280,发送 1400 字节负载应提示 message too long
ping -M do -s 1400 10.8.0.5
总结
在公网服务器与私有内网通过隧道连接的架构中,MTU 不一致是导致“小包能过、大包卡死”的元凶。锁定 MTU 并重置 Webhook 连接是解决此类问题的关键。