From b82bc21d1b31dd9599f87b4f4afa20c897c87ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Sun, 25 Aug 2024 02:12:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 + .../plugins/openresty_controller.go | 187 ------------------ .../fail2ban/controller.go} | 22 +-- app/plugins/fail2ban/main.go | 39 ++++ .../plugins/frp_controller.go | 0 .../plugins/gitea_controller.go | 0 app/plugins/loader/loader.go | 4 +- .../plugins/mysql_controller.go | 0 app/plugins/openresty/main.go | 2 +- .../plugins/php_controller.go | 0 .../plugins/phpmyadmin_controller.go | 0 .../plugins/podman_controller.go | 0 .../plugins/postgresql_controller.go | 0 .../plugins/pureftpd_controller.go | 0 .../plugins/redis_controller.go | 0 .../plugins/rsync_controller.go | 0 .../plugins/s3fs_controller.go | 0 .../plugins/supervisor_controller.go | 0 .../plugins/toolbox_controller.go | 0 19 files changed, 57 insertions(+), 201 deletions(-) delete mode 100644 app/http/controllers/plugins/openresty_controller.go rename app/{http/controllers/plugins/fail2ban_controller.go => plugins/fail2ban/controller.go} (94%) create mode 100644 app/plugins/fail2ban/main.go rename app/{http/controllers => }/plugins/frp_controller.go (100%) rename app/{http/controllers => }/plugins/gitea_controller.go (100%) rename app/{http/controllers => }/plugins/mysql_controller.go (100%) rename app/{http/controllers => }/plugins/php_controller.go (100%) rename app/{http/controllers => }/plugins/phpmyadmin_controller.go (100%) rename app/{http/controllers => }/plugins/podman_controller.go (100%) rename app/{http/controllers => }/plugins/postgresql_controller.go (100%) rename app/{http/controllers => }/plugins/pureftpd_controller.go (100%) rename app/{http/controllers => }/plugins/redis_controller.go (100%) rename app/{http/controllers => }/plugins/rsync_controller.go (100%) rename app/{http/controllers => }/plugins/s3fs_controller.go (100%) rename app/{http/controllers => }/plugins/supervisor_controller.go (100%) rename app/{http/controllers => }/plugins/toolbox_controller.go (100%) diff --git a/README.md b/README.md index 1131719a14..1c893ca0fd 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,10 @@ 交流QQ群:[12370907](https://jq.qq.com/?_wv=1027&k=I1oJKSTH) | 论坛:[tom.moe](https://tom.moe) | 赞助:[爱发电](https://afdian.com/a/TheTNB) +## 项目现状 + +**目前我在着手使用新的「自研」框架重构本项目,由于更改非常大需要一定时间,预期 8 月底会带来新的更新。** + ## 优势 1. **极低占用:** 在 Debian 12 下部署面板 + LNMP 环境,内存占用不到 500 MB,遥遥领先于使用容器化的其他面板。 diff --git a/app/http/controllers/plugins/openresty_controller.go b/app/http/controllers/plugins/openresty_controller.go deleted file mode 100644 index 0795775fa5..0000000000 --- a/app/http/controllers/plugins/openresty_controller.go +++ /dev/null @@ -1,187 +0,0 @@ -package plugins - -import ( - "fmt" - "regexp" - "time" - - "github.com/go-resty/resty/v2" - "github.com/goravel/framework/contracts/http" - "github.com/spf13/cast" - - "github.com/TheTNB/panel/v2/pkg/h" - "github.com/TheTNB/panel/v2/pkg/io" - "github.com/TheTNB/panel/v2/pkg/shell" - "github.com/TheTNB/panel/v2/pkg/str" - "github.com/TheTNB/panel/v2/pkg/systemctl" - "github.com/TheTNB/panel/v2/pkg/types" -) - -type OpenRestyController struct { - // Dependent services -} - -func NewOpenrestyController() *OpenRestyController { - return &OpenRestyController{} -} - -// GetConfig -// -// @Summary 获取配置 -// @Tags 插件-OpenResty -// @Produce json -// @Security BearerToken -// @Success 200 {object} controllers.SuccessResponse -// @Router /plugins/openresty/config [get] -func (r *OpenRestyController) GetConfig(ctx http.Context) http.Response { - config, err := io.Read("/www/server/openresty/conf/nginx.conf") - if err != nil { - return h.Error(ctx, http.StatusInternalServerError, "获取配置失败") - } - - return h.Success(ctx, config) -} - -// SaveConfig -// -// @Summary 保存配置 -// @Tags 插件-OpenResty -// @Produce json -// @Security BearerToken -// @Param config body string true "配置" -// @Success 200 {object} controllers.SuccessResponse -// @Router /plugins/openresty/config [post] -func (r *OpenRestyController) SaveConfig(ctx http.Context) http.Response { - config := ctx.Request().Input("config") - if len(config) == 0 { - return h.Error(ctx, http.StatusInternalServerError, "配置不能为空") - } - - if err := io.Write("/www/server/openresty/conf/nginx.conf", config, 0644); err != nil { - return h.Error(ctx, http.StatusInternalServerError, "保存配置失败") - } - - if err := systemctl.Reload("openresty"); err != nil { - _, err = shell.Execf("openresty -t") - return h.Error(ctx, http.StatusInternalServerError, fmt.Sprintf("重载服务失败: %v", err)) - } - - return h.Success(ctx, nil) -} - -// ErrorLog -// -// @Summary 获取错误日志 -// @Tags 插件-OpenResty -// @Produce json -// @Security BearerToken -// @Success 200 {object} controllers.SuccessResponse -// @Router /plugins/openresty/errorLog [get] -func (r *OpenRestyController) ErrorLog(ctx http.Context) http.Response { - if !io.Exists("/www/wwwlogs/nginx_error.log") { - return h.Success(ctx, "") - } - - out, err := shell.Execf("tail -n 100 /www/wwwlogs/openresty_error.log") - if err != nil { - return h.Error(ctx, http.StatusInternalServerError, out) - } - - return h.Success(ctx, out) -} - -// ClearErrorLog -// -// @Summary 清空错误日志 -// @Tags 插件-OpenResty -// @Produce json -// @Security BearerToken -// @Success 200 {object} controllers.SuccessResponse -// @Router /plugins/openresty/clearErrorLog [post] -func (r *OpenRestyController) ClearErrorLog(ctx http.Context) http.Response { - if out, err := shell.Execf("echo '' > /www/wwwlogs/openresty_error.log"); err != nil { - return h.Error(ctx, http.StatusInternalServerError, out) - } - - return h.Success(ctx, nil) -} - -// Load -// -// @Summary 获取负载状态 -// @Tags 插件-OpenResty -// @Produce json -// @Security BearerToken -// @Success 200 {object} controllers.SuccessResponse -// @Router /plugins/openresty/load [get] -func (r *OpenRestyController) Load(ctx http.Context) http.Response { - client := resty.New().SetTimeout(10 * time.Second) - resp, err := client.R().Get("http://127.0.0.1/nginx_status") - if err != nil || !resp.IsSuccess() { - return h.Success(ctx, []types.NV{}) - } - - raw := resp.String() - var data []types.NV - - workers, err := shell.Execf("ps aux | grep nginx | grep 'worker process' | wc -l") - if err != nil { - return h.Error(ctx, http.StatusInternalServerError, "获取负载失败") - } - data = append(data, types.NV{ - Name: "工作进程", - Value: workers, - }) - - out, err := shell.Execf("ps aux | grep nginx | grep 'worker process' | awk '{memsum+=$6};END {print memsum}'") - if err != nil { - return h.Error(ctx, http.StatusInternalServerError, "获取负载失败") - } - mem := str.FormatBytes(cast.ToFloat64(out)) - data = append(data, types.NV{ - Name: "内存占用", - Value: mem, - }) - - match := regexp.MustCompile(`Active connections:\s+(\d+)`).FindStringSubmatch(raw) - if len(match) == 2 { - data = append(data, types.NV{ - Name: "活跃连接数", - Value: match[1], - }) - } - - match = regexp.MustCompile(`server accepts handled requests\s+(\d+)\s+(\d+)\s+(\d+)`).FindStringSubmatch(raw) - if len(match) == 4 { - data = append(data, types.NV{ - Name: "总连接次数", - Value: match[1], - }) - data = append(data, types.NV{ - Name: "总握手次数", - Value: match[2], - }) - data = append(data, types.NV{ - Name: "总请求次数", - Value: match[3], - }) - } - - match = regexp.MustCompile(`Reading:\s+(\d+)\s+Writing:\s+(\d+)\s+Waiting:\s+(\d+)`).FindStringSubmatch(raw) - if len(match) == 4 { - data = append(data, types.NV{ - Name: "请求数", - Value: match[1], - }) - data = append(data, types.NV{ - Name: "响应数", - Value: match[2], - }) - data = append(data, types.NV{ - Name: "驻留进程", - Value: match[3], - }) - } - - return h.Success(ctx, data) -} diff --git a/app/http/controllers/plugins/fail2ban_controller.go b/app/plugins/fail2ban/controller.go similarity index 94% rename from app/http/controllers/plugins/fail2ban_controller.go rename to app/plugins/fail2ban/controller.go index 600709739b..9df9ac431e 100644 --- a/app/http/controllers/plugins/fail2ban_controller.go +++ b/app/plugins/fail2ban/controller.go @@ -1,4 +1,4 @@ -package plugins +package openresty import ( "regexp" @@ -19,18 +19,18 @@ import ( "github.com/TheTNB/panel/v2/pkg/types" ) -type Fail2banController struct { +type Controller struct { website internal.Website } -func NewFail2banController() *Fail2banController { - return &Fail2banController{ +func NewController() *Controller { + return &Controller{ website: services.NewWebsiteImpl(), } } // List 所有 Fail2ban 规则 -func (r *Fail2banController) List(ctx http.Context) http.Response { +func (r *Controller) List(ctx http.Context) http.Response { raw, err := io.Read("/etc/fail2ban/jail.local") if err != nil { return h.Error(ctx, http.StatusUnprocessableEntity, err.Error()) @@ -77,7 +77,7 @@ func (r *Fail2banController) List(ctx http.Context) http.Response { } // Add 添加 Fail2ban 规则 -func (r *Fail2banController) Add(ctx http.Context) http.Response { +func (r *Controller) Add(ctx http.Context) http.Response { if sanitize := h.Sanitize(ctx, map[string]string{ "name": "required", "type": "required|in:website,service", @@ -217,7 +217,7 @@ logpath = ` + logPath + ` } // Delete 删除规则 -func (r *Fail2banController) Delete(ctx http.Context) http.Response { +func (r *Controller) Delete(ctx http.Context) http.Response { jailName := ctx.Request().Input("name") raw, err := io.Read("/etc/fail2ban/jail.local") if err != nil { @@ -242,7 +242,7 @@ func (r *Fail2banController) Delete(ctx http.Context) http.Response { } // BanList 获取封禁列表 -func (r *Fail2banController) BanList(ctx http.Context) http.Response { +func (r *Controller) BanList(ctx http.Context) http.Response { name := ctx.Request().Input("name") if len(name) == 0 { return h.Error(ctx, http.StatusUnprocessableEntity, "缺少参数") @@ -283,7 +283,7 @@ func (r *Fail2banController) BanList(ctx http.Context) http.Response { } // Unban 解封 -func (r *Fail2banController) Unban(ctx http.Context) http.Response { +func (r *Controller) Unban(ctx http.Context) http.Response { name := ctx.Request().Input("name") ip := ctx.Request().Input("ip") if len(name) == 0 || len(ip) == 0 { @@ -298,7 +298,7 @@ func (r *Fail2banController) Unban(ctx http.Context) http.Response { } // SetWhiteList 设置白名单 -func (r *Fail2banController) SetWhiteList(ctx http.Context) http.Response { +func (r *Controller) SetWhiteList(ctx http.Context) http.Response { ip := ctx.Request().Input("ip") if len(ip) == 0 { return h.Error(ctx, http.StatusUnprocessableEntity, "缺少参数") @@ -327,7 +327,7 @@ func (r *Fail2banController) SetWhiteList(ctx http.Context) http.Response { } // GetWhiteList 获取白名单 -func (r *Fail2banController) GetWhiteList(ctx http.Context) http.Response { +func (r *Controller) GetWhiteList(ctx http.Context) http.Response { raw, err := io.Read("/etc/fail2ban/jail.local") if err != nil { return h.Error(ctx, http.StatusUnprocessableEntity, err.Error()) diff --git a/app/plugins/fail2ban/main.go b/app/plugins/fail2ban/main.go new file mode 100644 index 0000000000..ab3621c549 --- /dev/null +++ b/app/plugins/fail2ban/main.go @@ -0,0 +1,39 @@ +package openresty + +import ( + "github.com/goravel/framework/contracts/foundation" + "github.com/goravel/framework/contracts/route" + + "github.com/TheTNB/panel/v2/app/http/middleware" + "github.com/TheTNB/panel/v2/app/plugins/loader" + "github.com/TheTNB/panel/v2/pkg/types" +) + +func init() { + loader.Register(&types.Plugin{ + Name: "Fail2ban", + Description: "Fail2ban 扫描系统日志文件并从中找出多次尝试失败的IP地址,将该IP地址加入防火墙的拒绝访问列表中", + Slug: "fail2ban", + Version: "1.0.2", + Requires: []string{}, + Excludes: []string{}, + Install: `bash /www/panel/scripts/fail2ban/install.sh`, + Uninstall: `bash /www/panel/scripts/fail2ban/uninstall.sh`, + Update: `bash /www/panel/scripts/fail2ban/update.sh`, + Boot: func(app foundation.Application) { + RouteFacade := app.MakeRoute() + RouteFacade.Prefix("api/plugins/fail2ban").Middleware(middleware.Session(), middleware.MustInstall()).Group(func(r route.Router) { + r.Prefix("openresty").Group(func(route route.Router) { + controller := NewController() + route.Get("jails", controller.List) + route.Post("jails", controller.Add) + route.Delete("jails", controller.Delete) + route.Get("jails/{name}", controller.BanList) + route.Post("unban", controller.Unban) + route.Post("whiteList", controller.SetWhiteList) + route.Get("whiteList", controller.GetWhiteList) + }) + }) + }, + }) +} diff --git a/app/http/controllers/plugins/frp_controller.go b/app/plugins/frp_controller.go similarity index 100% rename from app/http/controllers/plugins/frp_controller.go rename to app/plugins/frp_controller.go diff --git a/app/http/controllers/plugins/gitea_controller.go b/app/plugins/gitea_controller.go similarity index 100% rename from app/http/controllers/plugins/gitea_controller.go rename to app/plugins/gitea_controller.go diff --git a/app/plugins/loader/loader.go b/app/plugins/loader/loader.go index 63cee12046..21efd81d41 100644 --- a/app/plugins/loader/loader.go +++ b/app/plugins/loader/loader.go @@ -11,7 +11,7 @@ func All() []*types.Plugin { return data } -// New 新注册插件 -func New(plugin *types.Plugin) { +// Register 注册插件 +func Register(plugin *types.Plugin) { data = append(data, plugin) } diff --git a/app/http/controllers/plugins/mysql_controller.go b/app/plugins/mysql_controller.go similarity index 100% rename from app/http/controllers/plugins/mysql_controller.go rename to app/plugins/mysql_controller.go diff --git a/app/plugins/openresty/main.go b/app/plugins/openresty/main.go index 70a6aaa41f..aaa4da0f2f 100644 --- a/app/plugins/openresty/main.go +++ b/app/plugins/openresty/main.go @@ -10,7 +10,7 @@ import ( ) func init() { - loader.New(&types.Plugin{ + loader.Register(&types.Plugin{ Name: "OpenResty", Description: "OpenResty® 是一款基于 NGINX 和 LuaJIT 的 Web 平台", Slug: "openresty", diff --git a/app/http/controllers/plugins/php_controller.go b/app/plugins/php_controller.go similarity index 100% rename from app/http/controllers/plugins/php_controller.go rename to app/plugins/php_controller.go diff --git a/app/http/controllers/plugins/phpmyadmin_controller.go b/app/plugins/phpmyadmin_controller.go similarity index 100% rename from app/http/controllers/plugins/phpmyadmin_controller.go rename to app/plugins/phpmyadmin_controller.go diff --git a/app/http/controllers/plugins/podman_controller.go b/app/plugins/podman_controller.go similarity index 100% rename from app/http/controllers/plugins/podman_controller.go rename to app/plugins/podman_controller.go diff --git a/app/http/controllers/plugins/postgresql_controller.go b/app/plugins/postgresql_controller.go similarity index 100% rename from app/http/controllers/plugins/postgresql_controller.go rename to app/plugins/postgresql_controller.go diff --git a/app/http/controllers/plugins/pureftpd_controller.go b/app/plugins/pureftpd_controller.go similarity index 100% rename from app/http/controllers/plugins/pureftpd_controller.go rename to app/plugins/pureftpd_controller.go diff --git a/app/http/controllers/plugins/redis_controller.go b/app/plugins/redis_controller.go similarity index 100% rename from app/http/controllers/plugins/redis_controller.go rename to app/plugins/redis_controller.go diff --git a/app/http/controllers/plugins/rsync_controller.go b/app/plugins/rsync_controller.go similarity index 100% rename from app/http/controllers/plugins/rsync_controller.go rename to app/plugins/rsync_controller.go diff --git a/app/http/controllers/plugins/s3fs_controller.go b/app/plugins/s3fs_controller.go similarity index 100% rename from app/http/controllers/plugins/s3fs_controller.go rename to app/plugins/s3fs_controller.go diff --git a/app/http/controllers/plugins/supervisor_controller.go b/app/plugins/supervisor_controller.go similarity index 100% rename from app/http/controllers/plugins/supervisor_controller.go rename to app/plugins/supervisor_controller.go diff --git a/app/http/controllers/plugins/toolbox_controller.go b/app/plugins/toolbox_controller.go similarity index 100% rename from app/http/controllers/plugins/toolbox_controller.go rename to app/plugins/toolbox_controller.go