镜像自 github.com/Chieko3020/qqbot
- Python 100%
- 入站验签:此前 ed25519 只用于应答 op=13,从未校验入站请求,任何人 伪造 webhook 即可调用全部指令(含 MC 管理指令与 LLM 额度) - 内容过滤分层:语义敏感词移出源码改为可配,保留确定性技术模式 - 输出侧审核:DeepSeek 无 moderation 端点,用一次 flash 判别调用实现, 默认 fail-open |
||
|---|---|---|
| src | ||
| tests | ||
| .env.example | ||
| .gitignore | ||
| README.md | ||
QQ Bot — 基于 Webhook 的 QQ 机器人
- QQ 官方 Webhook 机器人,运行在 127.0.0.1:4001(nginx 反代),接收消息并确定性强过滤后回复
- 模块化设计:core/chat/mc 包结构
- 内置 MC 服务器监控(状态/性能/TPS/内存/日志/备份)+ RCON + 自动备份
- 支持 Luna AI 聊天(DeepSeek,通过 ai-gateway),内联键盘交互
- 支持音乐搜索播放(Enhanced API + 语音上传)
- 安全:入站 ed25519 验签(防伪造事件)+ msg_id 去重 + 滑动窗口频控 + 分层输入过滤 + 50K 日配额
- 凭据全部通过环境变量注入(systemd EnvironmentFile → .env),源码零硬编码
- 开发环境:Python 3.12
项目简介
QQ Bot 后端服务。接收 QQ 官方 Webhook 回调,先做 ed25519 入站验签,再根据白名单指令分发到对应处理函数。MC 监控通过 RCON + systemctl 实现,零外部脚本依赖。聊天和音乐功能通过本地 API 转发。
技术栈
| 组件 | 选型 |
|---|---|
| 运行时 | Python 3.12 |
| HTTP 服务 | http.server (标准库) |
| 签名验证 | cryptography (ed25519) |
| RCON | socket + struct (标准库) |
| LLM | DeepSeek v4-flash (通过 ai-gateway) |
项目结构
qqbot/
├── src/
│ ├── main.py # 入口:HTTP Handler + 告警线程
│ ├── daily_counter.py # 日配额计数器
│ ├── core/
│ │ ├── config.py # 配置 / 日志 / 频控 / _mc_cfg
│ │ ├── qq_client.py # QQ Bot API (token/消息/语音)
│ │ ├── signature.py # 入站 Ed25519 验签 / op=13 应答
│ │ ├── security.py # 分层输入过滤 / URL 移除
│ │ └── handlers.py # 指令分发
│ ├── chat/
│ │ ├── luna.py # AI 聊天
│ │ └── music.py # 音乐搜索播放
│ └── mc/
│ └── server.py # MC 监控 / RCON / 备份
├── tests/
│ └── test_inbound_signature.py # 入站验签黑盒验收(7 项)
├── config/
│ └── bot_config.json # 指令开关 + MC 服务器配置(不入库)
├── .env.example # 环境变量模板,复制为 .env 填入凭据
├── README.md
└── .gitignore
安全模型
入口真实性是唯一真正有效的一层,其余为纵深防御:
① 入站验签 Ed25519(X-Signature-Ed25519, event_ts + raw_body) ← 缺它则任何人可伪造事件
② 输入过滤 CORE_PATTERNS:提示注入 / 危险命令 / 脚本注入(确定性模式)
③ 语义敏感词 默认空,经 QQBOT_SEMANTIC_PATTERNS 或 config 注入(可选兜底)
④ 输出审核 LLM as judge:回复发出前过一次 flash 判别(可关,fail-open)
⑤ 成本封顶 滑动窗口频控 + 50K tokens 日配额
⑥ 传输边界 仅监听 127.0.0.1,由 nginx 终结 TLS
要点:
- 验签必须用原始 body 字节,不能
json.dumps重新序列化。 - 私钥由 AppSecret 确定性派生(重复拼接至 ≥32 字节取前 32 字节),与官方文档 golang 示例一致。
op=13(回调地址验证)是入站请求但不带签名头,故放在验签之前处理。- 时间戳参与签名并设容差(默认 300s),超窗拒绝以抗重放。
- 验签失败一律
401丢弃并记 WARN,不进入任何 handler。 - ④ 输出审核:DeepSeek 没有 moderation 端点(只有服务端内联过滤,违规返回 400),
因此用一次 flash 判别调用实现。默认 fail-open —— 审核不可用时不阻塞聊天。
⚠️ 不要指向本机 ai-gateway:它是语义缓存网关,会把"相似" prompt 判为同一请求
并复用答案,实测出现过"违规样本命中缓存的 allow=true 而放行"。需要走网关时请单起
一个
cache.enabled=false的实例。 - 正则黑名单拦不住变形/谐音/多轮绕过,内容合规不要只靠它;政治类词不进源码。
编译和运行
pip install cryptography
cp .env.example .env # 填入 QQ_APP_ID / QQ_APP_SECRET
python -m src.main
# Listening on http://127.0.0.1:4001
本地跑入站验签验收(自起副本于 4101 端口,不碰生产):
python3 tests/test_inbound_signature.py # 期望 7/7 passed
生产环境通过 systemd 启动(EnvironmentFile 指向 .env),nginx 将 Webhook 回调反代到 4001 端口。
配置
环境变量(.env)
| 变量 | 必填 | 说明 |
|---|---|---|
QQ_APP_ID |
是 | QQ 开放平台机器人 AppID |
QQ_APP_SECRET |
是 | QQ 开放平台机器人 AppSecret(入站验签派生密钥 + 换取 access_token) |
DEEPSEEK_KEY |
否 | DeepSeek 访问密钥(走 ai-gateway 时可留空) |
LISTEN_HOST |
否 | 监听地址,默认 127.0.0.1 |
LISTEN_PORT |
否 | 监听端口,默认 4001(nginx 反代指向) |
DEEPSEEK_URL |
否 | LLM 上游地址,默认 http://127.0.0.1:4000/v1/chat/completions |
QQBOT_VERIFY_SIGNATURE |
否 | 入站验签开关,默认 1。置 0 会使任何人都能伪造事件 |
QQBOT_SIGNATURE_TOLERANCE_SEC |
否 | 时间戳容差秒数,默认 300 |
QQBOT_SEMANTIC_PATTERNS |
否 | 语义敏感词兜底,逗号分隔,默认空 |
MODERATION_ENABLED |
否 | 输出审核开关,默认 1 |
MODERATION_URL |
否 | 审核端点,默认官方 chat/completions。勿指向 ai-gateway |
MODERATION_MODEL |
否 | 审核模型,默认 deepseek-flash |
MODERATION_TIMEOUT_SEC |
否 | 审核超时秒数,默认 8 |
MODERATION_MAX_TOKENS |
否 | 审核输出上限,默认 256(推理模型需留余量) |
MODERATION_FAIL_MODE |
否 | open(默认,放行)或 closed(拦截) |
MODERATION_KEY |
否 | 审核专用 key,默认复用 DEEPSEEK_KEY |
⚠ 凭据只从环境变量读取,源码不包含任何密钥。.env 已被 .gitignore 忽略,严禁提交。
config/bot_config.json
{
"commands": { "状态": true, "luna": true, ... },
"mc_server": {
"name": "MC Server",
"service_name": "mcserver",
"server_dir": "/home/ubuntu/minecraft",
"rcon_password": ""
}
}
| 字段 | 说明 |
|---|---|
commands.* |
指令开关(true/false) |
mc_server.name |
服务器显示名称 |
mc_server.service_name |
systemd 服务名 |
mc_server.server_dir |
服务器根目录 |
mc_server.rcon_password |
RCON 密码(可选,从 server.properties 自动读取) |
指令
| 指令 | 功能 |
|---|---|
| 状态 / 性能 / TPS | 服务器运行状态 |
| 在线人数 / 内存 | 资源监控 |
| 日志 / 备份 | 日志和备份管理 |
| luna | AI 聊天(例: luna 你好) |
| 音乐 | 音乐搜索和播放 |
| 帮助 | 完整菜单 |