gongxiangp2/docs/FRP穿透服务故障诊断与修复-20260130.md
chenpei 752b7bf999 fix: 修复批量上传和视频扩展名问题
主要修复:

- 修复批量上传闭包陷阱,防止文件丢失

- 添加 fileName 参数传递原始文件名,保留正确扩展名

- 添加取消检查回调,改进批量上传取消功能

其他改进:

- 优化搜索功能和管理后台

- 添加 FRP 故障诊断文档

- 更新环境验证和网络检测
2026-02-03 11:12:50 +08:00

8.5 KiB
Raw Blame History

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

更换步骤:

  1. 更新 FRP 服务器配置
  2. 更新生产服务器 frpc 配置
  3. 先重启 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 健康检查日志

后续建议

  1. 定期检查 FRP Dashboard: 访问 http://127.0.0.1:7500(需在服务器本地或 SSH 隧道)
  2. 定期更换 Token: 建议每 3-6 个月更换一次
  3. 监控告警: 可添加钉钉 Webhook 实现告警通知
  4. 考虑 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"