Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe28fc5623 | ||
|
|
8401948dc0 | ||
|
|
4413eb3571 | ||
|
|
fbadd44af5 | ||
|
|
e6488d3f1b | ||
|
|
e4ecc57825 |
31
README.md
@@ -11,7 +11,7 @@ frps-multiuser will run as one single process and accept HTTP requests from frps
|
||||

|
||||

|
||||
|
||||
## update notes
|
||||
## Update Notes
|
||||
|
||||
+ **the default tokens file is frps-multiuser.ini now,ini file support comment**
|
||||
+ **remove `-l`,it configure in `frps-multiuser.ini` now**
|
||||
@@ -23,6 +23,7 @@ frps-multiuser will run as one single process and accept HTTP requests from frps
|
||||
+ **you can limit `ports`,`domains` and `subdomains` for each user now**
|
||||
|
||||
***when a user is dynamic been `remove` or `disable`,it will take some time to be effective***
|
||||
|
||||
***the limit of `ports`、`domains`、`subdomains` only effective at `NewProxy`***
|
||||
|
||||
### Features
|
||||
@@ -130,6 +131,32 @@ local_port = 22
|
||||
remote_port = 6000
|
||||
```
|
||||
|
||||
## Run as service
|
||||
|
||||
this example is for `ubuntu` and with `root` user
|
||||
|
||||
+ 1.unzip `frps-multiuser.zip` to dir `/root/frps-multiuser`
|
||||
+ 2.touch a file with command `touch frps-multiuser.service` in dir `/root/frps-multiuser`.the file content is:
|
||||
```ini
|
||||
[Unit]
|
||||
Description = frp multiuser service
|
||||
After = network.target syslog.target
|
||||
Wants = network.target
|
||||
|
||||
[Service]
|
||||
Type = simple
|
||||
# config of frps-multiuser.ini,you should change the file path
|
||||
Environment=FRPS_MULTIUSER_OPTS="-c /root/frps-multiuser/frps-multiuser.ini"
|
||||
# command of run frps-multiuser,you should change the file path
|
||||
ExecStart = /root/frps-multiuser/frps-multiuser $FRPS_MULTIUSER_OPTS
|
||||
|
||||
[Install]
|
||||
WantedBy = multi-user.target
|
||||
```
|
||||
+ 3.copy `frps-multiuser.service` to `/etc/systemd/system/` with command `cp /root/frps-multiuser.service /etc/systemd/system/`
|
||||
+ 4.reload service with command `systemctl daemon-reload`
|
||||
+ 5.start service with command `service frps-multiuser start`
|
||||
|
||||
## Issues & Ideas
|
||||
|
||||
___If you want visit mange ui from internet, you should change `plugin_addr` to `0.0.0.0`___
|
||||
@@ -141,4 +168,4 @@ If you have any issues or ideas, put it on [issues](https://github.com/yhl452493
|
||||
+ [frp](https://github.com/fatedier/frp)
|
||||
+ [fp-multiuser](https://github.com/gofrp/fp-multiuser)
|
||||
+ [layui](https://github.com/layui/layui)
|
||||
+ [layui-theme-dark](https://github.com/Sight-wcg/layui-theme-dark)
|
||||
+ [layui-theme-dark](https://github.com/Sight-wcg/layui-theme-dark)
|
||||
|
||||
29
README_zh.md
@@ -23,6 +23,7 @@ frps-multiuser 会以一个单独的进程运行,并接收 frps 发送过来
|
||||
+ **新增对用户的`端口`、`域名`、`二级域名`进行限制**
|
||||
|
||||
***用户被`删除`或`禁用`后,不会马上生效,需要等一段时间***
|
||||
|
||||
***用户`端口`、`域名`、`二级域名`限制仅在建立新连接(`NewProxy`)时生效***
|
||||
|
||||
### 功能
|
||||
@@ -130,6 +131,32 @@ local_port = 22
|
||||
remote_port = 6000
|
||||
```
|
||||
|
||||
## 以服务的形式运行
|
||||
|
||||
本实例是在 `ubuntu` 下, 以 `root` 用户执操作
|
||||
|
||||
+ 1、解压 `frps-multiuser.zip` 到目录 `/root/frps-multiuser`
|
||||
+ 2、在目录 `/root/frps-multiuser` 下 用命令创建文件:`touch frps-multiuser.service`。创建后修改文件内容:
|
||||
```ini
|
||||
[Unit]
|
||||
Description = frp multiuser service
|
||||
After = network.target syslog.target
|
||||
Wants = network.target
|
||||
|
||||
[Service]
|
||||
Type = simple
|
||||
# 启动frps-multiuser的配置文件路径,需修改为您的frps-multiuser.ini的路径
|
||||
Environment=FRPS_MULTIUSER_OPTS="-c /root/frps-multiuser/frps-multiuser.ini"
|
||||
# 启动frps-multiuser的命令,需修改为您的frps-multiuser的安装路径
|
||||
ExecStart = /root/frps-multiuser/frps-multiuser $FRPS_MULTIUSER_OPTS
|
||||
|
||||
[Install]
|
||||
WantedBy = multi-user.target
|
||||
```
|
||||
+ 3、复制服务文件: `cp /root/frps-multiuser.service /etc/systemd/system/`
|
||||
+ 4、重载服务: `systemctl daemon-reload`
|
||||
+ 5、启动服务: `service frps-multiuser start`
|
||||
|
||||
## 使用
|
||||
|
||||
___如果要从外网访问管理界面, 需要把配置中的 `plugin_addr` 改为 `0.0.0.0`___
|
||||
@@ -141,4 +168,4 @@ ___如果要从外网访问管理界面, 需要把配置中的 `plugin_addr` 改
|
||||
+ [frp](https://github.com/fatedier/frp)
|
||||
+ [fp-multiuser](https://github.com/gofrp/fp-multiuser)
|
||||
+ [layui](https://github.com/layui/layui)
|
||||
+ [layui-theme-dark](https://github.com/Sight-wcg/layui-theme-dark)
|
||||
+ [layui-theme-dark](https://github.com/Sight-wcg/layui-theme-dark)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"User Manage": "User Manage",
|
||||
"frps multiuser": "frps multiuser",
|
||||
"User": "User",
|
||||
"Token": "Token",
|
||||
"Notes": "Notes",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"User Manage": "用户管理",
|
||||
"frps multiuser": "frps用户管理",
|
||||
"User": "用户名(user)",
|
||||
"Token": "凭证(meta_token)",
|
||||
"Notes": "备注",
|
||||
|
||||
128
assets/static/css/index-color.css
Normal file
@@ -0,0 +1,128 @@
|
||||
header {
|
||||
background-color: #58b7ff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.layui-btn {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.layui-layer-btn .layui-layer-btn0 {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.layui-btn-primary {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.layui-btn-primary:hover {
|
||||
border-color: #79bbff;
|
||||
}
|
||||
|
||||
.layui-input:focus,
|
||||
.layui-textarea:focus {
|
||||
border-color: #79bbff !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.layui-form-danger + .layui-form-select .layui-input,
|
||||
.layui-form-danger:focus {
|
||||
border-color: #ff5722 !important;
|
||||
}
|
||||
|
||||
.layui-laypage .layui-laypage-curr .layui-laypage-em {
|
||||
background-color: #409eff;
|
||||
}
|
||||
|
||||
.layui-laypage input:focus, .layui-laypage select:focus {
|
||||
border-color: #79bbff !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.layui-table-view .layui-table td[data-edit]:hover:after {
|
||||
border-color: #79bbff;
|
||||
}
|
||||
|
||||
.layui-form-checkbox[lay-skin=primary]:hover > i {
|
||||
border-color: #79bbff;
|
||||
}
|
||||
|
||||
.layui-form-checked[lay-skin=primary] > i {
|
||||
background-color: #409eff;
|
||||
border-color: #409eff !important;
|
||||
}
|
||||
|
||||
.layui-table-checked {
|
||||
background-color: #ecf5ff;
|
||||
}
|
||||
|
||||
.layui-table-checked:hover {
|
||||
background-color: #d9ecff;
|
||||
}
|
||||
|
||||
.layui-table-cell-c:hover{
|
||||
border-color: #79bbff;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
header {
|
||||
background-color: #395c74;
|
||||
}
|
||||
|
||||
.layui-btn {
|
||||
background-color: #4f80a1;
|
||||
}
|
||||
|
||||
.layui-layer-btn .layui-layer-btn0 {
|
||||
background-color: #4f80a1;
|
||||
}
|
||||
|
||||
.layui-btn-primary {
|
||||
background-color: transparent;
|
||||
border-color: #484849;
|
||||
}
|
||||
|
||||
.layui-btn-primary:hover {
|
||||
border-color: #5f5f60;
|
||||
}
|
||||
|
||||
.layui-input:focus,
|
||||
.layui-textarea:focus {
|
||||
border-color: #5f5f60 !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.layui-laypage .layui-laypage-curr .layui-laypage-em {
|
||||
background-color: #4f80a1;
|
||||
}
|
||||
|
||||
.layui-laypage input:focus, .layui-laypage select:focus {
|
||||
border-color: #5f5f60 !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.layui-table-view .layui-table td[data-edit]:hover:after {
|
||||
border-color: #5f5f60;
|
||||
}
|
||||
|
||||
.layui-form-checkbox[lay-skin=primary]:hover > i {
|
||||
border-color: #5f5f60;
|
||||
}
|
||||
|
||||
.layui-form-checked[lay-skin=primary] > i {
|
||||
background-color: #484849;
|
||||
border-color: #484849 !important;
|
||||
}
|
||||
|
||||
.layui-table-checked {
|
||||
background-color: rgba(255, 255, 255, .04);
|
||||
}
|
||||
|
||||
.layui-table-checked:hover {
|
||||
background-color: rgba(255, 255, 255, .08);
|
||||
}
|
||||
|
||||
.layui-table-cell-c:hover{
|
||||
border-color: #5f5f60;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,18 @@
|
||||
body {
|
||||
padding: 15px;
|
||||
html, body {
|
||||
padding: 0;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
header .title {
|
||||
padding: 10px 15px;
|
||||
line-height: 40px;
|
||||
font-size: 25px;
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 15px 15px 0 15px;
|
||||
}
|
||||
|
||||
#searchForm input {
|
||||
height: 30px;
|
||||
line-height: 28px;
|
||||
@@ -44,10 +54,14 @@ body {
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.layui-btn-container{
|
||||
.layui-btn-container {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.layui-layer-btn > a[class^=layui-layer-btn]{
|
||||
.layui-layer-btn > a[class^=layui-layer-btn] {
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.layui-table-page {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<link rel="stylesheet" href="./static/layui/css/layui.css">
|
||||
<link rel="stylesheet" href="./static/css/layui-theme-dark.css">
|
||||
<link rel="stylesheet" href="./static/css/index.css">
|
||||
<link rel="stylesheet" href="./static/css/index-color.css">
|
||||
<script src="./static/layui/layui.js"></script>
|
||||
<script src="./static/js/index.js"></script>
|
||||
<style>
|
||||
@@ -18,42 +19,48 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<form class="layui-form layui-row layui-col-space16" id="searchForm" lay-filter="searchForm">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-username"></i>
|
||||
<header>
|
||||
<div class="title">${ .FrpsMultiuser }</div>
|
||||
</header>
|
||||
<section>
|
||||
<form class="layui-form layui-row layui-col-space16" id="searchForm" lay-filter="searchForm">
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-username"></i>
|
||||
</div>
|
||||
<input type="text" name="user" placeholder="${ .User }" class="layui-input" autocomplete="off"
|
||||
lay-affix="clear">
|
||||
</div>
|
||||
<input type="text" name="user" placeholder="${ .User }" class="layui-input" autocomplete="off"
|
||||
lay-affix="clear">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-vercode"></i>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-vercode"></i>
|
||||
</div>
|
||||
<input type="text" name="token" placeholder="${ .Token }" class="layui-input" autocomplete="off"
|
||||
lay-affix="clear">
|
||||
</div>
|
||||
<input type="text" name="token" placeholder="${ .Token }" class="layui-input" autocomplete="off"
|
||||
lay-affix="clear">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-note"></i>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-input-wrap">
|
||||
<div class="layui-input-prefix">
|
||||
<i class="layui-icon layui-icon-note"></i>
|
||||
</div>
|
||||
<input type="text" name="comment" placeholder="${ .Notes }" class="layui-input" autocomplete="off"
|
||||
lay-affix="clear">
|
||||
</div>
|
||||
<input type="text" name="comment" placeholder="${ .Notes }" class="layui-input" autocomplete="off"
|
||||
lay-affix="clear">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm" id="searchBtn">${ .Search }</button>
|
||||
<button class="layui-btn layui-btn-sm layui-btn-primary" type="reset" id="resetBtn">${ .Reset }</button>
|
||||
<div class="layui-col-md3">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm" id="searchBtn">${ .Search }</button>
|
||||
<button class="layui-btn layui-btn-sm layui-btn-primary" type="reset" id="resetBtn">${ .Reset }</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table id="tokenTable" lay-filter="tokenTable"></table>
|
||||
</form>
|
||||
<table id="tokenTable" lay-filter="tokenTable"></table>
|
||||
</section>
|
||||
|
||||
<script type="text/html" id="toolbarTemplate">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm" lay-event="add">${ .NewUser }</button>
|
||||
|
||||
@@ -164,6 +164,7 @@ func (c *HandleController) MakeManagerFunc() func(context *gin.Context) {
|
||||
return func(context *gin.Context) {
|
||||
context.HTML(http.StatusOK, "index.html", gin.H{
|
||||
"UserManage": ginI18n.MustGetMessage(context, "User Manage"),
|
||||
"FrpsMultiuser": ginI18n.MustGetMessage(context, "frps multiuser"),
|
||||
"User": ginI18n.MustGetMessage(context, "User"),
|
||||
"Token": ginI18n.MustGetMessage(context, "Token"),
|
||||
"Notes": ginI18n.MustGetMessage(context, "Notes"),
|
||||
|
||||
|
Before Width: | Height: | Size: 147 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 129 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 331 KiB After Width: | Height: | Size: 236 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 134 KiB |