15 KiB
FRPS 服务端管理方案(havline-agent,部署于公网服务器)
需求:frpc 端(Havline/NAS)提交穿透规则后,公网服务器端自动完成反向代理设置,实现域名无端口访问(
http://tv.36800.cc),并自动管理服务器侧证书与 frps。 实现形态:在公网 VPS 上部署一个常驻管理组件 havline-agent(单个 Go 二进制 + systemd),对外提供管理 API;Havline 在规则变化时调用该 API,agent 在 VPS 本地完成 Nginx 反代配置、frps 管理与证书部署。 安装与管理通道:agent 的首次安装、升级、卸载通过 SSH 由 Havline 远程完成(用户在 Havline 界面填 SSH 信息点按钮即可,无需手工登 VPS);装好后 agent 以 API 接受日常管理。管理面板全部在本地 Havline,VPS 上没有任何面板。 修订记录:v2 混合形态(SSH 装/卸 + API 管理);v1 为纯 SSH 推送方案,v2 初稿为「agent 纯 API」方案,两版历史见文末对照。
1. 目标与效果
| 诉求 | 达成方式 |
|---|---|
| frpc 提交规则后 frps 端自动反代 | Havline 保存规则 → 调 agent API 注册域名路由 → agent 写 Nginx vhost 并 reload |
| 无端口访问 | agent 的 Nginx 监听 80(443),proxy_pass 到 frps vhost 端口,URL 不带端口号 |
| 管理证书 | Havline 证书页(DNS-01)签发后一键推送到 agent,自动挂 443 并续期重推 |
| frps 管理 | 配置下发(vhost 端口等)、进程重启/状态/版本、端口占用诊断,全部 API 化 |
| VPS 上已有 Nginx/站点 | 共存:agent 只写自己的 vhost 文件(conf.d/havline-*.conf),不动其他配置 |
最终链路(http 规则为例):
用户 → http://tv.36800.cc(80,无端口)
→ VPS Nginx(agent 生成的 vhost)→ 127.0.0.1:8080(frps vhostHTTPPort)
→ frps 按域名路由 → FRP 隧道 → NAS frpc → 192.168.31.152:7023
2. 总体架构
Havline (NAS,管理面板所在地) 公网服务器 (VPS)
┌──────────────────────────────┐ ┌────────────────────────────────┐
│ FRP 模块(现有) │ │ frps :7000 控制 / 8080 vhost │
│ 规则 CRUD / frpc / frps.toml │ │ nginx :80/443 │
│ 证书页(lego DNS-01,已有) │ │ └─ havline-*.conf(agent 产物) │
│ ┌────────────────────┐ │ │ havline-agent :7700(常驻) │
│ │ SSH 安装器(新增) │──SSH──┼→ 首次安装/升级/卸载 agent │
│ │ agent 客户端(新增) │──API──┼→ 日常管理:路由/配置/证书/状态 │
│ └────────────────────┘ │ │ ├─ 路由管理(nginx vhost 编排) │
│ 管理面板 = Havline 网页 │ │ ├─ frps 管理(配置/进程/诊断) │
│ (规则页/证书页/管理弹窗) │ │ └─ 证书接收与挂载 │
└──────────────────────────────┘ └────────────────────────────────┘
两条通道各司其职:
- SSH(低频):仅用于 agent 生命周期——安装、升级、卸载、agent 失联自救。用户在 Havline 填一次 SSH 信息(可选保存备用);
- API(高频):日常全部管理——规则同步、frps 配置下发、证书推送、状态查询。面板 100% 在 Havline 本地,VPS 上没有任何管理界面。
职责划分:Havline 是控制面(用户在哪配置就存哪),agent 是执行面(只接收指令并落实),frps/Nginx 是数据面。agent 无状态(配置即文件),可随时重装。
3. havline-agent 设计(VPS 侧)
单个 Go 二进制(复用主项目代码编译,cmd/havline-agent),systemd 常驻,管理 API 监听 :7700(可配置)。
3.1 管理 API(Bearer Token 鉴权)
| 方法/路径 | 作用 |
|---|---|
GET /api/v1/ping |
连通性/鉴权校验(Havline「测试连接」按钮) |
GET /api/v1/status |
frps 版本/运行方式/配置路径、80/443/7000/8080 端口占用者、已注册路由、证书有效期 |
PUT /api/v1/routes |
注册/更新域名路由:{domain, upstream(=frps vhost 端口), tls, cert_id} → 写 Nginx vhost → nginx -t → reload(失败自动回滚文件) |
DELETE /api/v1/routes/{domain} |
注销路由(规则删除/停用时调用) |
GET /api/v1/routes |
当前路由清单(对账用) |
PUT /api/v1/frps/config |
下发完整 frps.toml(Havline 同源生成)→ 备份旧文件 → 按运行方式重启/重载 → 回读验证 |
POST /api/v1/certs |
部署证书:{domain, fullchain_pem, key_pem} → 写 /var/lib/havline-agent/certs/<domain>/(0600)→ 更新 443 vhost → reload |
3.2 Nginx 编排(反代核心)
- 每个域名一个文件:
/etc/nginx/conf.d/havline-tv.36800.cc.conf,模板:
server {
listen 80;
server_name tv.36800.cc;
location / {
proxy_pass http://127.0.0.1:8080; # frps vhostHTTPPort
proxy_set_header Host $host; # frps 按域名分流,必须保留
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
}
}
# 启用证书后追加 443 server 块(ssl_certificate 指向 agent 证书目录)+ 80 跳转
- 写入流程:写
.tmp→nginx -t校验 → 通过则替换并nginx -s reload,失败保留原文件并把nginx -t输出回传给 Havline 显示; - 只增删自己的
havline-*.conf,绝不触碰其他配置 → 与宝塔/手工站点共存; - 首次运行自检:nginx 是否安装、
conf.d/sites-enabled目录探测、80/443 监听者识别(nginx? frps? 其他?)。
3.3 frps 管理
- 配置下发:Havline「frps.toml 同源生成」已有(含 vhost 端口、auth、webServer),改为推送给 agent 落盘:备份旧文件 → 原子替换 → 按运行方式生效(systemd 单元
systemctl restart frps;nohup 场景pkill frps后按原命令拉起,agent 从状态接口学习原启动命令); - 诊断:
status聚合 frps 版本/存活/配置路径 +ss -tlnp端口占用判定——把之前手工排查(port unavailable、80 被占)变成 API 一次调用; - 边界:不安装/升级 frps 二进制(检测报告提示版本即可)。
3.4 证书
- 签发仍在 Havline 证书页(lego DNS-01,复用 DDNS 凭证,NAS 侧完成,VPS 无需参与);
- 部署:证书页「部署到服务器」→
POST /certs推送 PEM → agent 落盘并生成 443 vhost → reload; - 续期:Havline 定时任务续期成功后自动重推,VPS 侧无感;
- (可选演进)agent 本地 ACME HTTP-01:agent 已在 80 上,可自助签发,作为无 DNS 凭证场景的备选,本期不做。
4. 通信协议与安全
| 项 | 设计 |
|---|---|
| 鉴权 | Bearer Token(Havline 服务端表单生成/粘贴,agent 配置文件持有;两端一致即可用),7700 建议用防火墙限制仅 NAS IP 访问 |
| 传输 | 明文 HTTP 起步可接受(Token + 内网限制);增强路径:agent 用 frps 证书或自签证书提供 HTTPS 管理口 |
| 命令安全 | agent 只执行固定动作(写文件/nginx -t/reload/重启 frps),不执行 Havline 下发的任意命令;域名/路径参数做白名单校验(域名格式、路径锁定 conf.d/havline-* 与 /var/lib/havline-agent/) |
| 幂等 | 路由/配置/证书接口全部幂等,重复调用无副作用;routes 对账接口支持 Havline 定时校准 |
| 审计 | agent 每个写操作记本地日志(who/when/what),Havline 侧同步状态入系统日志 |
5. Havline 侧改动(frpc 端)
| 模块 | 内容 |
|---|---|
| 数据模型 | frp_servers 加 agent_url、agent_token_enc(secret.Box 加密不回显)、mgmt_enabled(默认 0,行为与 v1.1.0 完全一致);迁移 023_frp_server_agent.sql |
| 规则联动 | 规则保存/删除/启停且 mgmt_enabled 时,自动调 agent 路由接口(http/https 类型域名规则);失败不阻塞保存,规则行显示同步状态(已同步/待同步/失败+原因) |
| frps.toml | 「下发到服务器」按钮替代「复制到 VPS」;一键含重启与验证 |
| 证书页 | 「部署到服务器」:选目标服务端 → 推送 PEM → 回显 agent 挂载结果;续期任务成功后自动重推 |
| 管理弹窗 | 服务端「管理」按钮:status 报告(frps 状态/端口占用者/路由清单/证书有效期)+ 一键操作(下发配置/全量对账) |
| API 客户端 | internal/frp/agent_client.go:Go HTTP 客户端封装上述 7 个接口(超时/重试/错误透传) |
6. agent 部署与生命周期管理(SSH,全程在 Havline 界面完成)
6.1 首次安装(用户不登 VPS)
- Havline 服务端表单「远程管理」分组填 SSH 信息(地址/端口/用户/密码或私钥,可选保存)+ 点「安装 agent」;
- Havline 经单次 SSH 会话自动完成:
- 探测环境:
uname -m(选二进制)、nginx 是否安装、systemd可用性、端口占用快照; - SFTP 上传
havline-agent二进制与install.sh(从 Havline 自带资源解出对应架构); - 远程执行
install.sh:落位/usr/local/bin/havline-agent、写/etc/havline-agent/agent.toml(生成随机 Token 并回传给 Havline,无需用户抄写)、注册systemd单元并启动; - 安装后立刻走 API
ping验证 + 防火墙提示(如 7700 未放行给出命令);
- 探测环境:
- UI 展示每步输出,失败可重试(幂等,重复安装=覆盖升级)。
6.2 升级 / 卸载 / 自救
| 动作 | 方式 | 说明 |
|---|---|---|
| 升级 agent | SSH:上传新二进制 + systemctl restart havline-agent |
路由/证书/Token 均在磁盘,不丢 |
| 卸载 agent | SSH:install.sh --uninstall(停服务、可选保留数据) |
nginx vhost 文件一并清理(可选项) |
| agent 失联 | API 不可达时,Havline 管理弹窗提示「走 SSH 通道诊断」:进程状态/端口/日志尾部 | SSH 是 API 故障时的备用通道 |
6.3 日常管理(API,面板在 Havline)
安装完成后的一切操作不再用 SSH:规则联动同步、frps.toml 下发、证书部署、status 查询、全量对账——全部是 Havline 界面按钮/自动触发,走 agent API。VPS 上没有任何管理面板,用户日常甚至不需要记住 VPS 密码。
6.5 Havline 侧新增「SSH 安装器」(与 agent 客户端并列)
| 模块 | 内容 |
|---|---|
internal/frp/ssh_installer.go(新) |
SSH 连接(x/crypto/ssh 已在 go.mod)、SFTP 上传二进制/install.sh、远程幂等安装流程、Token 回传 |
| agent 二进制内嵌 | 构建期把 havline-agent 各架构二进制 embed 进 Havline(构建矩阵:linux-amd64/arm64),安装时按 uname -m 选择,无需用户单独下载 |
| 数据模型 | 复用 023 迁移:ssh_host/port/user/auth/secret_enc 可选保存(仅启用「安装/升级/卸载」功能时需要),agent API Token 由安装器自动生成并写入 Havline |
| UI | 服务端表单「远程管理」:SSH 信息(可选)+「安装 agent / 升级 / 卸载 / 走 SSH 诊断」按钮,安装过程实时输出展示 |
SSH 信息可选保存:仅安装/升级时需要;日常管理走 API Token。安全上 SSH 凭据同 token 机制(secret.Box 加密、不回显),远程命令固定白名单模板(上传/安装/卸载三种),无注入面。
7. 实现拆解与工作量
| 模块 | 位置 | 内容 | 量级 |
|---|---|---|---|
| agent 主体 | cmd/havline-agent/ + internal/agent/(新) |
HTTP 服务、鉴权、路由/frps/证书三个执行器、nginx 模板与 reload、状态聚合 | 大(约 1200 行) |
| Havline SSH 安装器 | internal/frp/ssh_installer.go(新) |
SSH/SFTP 上传、远程幂等安装/升级/卸载、agent 二进制 embed、Token 自动回传 | 中 |
| Havline agent 客户端 | internal/frp/agent_client.go(新) |
7 个接口封装 | 中 |
| 数据模型/迁移 | 023_frp_server_agent.sql |
SSH + agent 字段 + 规则同步状态 | 小 |
| 规则联动 | internal/frp/service.go |
保存/删除/启停后同步调用 + 状态落库 | 中 |
| API/UI | frpmulti_handler.go、router.go、FrpView.vue、client.ts |
5 个端点 + 表单分组 + 管理弹窗 + 同步状态列 | 中 |
| 测试 | agent_test.go 等 |
nginx 模板渲染/回滚、接口幂等、鉴权 | 中 |
总计约 2500–3000 行(含测试)。mgmt_enabled=0 时 Havline 行为与 v1.1.0 完全一致;agent 未部署的服务端不受任何影响。
8. 里程碑
| 阶段 | 内容 | 验收 |
|---|---|---|
| M1 | agent 主体(ping/status/routes)+ Havline SSH 安装器(一键安装) | Havline 填 SSH 信息点「安装」后自动装好 agent 并回连成功,status 能报端口占用者 |
| M2 | Havline 规则联动 + 路由自动注册 + frps 配置下发 | 保存 http 规则后 http://域名 无端口直达;frps.toml 一键下发生效 |
| M3 | 证书推送 + 续期联动 + 443 路由 | https://域名 可用,续期自动重推 |
| M4 | 管理弹窗 UI + 全量对账 + 升级/卸载/SSH 诊断 + 手册更新 | 手册第 6 节新增方案 C(agent 模式:SSH 装、API 管) |
9. 明确不做(本期)
- 不做 agent 侧自主 ACME(DNS-01 在 NAS 侧签发已覆盖;HTTP-01 作为后续可选);
- 不做 frps 二进制远程安装/升级(status 报告版本,安装沿用现有手册);
- 不做 agent 集群/多机编排(一个服务端一个 agent,模型对齐现有 frp_servers);
- 不动 frp 二进制与协议(agent 只操作 frps 的配置文件、进程与 vhost 端口)。
10. 方案形态对照
| v2 最终(agent + SSH 安装器) | v1(纯 SSH 推送) | |
|---|---|---|
| VPS 侧 | 常驻 agent,但安装/升级由 Havline SSH 一键完成 | 零安装 |
| 日常管理 | API(面板全在 Havline,日常无需 SSH) | 每次操作都走 SSH 命令 |
| 能力上限 | 高:本地编排 nginx/frps/证书,可自愈可扩展 | 受限于 SSH 命令白名单 |
| 与已有站点共存 | 只写 havline-*.conf,共存 |
可实现但每步都要远程拼配置 |
| 故障定位 | status API 一次拿全;agent 失联时 SSH 急救 | 每次探测拼 SSH 命令 |
| 适用 | VPS 长期做穿透入口、多域名/HTTPS 全自动 | 不想在 VPS 装常驻组件 |
结论:SSH 与 API 不是二选一——SSH 只承担 agent 生命周期(装/升/卸/急救),API 承担日常管理;管理面板 100% 在 Havline 本地,VPS 上没有任何管理界面。