主要修复: - 修复批量上传闭包陷阱,防止文件丢失 - 添加 fileName 参数传递原始文件名,保留正确扩展名 - 添加取消检查回调,改进批量上传取消功能 其他改进: - 优化搜索功能和管理后台 - 添加 FRP 故障诊断文档 - 更新环境验证和网络检测
8.5 KiB
8.5 KiB
FRP 穿透服务故障诊断与修复报告
日期: 2026-01-30
问题: 网站频繁无法访问,FRP 穿透服务不稳定
问题概述
素材库网站通过 FRP 穿透服务对外提供访问,但近期频繁出现无法访问的情况,约 2 天崩溃一次。
系统架构
┌─────────────────────┐ ┌──────────────────────┐ ┌─────────────┐
│ 生产服务器 │ │ FRP 服务器 │ │ 公网用户 │
│ 192.168.58.20 │────→│ 180.97.221.140 │←────│ │
│ - 素材库 Docker │ │ - frps 监听 7000 │ │ 访问 :2320 │
│ - frpc 客户端 │ │ - 转发端口 2320 │ └─────────────┘
└─────────────────────┘ └──────────────────────┘
诊断过程
问题1:FRP 配置冲突
现象: 服务器日志出现大量 timeout trying to get work connection 错误
排查:
cat /etc/frp/frpc.toml
发现: 配置文件中同时启用了互斥的选项:
[transport]
tcpMux = true # TCP 多路复用(单连接)
poolCount = 50 # 连接池(50个连接)
原因:
tcpMux = true表示使用单个多路复用连接poolCount = 50表示使用 50 个独立连接- 这两个选项互斥,导致连接无法正常建立
修复:
[transport]
tcpMux = true
tcpMuxKeepaliveInterval = 10
# 移除 poolCount
问题2:未知客户端 bi2 占用资源
现象: FRP 服务器上发现多个未知代理
排查:
curl -s -u admin:密码 http://127.0.0.1:7500/api/proxy/tcp
发现:
| 代理名称 | 远程端口 | 来源 IP | 说明 |
|---|---|---|---|
| youyidian-3d | 2320 | 58.216.227.194 | ✅ 正常(素材库) |
| bi2-ssh | 6000 | 36.153.91.234 | ❓ 未知客户端 |
| bi2-http-80 | 8000 | 36.153.91.234 | ❓ 未知客户端 |
| bi2-http-8080 | 8080 | 36.153.91.234 | ❓ 未知客户端 |
| bi2-mysql | 6002 | 36.153.91.234 | ❓ 未知客户端 |
bi2 客户端信息:
- IP: 36.153.91.234
- 位置: 中国重庆市(中国移动)
- 首次连接: 2025-11-17
- 状态: 未经授权使用了 FRP Token
问题3:bi2-ssh 被暴力扫描攻击
现象: bi2-ssh 端口 6000 被全球 SSH 扫描机器人攻击
攻击统计 (2026-01-30):
| 攻击源 IP | 连接次数 |
|---|---|
| 209.38.230.85 | 18,976 |
| 193.32.162.46 | 9,882 |
| 193.32.162.101 | 5,629 |
| 94.156.152.194 | 4,435 |
| 45.148.10.66 | 2,904 |
| 45.148.10.195 | 1,294 |
| 总计 | 43,895 |
影响:
- 攻击流量消耗 FRP 服务器连接资源
- 导致素材库 (youyidian-3d) 无法获取工作连接
- 出现
failed to get work connection: control is closed错误
解决方案
方案1:修复 FRP 配置
服务器端 /etc/frp/frps.toml:
bindAddr = "0.0.0.0"
bindPort = 7000
auth.method = "token"
auth.token = "YYD3D_FRP_20260130_edd41d728bfd59a5"
[transport]
tcpMux = true
tcpMuxKeepaliveInterval = 60
tcpKeepalive = 30
heartbeatTimeout = 90
log.to = "/var/log/frps.log"
log.level = "info"
log.maxDays = 7
客户端 /etc/frp/frpc.toml:
serverAddr = "180.97.221.140"
serverPort = 7000
[auth]
method = "token"
token = "YYD3D_FRP_20260130_edd41d728bfd59a5"
[transport]
tcpMux = true
tcpMuxKeepaliveInterval = 10
heartbeatInterval = 10
heartbeatTimeout = 30
[[proxies]]
name = "youyidian-3d"
type = "tcp"
localIP = "127.0.0.1"
localPort = 4320
remotePort = 2320
[proxies.healthCheck]
type = "tcp"
intervalSeconds = 15
maxFailed = 3
timeoutSeconds = 5
方案2:封禁攻击 IP
在 FRP 服务器上使用 firewalld 封禁主要攻击源:
# 封禁攻击 IP
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=209.38.230.85 drop"
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=193.32.162.46 drop"
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=193.32.162.101 drop"
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=94.156.152.194 drop"
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=45.148.10.66 drop"
firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=45.148.10.195 drop"
firewall-cmd --reload
方案3:更换 FRP Token
踢掉未授权的 bi2 客户端,更换 Token 防止重连:
旧 Token: LiuYunKu_NAS_2024_SecureToken (已泄露/被滥用)
新 Token: YYD3D_FRP_20260130_edd41d728bfd59a5
更换步骤:
- 更新 FRP 服务器配置
- 更新生产服务器 frpc 配置
- 先重启 frps,再重启 frpc
方案4:部署自动监控脚本
创建 /root/scripts/frp-monitor.sh,每分钟检测公网是否可访问:
#!/bin/bash
# FRP 穿透服务健康监控脚本
# 每分钟检测公网是否可访问,连续失败3次自动重启
LOG="/var/log/frp-monitor.log"
FAIL_COUNT_FILE="/tmp/frp_fail_count"
MAX_FAILS=3
log() {
echo "[$(date "+%Y-%m-%d %H:%M:%S")] $1" >> "$LOG"
}
# 核心检测:公网端口能不能真正访问
check_public_access() {
timeout 5 curl -sf "http://180.97.221.140:2320/" > /dev/null 2>&1
}
# 读取失败计数
FAIL_COUNT=$(cat "$FAIL_COUNT_FILE" 2>/dev/null || echo 0)
if check_public_access; then
# 访问正常
if [ "$FAIL_COUNT" -gt 0 ]; then
log "✅ 服务恢复正常,重置失败计数"
fi
echo 0 > "$FAIL_COUNT_FILE"
else
# 访问失败
FAIL_COUNT=$((FAIL_COUNT + 1))
echo "$FAIL_COUNT" > "$FAIL_COUNT_FILE"
log "⚠️ 公网访问检测失败 ($FAIL_COUNT/$MAX_FAILS)"
# 连续失败达到阈值,强制重启
if [ "$FAIL_COUNT" -ge "$MAX_FAILS" ]; then
log "🚨 连续失败 $MAX_FAILS 次,强制重启 FRP"
# 强制杀掉所有 frpc 进程(清理连接池)
killall -9 frpc 2>/dev/null
sleep 2
# 重启 systemd 服务
systemctl start frpc.service
sleep 5
# 验证是否恢复
if check_public_access; then
log "✅ FRP 重启成功,服务已恢复"
else
log "❌ FRP 重启后仍然失败,可能是服务器端问题"
fi
# 重置计数
echo 0 > "$FAIL_COUNT_FILE"
fi
fi
cron 定时任务:
* * * * * /bin/bash /root/scripts/frp-monitor.sh
当前状态 (2026-01-30 11:31)
| 项目 | 状态 |
|---|---|
| FRP 服务器 | ✅ 运行正常 |
| 素材库穿透 (youyidian-3d) | ✅ 在线 |
| bi2 客户端 | ✅ 已断开(Token 已更换) |
| 攻击 IP | ✅ 已封禁 6 个主要来源 |
| 监控脚本 | ✅ 已部署(每分钟检测) |
| 公网访问 | ✅ 正常 |
重要配置信息
SSH 连接信息
| 服务器 | 别名 | 端口 | 用途 |
|---|---|---|---|
| 180.97.221.140 | frp | 9527 | FRP 穿透服务器 |
| 192.168.58.20 | prod | 22 | 生产服务器(TrueNAS) |
FRP Token
当前有效 Token: YYD3D_FRP_20260130_edd41d728bfd59a5
⚠️ 安全提醒:
- Token 等同于"入场券",知道就能连接
- 不要在代码仓库、公开文档中暴露
- 定期检查 FRP Dashboard 是否有未知客户端
监控日志位置
| 日志 | 路径 | 说明 |
|---|---|---|
| FRP 服务器日志 | /var/log/frps.log |
frps 运行日志 |
| FRP 客户端日志 | /root/frp/frpc.log |
frpc 运行日志 |
| 监控脚本日志 | /var/log/frp-monitor.log |
健康检查日志 |
后续建议
- 定期检查 FRP Dashboard: 访问
http://127.0.0.1:7500(需在服务器本地或 SSH 隧道) - 定期更换 Token: 建议每 3-6 个月更换一次
- 监控告警: 可添加钉钉 Webhook 实现告警通知
- 考虑 IP 白名单: 在 frps 配置中限制只允许特定 IP 连接
附录:常用命令
# 查看 FRP 服务器状态
ssh -p 9527 frp "systemctl status frps"
# 查看 FRP 客户端状态
ssh prod "systemctl status frpc"
# 查看当前连接的客户端
ssh -p 9527 frp "ss -tnp | grep :7000"
# 查看代理状态
ssh -p 9527 frp "curl -s -u admin:Admin@frp2024 http://127.0.0.1:7500/api/proxy/tcp"
# 测试公网访问
curl -I http://180.97.221.140:2320/
# 查看监控日志
ssh prod "tail -50 /var/log/frp-monitor.log"
# 手动重启 FRP
ssh -p 9527 frp "systemctl restart frps"
ssh prod "systemctl restart frpc"