Telegram机器人校验请求来源真实性:防止Webhook伪造的完整攻略

在Telegram机器人开发中,Webhook请求的来源验证是保障安全的核心环节。本文深入解析Telegram官方提供的secret_token与固定IP双重校验机制,结合完整代码示例,教你有效拦截伪造请求,确保机器人只响应真实的Telegram服务器。

阅读提示涉及账号和安全设置时,请边阅读边核对当前设备界面。

在当前机器人开发实践中,Webhook已经成为接收Telegram消息最常用的方式。然而,Webhook端点暴露在公网,任何人都可能向你的服务器发送伪造的请求。如果机器人无法准确辨别请求是否来自Telegram官方服务器,就可能导致数据泄露、权限滥用甚至机器被控制等严重后果。本文将以Telegram官方API为基础,详细介绍校验请求来源真实性的两种核心方法,并给出可直接落地的代码示例。

理解Telegram Webhook请求机制

Telegram机器人通过setWebhook方法将更新推送到你指定的HTTPS端点。当用户发送消息、触发命令或按钮点击时,Telegram服务器会向该端点发送一个HTTP POST请求,请求体为Update对象。为了保证这个请求确实来自Telegram,官方提供了两类标准校验手段:1)在设置Webhook时附带的secret_token参数;2)Telegram服务器的固定IP地址。此外,你还可以在业务层增加额外的逻辑验证,如确认更新中chat.id等字段是否符合预期。

Telegram官方提供的验证机制

1. secret_token——第一道密码

通过setWebhook方法可以传递一个可选的secret_token字符串。Telegram在发送请求时会将该token放入HTTP头字段X-Telegram-Bot-Api-Secret-Token中。你的服务器只需对比此头字段的值是否与配置时一致,即可过滤掉大多数伪造请求。

2. 固定IP地址——第二道防火墙

Telegram服务器有一个默认IP段(通常为149.154.167.220和149.154.175.50等),你可以从官方获取最新列表。在服务器防火墙或应用层限制只允许这些IP访问Webhook端点,能大幅提高安全性。注意,Telegram的IP段可能变化,建议定期刷新。

实现请求来源校验的完整步骤

下面是一个基于Python Flask的Webhook接收示例,将secret_token校验和IP白名单校验结合到实际操作中。

import os
from flask import Flask, request, abort

app = Flask(__name__)

# 在setWebhook时设置的secret_token
SECRET_TOKEN = os.getenv('BOT_SECRET_TOKEN')
# Telegram官方IP段(可动态获取)
ALLOWED_IPS = {'149.154.167.220', '149.154.175.50'}

@app.route('/webhook', methods=['POST'])
def webhook():
    # 第二步:校验IP地址
    if request.remote_addr not in ALLOWED_IPS:
        abort(403)
    # 第一步:校验secret_token
    token = request.headers.get('X-Telegram-Bot-Api-Secret-Token')
    if token != SECRET_TOKEN:
        abort(403)
    # 通过校验,处理更新
    update = request.get_json()
    print(update)
    return 'OK'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8443, ssl_context=('cert.pem', 'key.pem'))

设置Webhook时携带secret_token

使用Telegram Bot API调用setWebhook方法时,添加secret_token参数。例如使用curl:

curl -F "url=https://yourdomain.com/webhook" -F "secret_token=your_random_token" https://api.telegram.org/bot<BOT_TOKEN>/setWebhook

建议用强随机字符串作为secret_token,并定期更换。

二次验证:业务层的校验策略

即使使用了上述两种官方推荐方法,你仍可在业务层增加额外校验,例如检查update对象中chat.id是否属于你期望的用户或群组,或者检查更新ID的连续性。但请注意,Telegram的update_id并非严格递增,可能存在间隙,不能作为严格顺序校验,只能用于简单去重。你也可以验证消息中的bot是否与你的机器人用户名匹配,但这意义有限,因为伪造者可能无法绕过前两层验证。

常见错误与注意事项

1. 忽略请求体大小限制:Telegram允许Webhook请求体最大为50MB,如果你需要接收媒体文件,务必确认服务器配置支持,否则会影响响应。
2. 没有启用HTTPS:Telegram要求Webhook必须使用HTTPS,且证书必须受信任。自签名证书需在setWebhook时提供证书文件,但生产环境建议使用正规证书。
3. 硬编码IP或token安全风险:不要把secret_token和IP白名单写死在前端代码或公开仓库中,应使用环境变量或密钥管理服务。
4. 不处理异常请求:未通过校验的请求应直接返回403,而不是返回200,否则Telegram会误认为请求已处理,导致重试机制异常。

总结

校验请求来源是Telegram机器人生产级部署的必备项。通过secret_token与IP白名单的双重验证,你几乎可以完全阻止伪造的Webhook请求。再辅以业务层的过滤逻辑,机器人将运行在非常安全的环境中。在实际项目中,你还应该结合监控日志、限流等机制,持续加固安全防线。希望本文能帮助你构建出更安全、更可靠的Telegram机器人。

FAQ

下载与安装

常见问题

Telegram Webhook的secret_token在哪里获取?

secret_token并不是预先分配的,而是在调用setWebhook方法时由开发者自行生成并传入。你可以使用任意安全的随机字符串,然后将其保存在服务器环境中。

如何确定Telegram服务器的IP地址?

Telegram官方提供了公开的IP地址段,主要用于Webhook和MTProto协议。你可以从Telegram帮助中心或开发者文档获取最新列表,并定期检查更新。目前常用IP包括149.154.167.220和149.154.175.50。

如果只使用secret_token校验是否足够?

secret_token能过滤大多数伪造请求,但如果攻击者能够窃取token(例如通过日志泄露),仍可能绕过。因此建议将IP白名单作为补充,双重校验会更安全。

Webhook请求校验失败时,应该返回什么状态码?

如果校验失败,应返回403 Forbidden。这样Telegram客户端会识别为失败,并根据错误类型决定是否重试。返回值200会被认为是成功,导致本次更新被标记为已处理。