在当前机器人开发实践中,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机器人。