71214524f4e485d239ddfe8104a5e5ff221d731e
- Multi-tenant client/proxy management with Flask+SQLite - Frps server control (start/restart/token rotation) - Generate frpc.ini with shared server token + admin API - Dashboard API integration (live client/proxy status) - RBAC: admin/tenant_admin/user roles - Audit logging for all operations - Systemd service files included - Requires legacy INI format (frp 0.70 TOML auth broken)
frps-manager
基于 frps 0.70.1 的内网穿透 Web 管理系统,多租户 + Web 端代理规则 CRUD。
功能
| 模块 | 说明 |
|---|---|
| 仪表盘 | frps 状态、监听端口、在线客户端/代理数、Server Token 显示、实时在线列表 |
| 租户 | 多租户隔离,每个租户独立带宽/连接配额 |
| 客户端 (frpc) | 注册 frpc 客户端(user 字段 + token),归属租户,启停、旋转 token |
| 代理规则 | 支持 tcp / udp / http / https,配置远端端口、域名、加密压缩、健康检查 |
| frpc.ini 生成 | 点客户端的「frpc.ini」按钮下载一份含所有代理 + 共享 server token + admin API 的配置 |
| 热重载支持 | 生成的 frpc.ini 默认带 admin_addr/admin_port,修改代理后用户在 frpc 主机执行 frpc reload -c /etc/frpc.ini 即可生效(无需 SSH 重启) |
| 用户 | admin / tenant_admin / user 三级 RBAC,每个用户绑定到租户 |
| 审计日志 | 全部管理操作(创建/删除/旋转 token/重载 frps…)写入日志 |
| frps 控制 | 通过 Web 重写 frps.ini 并重启 frps、旋转 server token、查看生成的 frps.ini |
关键设计:frps 0.70 的特殊性
fatedier/frp 0.70.1 的 TOML 配置和 auth 流程有问题:
- TOML 解析器不接受
auth.method = "token"/auth.token = "..."这种点路径键(尽管官方 example 文件这么写) --tokenCLI flag 设的值会被 TOML 加载流程覆盖为空值- 唯一真正可用的格式:
legacy INI([common]+token = xxx),frp 在加载时会打印WARNING: ini format is deprecated
所以本系统:
- 生成
frps.ini(legacy INI)而不是 frps.toml - 生成
frpc.ini(legacy INI)给用户 - 会在 frps 日志看到 deprecation warning — 这是 frp 项目已知问题,未来升级到 0.71+(修复 TOML auth 后)只需把
render_frps_ini改成 TOML 渲染
另一个特殊性:frps 0.70+ 没有 server-side [[proxies]] 段 — 所有代理规则都在 frpc 端 [[xxx]] 配置里,启动时通过 control message 推给 frps。所以 Web 系统所有代理数据都在 frpc.ini 里,frps.ini 只管 bind/dashboard/auth/log。
技术栈
- 后端: Flask 3.0 + Flask-SQLAlchemy + SQLite
- WSGI: Gunicorn (2 workers)
- 前端: Jinja2 模板 + 原生 CSS(无前端框架依赖)
- 被管理: frps 0.70.1(GitHub: fatedier/frp)+ frpc 0.70.1
- 认证: Werkzeug password hashing + Flask session
目录结构
frps-manager/
├── app.py # Flask 应用主文件(模型、路由、INI 渲染逻辑)
├── wsgi.py # Gunicorn 入口(DB 初始化)
├── init_db.py # 独立 DB 初始化脚本
├── requirements.txt
├── README.md
├── _smoke_test.py # 端到端测试(起 frps + frpc + reload 验证)
├── scripts/
│ ├── deploy.sh # 一键部署脚本(systemd)
│ └── dev.sh # 本地开发启动
├── templates/ # Jinja2 模板
│ ├── base.html # 布局 + 导航
│ ├── login.html
│ ├── dashboard.html
│ ├── tenants.html / tenant_form.html
│ ├── clients.html / client_form.html
│ ├── proxies.html / proxy_form.html
│ ├── users.html / user_form.html
│ ├── logs.html
│ ├── change_password.html
│ └── error.html
├── static/
│ └── style.css # 全部样式
├── instance/ # SQLite DB + server token(运行时生成)
│ ├── frps_manager.db
│ └── server_token # 0600 权限,仅 root 可读
└── runtime/ # 运行时数据
├── bin/frps # frps 二进制(deploy.sh 自动下载)
├── conf/frps.ini # 由 app.py 生成的 frps 配置
├── logs/ # gunicorn / frps 日志
├── frps.service # frps systemd 单元
├── frps-manager.service # web systemd 单元
└── frpc@.service # 用户给 frpc 主机用的模板
安装
一键部署(推荐)
git clone <repo-url> /opt/frps-manager
cd /opt/frps-manager
sudo bash scripts/deploy.sh
部署脚本会自动:
- 安装系统依赖(python3, pip, venv, curl)
- 下载 frp 0.70.1 二进制到
runtime/bin/frps - 创建 venv 并安装依赖
- 初始化 SQLite(默认管理员
admin / admin,默认租户default) - 生成
frps.ini(含自动生成的 server token) - 安装并启动两个 systemd 服务:
frps.service— 监听 0.0.0.0:7000,dashboard 在 127.0.0.1:7500frps-manager.service— Web UI 在 0.0.0.0:5390
启动后访问 http://<host>:5390,用 admin / admin 登录,立刻去「改密」改掉默认密码。
本地开发
cd frps-manager
bash scripts/dev.sh
# 浏览器打开 http://localhost:5390
多租户使用流程
- 管理员登录 → 创建 租户(带带宽/连接配额元数据,文档用)
- 创建 普通用户(绑定到该租户,role = user)
- 租户用户登录 → 创建 frpc 客户端(分配名称 + 租户)
- 在该客户端下添加 代理规则(类型、远端端口/域名、本地端口、加密/压缩/健康检查…)
- 点客户端列表的「frpc.ini」下载配置(包含所有代理 + 共享 server token + admin API)
- 把
frpc.ini拷贝到 frpc 主机,启动 frpc - 改代理后:用户拉到新 frpc.ini 后在 frpc 主机执行
frpc reload -c /etc/frpc.ini,frpc 自动应用新配置(dashboard 立刻显示新代理在线)
frpc 配置示例
Web 生成的 frpc.ini:
# Generated by frps-manager for client: laptop-jdoe
[common]
server_addr = your.frps.host
server_port = 7000
authentication_method = token
token = AbCdEf123456... # 与所有 frpc 共用的 server token
admin_addr = 127.0.0.1
admin_port = 7400
admin_user = admin
admin_pwd = admin # 用于 `frpc reload` 命令
[laptop-jdoe_ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6001
use_encryption = true
[laptop-jdoe_web]
type = http
local_ip = 127.0.0.1
local_port = 8080
custom_domains = web.example.com
存到 frpc 主机 /etc/frpc/laptop-jdoe.ini,然后用模板 unit:
sudo cp /path/to/frps-manager/runtime/frpc@.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now frpc@laptop-jdoe
改代理后:
# 在 frpc 主机执行
sudo frpc reload -c /etc/frpc/laptop-jdoe.ini
# 或者 frpc reload -c /etc/frpc.ini(按你保存的路径)
配置(环境变量)
| 变量 | 默认值 | 说明 |
|---|---|---|
FLASK_SECRET |
随机 | Flask session 密钥(生产必须设置一个长随机串) |
FRPS_BIN |
runtime/bin/frps |
frps 可执行文件路径 |
FRPS_CONFIG |
runtime/conf/frps.ini |
frps.ini 路径 |
FRPS_SERVICE |
frps |
systemd 单元名(不含 .service) |
FRPS_DASHBOARD_URL |
http://127.0.0.1:7500 |
frps dashboard URL |
FRPS_DASHBOARD_USER |
admin |
dashboard 用户名 |
FRPS_DASHBOARD_PASS |
admin123 |
dashboard 密码 |
FRPS_BIND_PORT |
7000 |
frps 监听端口 |
FRPS_WEB_ADDR |
127.0.0.1 |
dashboard 监听地址 |
FRPS_WEB_PORT |
7500 |
dashboard 端口 |
FRPS_VHOST_HTTP_PORT |
80 |
http 虚拟主机端口 |
FRPS_VHOST_HTTPS_PORT |
443 |
https 虚拟主机端口 |
FRPC_ADMIN_ADDR |
127.0.0.1 |
写入 frpc.ini 的 admin API 地址 |
FRPC_ADMIN_PORT |
7400 |
写入 frpc.ini 的 admin API 端口(每台 frpc 主机必须唯一) |
FRPC_ADMIN_USER |
admin |
写入 frpc.ini 的 admin 用户名 |
FRPC_ADMIN_PWD |
admin |
写入 frpc.ini 的 admin 密码 |
安全建议
- 改默认 admin 密码
- dashboard(7500)只在 127.0.0.1 监听 — 如果要让远程看 dashboard,把它放到 nginx 反向代理后面 + HTTPS
- Web UI(5390)同理,建议放到 nginx + HTTPS 后
- 不要把 frps 暴露到公网 0.0.0.0:7000 而不设防火墙 — 每个 frpc 用同一个 server token,谁拿到 token 都能连
- 如果需要更强的隔离,部署多个 frps 实例在不同端口,每个 frps 一个 server token
instance/server_token包含所有 frpc 的共享密钥,备份时加密
已知限制
- frps 0.70.1 INI 格式被官方 deprecation warning — 升级到 0.71+ 后只需把
render_frps_ini改为 TOML - frpc 0.70.1 也用 INI(frpc 端 INI 一直支持到最新版本,不受影响)
- Web UI 不支持批量操作(一次性添加多个代理)
- 没有内嵌 traffic chart;如需图表请用 Prometheus + frps 自带的
/metrics端点
License
MIT
Description
Releases
1
frps_manager_0.0.1
Latest
Languages
Python
50.2%
HTML
28.9%
CSS
10.1%
Shell
9.4%
Jinja
1.4%