- 「公网服务端」新增 Nginx 启停控制(Agent 0.15.2,停止带二次确认) - frps 启动失败不再误报成功,并增强启动诊断 - frps vhost 端口禁止 80/443,避免与 VPS 上 Nginx 冲突 - 旧服务端配置的 tcp_mux / login_fail_exit 默认值补齐 - 新增安全审查、页面布局方案与场景操作文档
14 KiB
公网服务端「添加 / 编辑」弹窗表单合理性分析
分析对象:
F:\Fonu-main\havline\web\src\views\AgentView.vue中的服务端弹窗(showServerModal) 重点:「远程管理」标签(serverFormTab === 'remote',模板 464–540 行) 性质:静态代码审查(未运行、未修改),用于后续评审与改进。 结论先行:整体结构清晰、密文回显与插件提示较完善,但**「远程管理」标签的帮助栏与标签页不匹配、表单缺少任何校验、enabled字段无 UI 入口**,属于需要优先修复的合理性问题。
一、分析对象与背景
- 该弹窗同时用于「添加服务端」和「编辑服务端」(
openServerModal,1407 行),标题随editingServer切换。 - 表单分为三个标签页(tabbar,404–406 行):
basic基础配置(410 行起):名称/地址/端口/认证(含 OIDC)/描述。advanced高级配置(542 行起):frpc 日志级别、传输协议、TLS、连接调优。remote远程管理(464 行起):frps 服务端参数、管理接口、公网 Agent 接入。
- 三块面板通过
v-show切换,共用一个<n-form>(409 行)和底部单个「保存」按钮(saveServer,1603 行)。 - 本次重点分析的「远程管理」标签包含 4 个区块:
frps vhost 与域名反代(466–491)TCP/UDP 端口分配(493–500)frps 管理接口(502–521)公网 Agent 管理(523–540)
二、表单整体结构观察
| 观察点 | 现状 | 合理性判断 |
|---|---|---|
| 标签顺序 | tabbar 顺序为 基础 / 高级 / 远程;DOM 面板顺序为 basic / remote / advanced(v-show 不影响显示,但维护易错位) |
基本可用,但 DOM 与 tab 顺序不一致,改动时易踩坑 |
| 表单校验 | <n-form label-placement="top" class="proxy-modal__pane" @submit.prevent="saveServer">,无 :model、无 :rules |
⚠️ 偏弱:required 仅显示星号,不产生校验 |
| 提交按钮 | 三页共用底部「保存」,只写数据库 | ⚠️ 与"远端需下发/重启才生效"的语义割裂 |
| 密文字段 | Token / OIDC Secret / Dashboard 密码 / SSH 密码密钥 / Agent Token 统一用 ConfiguredSecretField |
✅ 较好,编辑留空保持不变 |
| 危险操作 | 「清除管理密码」「清除证书/密钥/CA」均有独立按钮 | ✅ 较好 |
三、「远程管理」标签逐区块分析
3.1 frps vhost 与域名反代(466–491 行)
字段:HTTP 回源端口 vhost_http_port、HTTPS 回源端口 vhost_https_port、子域名根 sub_domain_host、tcpmux 监听端口 tcpmux_http_connect_port、自定义 404 页面 custom_404_page、强制 TLS tls_force、frps 写文件日志 frps_log_to_file、日志保留天数 frps_log_max_days。
合理之处:
- 对 80/443 冲突有专门告警(469 行),并解释"应由 Nginx 占用"。
- 提示了"修改后需下发并重启、重新部署规则"的必要性。
问题:
- 本质是 frps 服务端配置,却归入"远程管理":
vhostHTTPPort/vhostHTTPSPort/subDomainHost/tcpmux是 frps.toml 的服务端参数,与"是否远程管理"无关;tls_force、frps_log_*同样是 frps 服务端行为。标签命名与内容职责不匹配。 - 端口冲突无校验:只对
==80/443告警,未校验vhost_http_port与vhost_https_port、server_port(默认 7000)、dashboard_port、tcpmux_http_connect_port之间的重复。 tls_force与高级标签的tls_enabled无联动:类型注释已写明"frpc 必须开 transport.tls.enable"(types.ts 405 行),但两字段分属不同标签、互不校验,配置成tls_force=true+tls_enabled=false时连接会失败。- 默认值呈现不一致:placeholder 写"默认 8080/8443",但
defaultServerOptions()(1291 行)不包含vhost_http_port/vhost_https_port/sub_domain_host/tcpmux_http_connect_port/custom_404_page/tls_force/frps_log_to_file/frps_log_max_days/allow_ports/max_ports_per_client,新增服务端时这些字段为undefined。 custom_404_page无格式/存在性校验(VPS 本地路径只能靠后端报错)。sub_domain_host的依赖关系未提示校验(规则用 subdomain 时才生效,属跨模块依赖)。
3.2 TCP/UDP 端口分配(493–500 行)
字段:allow_ports(端口白名单)、max_ports_per_client。
- 说明文字较准确(区分 vhost 回源端口不在此限制、需云安全组与主机防火墙放行)。
- 问题:
allow_ports为纯文本,格式(6000,6005-6010)无前端校验,错误只会在后端/下发阶段暴露;max_ports_per_client允许 0(不限)与n-input-number默认空值语义需要靠文案理解。
3.3 frps 管理接口(502–521 行)
字段:dashboard_addr、dashboard_port、dashboard_user、dashboard_password(密文)+「清除管理密码」。
- 说明清楚地区分了"仅用于 Havline 拉取流量,与连接认证无关"。
- 问题:
- 成对字段无关联校验:只填
dashboard_port不填dashboard_addr(或反之)时无提示,仅静默不采集。 - 该区块与「远程管理」标签主题(Agent/远程)关联度弱,它其实是 frps 的可观测性配置。
- 成对字段无关联校验:只填
3.4 公网 Agent 管理(523–540 行)
字段:agent_url、agent_token、ssh_host、ssh_port、ssh_user、ssh_auth(key/password)、ssh_secret、「启用 Agent 日常管理」mgmt_enabled;编辑且已配置时额外显示「测试连接 / 下发 frps 配置 / 查看服务端详情」。
合理之处:
- 明确"首次安装/升级需 SSH,日常走 Agent API";SSH 仅用于生命周期与隧道。
- 三个快捷操作按钮对编辑态友好。
问题:
agent_urlplaceholder 与实际安全模型冲突:示例http://vps.example.com:7700(525 行)鼓励公网明文 HTTP,而页面自身文案强调"不会默认暴露公网 7700"(244 行),且默认推荐 SSH 隧道 / HTTPS 固定。示例具有误导性。- SSH 字段无完整性校验:填了
ssh_host但缺ssh_user/ssh_secret、或ssh_auth=key却粘贴密码时,无前端提示,失败延后到安装阶段。 ssh_secret文案不随ssh_auth切换:始终为"SSH 密码/私钥",用户需自行判断格式。mgmt_enabled=true但agent_url为空的冲突组合无提示。- 弹窗内「下发 frps 配置」(539 行)用的是已保存数据:
pushAgentConfig(editingServer)以服务端 id 触发,后端按已存库配置生成;若用户在同一弹窗内刚改了 vhost/端口(尚未保存),点它下发的是旧配置,与"修改后需下发"的预期相悖。
四、合理性问题清单(按优先级)
P0(建议优先修复)
-
「远程管理」帮助栏串台(明确缺陷)
serverHelpItems(1307 行)只对advanced分支;remote落入默认分支,展示的是基础配置的说明(基本信息/认证方式/frps 管理接口/描述)。- 帮助栏标题
serverFormTab === 'basic' ? '配置说明' : '高级配置说明'(601 行):remote标签显示"高级配置说明"。 serverHelpTip(1323 行)对remote返回通用兜底文案。- 结果:用户在「远程管理」标签看到的右侧说明与其所在标签完全不符。
-
表单无任何校验(409、1603 行)
- 无
:model/:rules;saveServer直接提交。缺:名称/主机地址必填、端口有效、创建时 token 认证令牌为空、dashboard 成对、SSH 完整性、端口冲突等。
- 无
-
enabled字段无 UI 入口serverForm.enabled在 reactive(1300 行)与 payload(1611 行)中存在,但三个标签页均无绑定输入,添加/编辑恒为true。用户无法在表单中停用服务端。
P1(影响体验/正确性)
- 跨字段、跨标签冲突无校验(端口重复;
tls_force↔tls_enabled;sub_domain_host依赖)。 - 保存与"下发/重启"语义混用;弹窗内「下发 frps 配置」可能下发未保存前的旧配置。
- 过时文案:多处提示"在「内网穿透」页服务端表单…填写"(244、310 行),但服务端表单已于 2026-09-24 迁入本页(AgentView),指引指向错误。
agent_url示例鼓励公网明文 HTTP,与页面安全模型矛盾。dashboard_port/tcpmux的 0/空语义依赖文案,无强制。
P2(可优化)
- 「远程管理」混合了 frps 服务端参数、管理接口、Agent 接入三类关注点,标签命名与内容不符;建议拆分或重命名为"服务端与 Agent"。
defaultServerOptions()未覆盖远程标签字段,新增时undefined,n-switch(tls_force/frps_log_to_file)可能收到undefined。- 高级标签用 collapse 收纳密集字段,远程标签 4 区块 ~18 字段平铺,密度管理不一致。
frps_log_max_days(远程)与log_max_days(高级/frpc)命名相近、分属不同标签,易混。custom_404_page、allow_ports无格式校验。
五、「远程管理」字段级对照表
| 字段(绑定) | 标签 | 控件 | 主要问题 | 建议 |
|---|---|---|---|---|
options.vhost_http_port |
HTTP 回源端口 | number | 端口冲突未校验;无默认值 | 与相关端口做唯一性校验;补充默认值 |
options.vhost_https_port |
HTTPS 回源端口 | number | 同上;tls_force 联动缺失 |
同上;联动 TLS 校验 |
options.sub_domain_host |
子域名根 | text | 依赖关系未提示 | 增加格式校验与说明 |
options.tcpmux_http_connect_port |
tcpmux 监听端口 | number | "存在 tcpmux 规则时必填"无强制 | 按规则类型动态必填 |
options.custom_404_page |
自定义 404 页面 | text | 无路径校验 | 格式提示/后端预校验 |
options.tls_force |
强制 TLS | switch | 与 frpc tls_enabled 无联动 |
跨标签联动校验/提示 |
options.frps_log_to_file |
frps 写文件日志 | switch | 默认 undefined | 纳入 defaultServerOptions |
options.frps_log_max_days |
日志保留天数 | number | 与 frpc log_max_days 易混 |
明确命名/分组 |
options.allow_ports |
端口白名单 | text | 无格式校验 | 正则校验 \d+(-\d+)?(,\d+(-\d+)?)* |
options.max_ports_per_client |
每客户端端口上限 | number | 0=不限需文案 | 保留,补 hint |
options.dashboard_addr |
管理地址 | text | 与 port 不成对校验 | 成对校验 |
options.dashboard_port |
管理端口 | number | 同上 | 成对校验 |
options.dashboard_user |
管理用户 | text | — | — |
serverForm.dashboard_password |
管理密码 | 密文 | — | — |
serverForm.agent_url |
Agent API 地址 | text | 示例误导;无格式校验 | 改为隧道/HTTPS 示例;URL 校验 |
serverForm.agent_token |
Agent Token | 密文 | — | — |
serverForm.ssh_host |
SSH 地址 | text | 无完整性依赖校验 | 完整性校验 |
serverForm.ssh_port |
SSH 端口 | number | — | — |
serverForm.ssh_user |
SSH 用户 | text | 同上 | 完整性校验 |
serverForm.ssh_auth |
SSH 认证 | select | 未联动 ssh_secret 文案 |
随选择切换文案/校验 |
serverForm.ssh_secret |
SSH 密码/私钥 | 密文 | 同上 | 按认证方式校验格式 |
serverForm.mgmt_enabled |
启用 Agent 日常管理 | switch | 与 agent_url 空值冲突 |
联动提示 |
serverForm.enabled |
(无标签) | 无 | 无 UI 入口 | 暴露或移除 |
六、改进建议
- 修正帮助栏(低成本、高收益):为
remote增加独立说明项集合;帮助栏标题改为按标签映射(如basic→配置说明 / advanced→高级配置说明 / remote→远程管理说明)。 - 引入表单校验:给
<n-form>加:model+:rules(或提交前手工校验),至少覆盖:名称/主机地址必填、端口范围、创建时 Token 认证必填、dashboard 成对、SSH 三件套完整、端口冲突、allow_ports格式。 - 处理
enabled:在基础配置补充"启用服务端"开关,或从表单与 payload 中移除。 - 跨字段联动:
tls_force↔tls_enabled、ssh_auth↔ssh_secret、mgmt_enabled↔agent_url、端口唯一性。 - 明确保存/生效语义:保存后如涉及 frps 参数变更,给出"需下发并重启"的显式提示;或将「下发 frps 配置」改为先保存再下发,避免下发旧配置。
- 修正过时文案:将"在「内网穿透」页服务端表单…"改为"本页表单…"(244、310 行)。
- 重排/重命名远程标签:按"frps 服务端参数 / 可观测性(管理接口) / Agent 接入"折叠分组;标签可命名为"服务端与 Agent"。补齐
defaultServerOptions()的远程字段默认值。 - 示例文案:
agent_urlplaceholder 改为 SSH 隧道本地地址或 HTTPS 固定示例,并注明不推荐公网明文。
七、附:类型定义对照
FrpServerOptions(web/src/api/types.ts 395–450 行)中与「远程管理」相关的字段均已定义,并有中文注释(如 tls_force 注明"frpc 必须开 transport.tls.enable"、dashboard_* 注明"仅用于拉取只读信息")。前端表单字段与类型基本一致,主要缺口在校验、默认值、帮助文案与字段归置,而非类型缺失。
本文档为静态分析结论,具体以
AgentView.vue源码为准;建议评审确认后再实施改动。