把安全检查前移到配置阶段:frpguard 的 13 条规则

举报
yd_296806354 发表于 2026/11/06 17:22:43 2026/11/06
【摘要】 把 frp 配置的安全检查前移到写配置的那一刻:13 条静态规则、可解释的扣分模型,以及为什么坚持不联网。

我这台 Windows 机器需要偶尔从外面连回来。搭 frp 的时候翻了一圈中文教程,发现一个规律:绝大多数教程给出的配置都是「能跑通、但不安全」的。

典型长这样:

bindPort = 7000
webServer.addr = "0.0.0.0"

[[proxies]]
type = "tcp"
localPort = 3389
remotePort = 13389

四行里埋了四个雷:没有 auth.token(谁都能把你的 frps 当免费跳板)、管理面板监听 0.0.0.0(面板直接挂公网)、没有 allowPorts(任意端口可被登记)、13389 这个端口号所有教程都在用(扫描器的字典第一条)。

这些问题有个共同点:它们都不影响连通性。配置跑得起来,端口能通,所以你根本不会意识到写错了。等意识到的时候,通常是因为日志里出现了陌生 IP。

于是我把「什么算错」写成规则,做成一个检查器。

frpguard 是什么

一个纯前端页面:把 frps.toml / frpc.toml 粘进去,立刻得到分级风险报告。

零依赖、单文件、无网络请求,双击 index.html 就能用。无网络请求这点很重要——意味着你可以放心粘贴包含真实 token 的配置(虽然我仍然建议先脱敏)。

13 条规则

规则分两个作用域(服务端 / 客户端),四个严重度。

服务端 frps.toml

规则 严重度 检查内容
FRPS_NO_AUTH 严重 没配 auth.token,任何人可把你的 frps 当免费跳板
FRPS_DASHBOARD_PUBLIC 严重 webServer.addr 不是回环地址,管理面板暴露公网
FRPS_WEAK_TOKEN 高危 token 短于 24 字符,可被爆破
FRPS_DASHBOARD_NO_PASS 高危 面板开了端口但没设密码
FRPS_ALLOWPORTS_WIDE 高危 allowPorts 某区间跨度 > 100,等于放行一大片端口
FRPS_ALLOWPORTS_NONE 中危 完全没配 allowPorts,默认允许任意端口
FRPS_ALLOWPORTS_PRIVILEGED 中危 allowPorts 含 < 1024 的低号端口

客户端 frpc.toml

规则 严重度 检查内容
FRPC_NO_TOKEN 严重 没配 token,你以为是连自己的 frps,其实可能连到别人的
FRPC_TUTORIAL_PORT 高危 remotePort 落在教程默认端口集合(13389 / 3389 / 7001 / 8080 / 8000 / 8888 / 9000)
FRPC_RDP_PUBLIC 高危 用 tcp 类型把 3389 映射到公网
FRPC_SECRETKEY_SHORT 高危 stcp / xtcp 的 secretKey 短于 24 字符
FRPC_TLS_OFF 中危 显式写了 transport.tls.enable = false,隧道内容明文
FRPC_NO_STCP 提示 全部代理都是 tcp 类型,没有 stcp / xtcp 备用路径

写规则时最难的不是判「有没有」,而是判「够不够」。比如 token 长度,我定在 24 字符——低于这个数的高熵爆破在常见带宽下是可行的。allowPorts 区间跨度定在 100,是因为真实的 frp 使用场景里,一个人同时需要一百多个连续远端端口的情况极少;跨度大往往意味着「懒得想,直接给一大段」。

评分模型

从 100 分开始扣:

严重度 扣分
严重 −40
高危 −20
中危 −8
提示 −3

结果截断在 0~100,三档配色:≥85 绿、60~84 黄、<60 红。

为什么用硬编码权重而不是加权模型? 因为可解释。用户看到「−40」能立刻知道哪几条最要命;某些评分模型给一个 73.6 分,你没法从分数反推该先改哪里。安全提示的价值在于让人立刻知道下一步做什么,不在于分数本身多精确。

为什么是静态分析

三个理由:

  1. 探测需要目标可达,而且会暴露「有人在扫你」——对一个刚暴露到公网的服务来说,这是额外风险。
  2. 配置文件本身就是风险的来源。上面那四行里没有一个需要「探测」才能发现的问题,全是读文本就能判定的。
  3. 无网络请求 = 可离线使用 = 可粘贴真实配置。这点决定了它到底会不会被真正用起来。一个要求你把配置上传到某台服务器的检查器,没人会粘真实 token 进去。

自己写 TOML 解析器的取舍

为了保持零依赖,我手写了一个 TOML 子集解析器,只支持 frp 配置用到的语法:[[table]]、[table]、key = value、点号嵌套键、多行数组、行内表。

不支持日期字面量、多行字符串、十六进制整数等 TOML 完整特性。这换来 git clone 后无需 npm install、无需构建、双击即用。

这是个明确的取舍:工具的使用成本必须低于它省下的成本。如果为了跑一个检查器要先装 node_modules,那不如不检查。

实测

用两份真实生产配置跑(内容已脱敏,只留结果):

配置 分数 命中
加固后的 frps.toml(本地面板 + 单端口放行 + 32 位 token) 100 无
加固后的 frpc.toml(stcp 备用 + 高位端口 + 仍开一条 tcp RDP) 80 FRPC_RDP_PUBLIC

第二条是我想强调的取舍:即使做了大部分加固,只要还对公网开着 RDP,就仍然扣分。

80 分不是「还凑合」,是「这里有一个必须知道自己承担了什么的选择」。工具的责任是把选择摆到明面上,而不是替用户做决定。

一条只提示、不重罚的规则

FRPC_NO_STCP 只是个「提示」,扣 3 分。

stcp(secret tcp)明显更安全——它不需要在服务端放行远端端口,访问端要用带 secretKey 的 visitor 才能连。但它要求每台访问设备都装 frpc visitor。对「随时随地用手机构一下」的场景,tcp 是理性选择。

工具不该把自己的洁癖强加给使用者。所以这里只提示、不重罚——这也是为什么它的严重度是「提示」而不是「中危」。

局限(说清楚)

  • 只做静态分析,不验证配置能否跑通、不检测端口是否真在监听
  • 规则覆盖的是常见错误,不是完整安全审计
  • 不支持旧版 frpc.ini(只支持 TOML,frp ≥ 0.52)
  • 不检查 [include] 引入的外部文件
  • 不联网核对 frp 版本是否有已知漏洞

一个只查「常见错误」的工具确实不高级。但现实是:绝大多数出事的人不是被高级攻击打穿的,是配置里就写着漏洞。

怎么用

git clone <repo>
cd frpguard

# 直接打开
open index.html        # macOS
start index.html       # Windows
xdg-open index.html    # Linux

页面上有四个样例按钮(加固前后的 frps / frpc 各一份),可以先点着看效果,再粘自己的配置。

如果愿意,也可以把 guard.js 单独拿去用——它是纯逻辑层,不碰 DOM,可以在 Node 里单测:

const { parseToml, run, score } = require("./guard.js");
const findings = run(parseToml(tomlText));
console.log(score(findings), findings.map(f => f.id));

把它挂进 CI,每次改配置自动跑一遍,也就十几行的事。

MIT 许可。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。