🆕新增接口控制服务端、命令控制服务端

This commit is contained in:
coward 2024-03-22 10:42:36 +08:00
parent a988b66ccd
commit 86c76add17
10 changed files with 142 additions and 44 deletions

View File

@ -8,62 +8,60 @@ import (
"wireguard-dashboard/repository" "wireguard-dashboard/repository"
) )
// RestartWireguard // getConfigFileName
// @description: 重启wireguard服务端 // @description: 获取服务端配置文件名称
func RestartWireguard() { // @return string
configPath, err := repository.System().GetServerSetting() func getConfigFileName() string {
data, err := repository.System().GetServerSetting()
if err != nil { if err != nil {
log.Errorf("获取服务端配置失败: %v", err.Error()) log.Errorf("获取服务端配置失败: %v", err.Error())
return return ""
} }
if configPath.ConfigFilePath != "" { if data.ConfigFilePath != "" {
configPath.ConfigFilePath = strings.Split(configPath.ConfigFilePath, "/")[len(strings.Split(configPath.ConfigFilePath, "/"))-1] data.ConfigFilePath = strings.Split(data.ConfigFilePath, "/")[len(strings.Split(data.ConfigFilePath, "/"))-1] // 这里取到的是wg0.conf
data.ConfigFilePath = strings.Split(data.ConfigFilePath, ".conf")[0] // 这里取到的就是wg0
} }
if err = exec.Command(fmt.Sprintf("wg-quick down %s", configPath.ConfigFilePath)).Run(); err != nil { return data.ConfigFilePath
log.Errorf("停止wireguard服务端失败: %v", err.Error()) }
}
if err = exec.Command(fmt.Sprintf("wg-quick up %s", configPath.ConfigFilePath)).Run(); err != nil { // RestartWireguard
log.Errorf("启动wireguard服务端失败: %v", err.Error()) // @description: 是否重启
// @param isAsync // 是否异步执行
func RestartWireguard(isAsync bool) {
if isAsync {
go func() {
StopWireguard() // 停止
StartWireguard() // 启动
}()
} else {
StopWireguard() // 停止
StartWireguard() // 启动
} }
return return
} }
// StopWireguard // StopWireguard
// @description: 停止服务端 // @description: 停止服务端
func StopWireguard() { func StopWireguard() {
configPath, err := repository.System().GetServerSetting() configFileName := getConfigFileName()
if err != nil {
log.Errorf("获取服务端配置失败: %v", err.Error())
return
}
if configPath.ConfigFilePath != "" { if err := exec.Command(fmt.Sprintf("wg-quick down %s", configFileName)).Run(); err != nil {
configPath.ConfigFilePath = strings.Split(configPath.ConfigFilePath, "/")[len(strings.Split(configPath.ConfigFilePath, "/"))-1]
}
if err = exec.Command(fmt.Sprintf("wg-quick down %s", configPath.ConfigFilePath)).Run(); err != nil {
log.Errorf("停止wireguard服务端失败: %v", err.Error()) log.Errorf("停止wireguard服务端失败: %v", err.Error())
} }
return
} }
// StartWireguard // StartWireguard
// @description: 启动服务端 // @description: 启动服务端
func StartWireguard() { func StartWireguard() {
configPath, err := repository.System().GetServerSetting() configFileName := getConfigFileName()
if err != nil {
log.Errorf("获取服务端配置失败: %v", err.Error())
return
}
if configPath.ConfigFilePath != "" { if err := exec.Command(fmt.Sprintf("wg-quick up %s", configFileName)).Run(); err != nil {
configPath.ConfigFilePath = strings.Split(configPath.ConfigFilePath, "/")[len(strings.Split(configPath.ConfigFilePath, "/"))-1]
}
if err = exec.Command(fmt.Sprintf("wg-quick up %s", configPath.ConfigFilePath)).Run(); err != nil {
log.Errorf("启动wireguard服务端失败: %v", err.Error()) log.Errorf("启动wireguard服务端失败: %v", err.Error())
} }
return
} }

View File

@ -2,6 +2,9 @@ package component
import ( import (
"gitee.ltd/lxh/logger/log" "gitee.ltd/lxh/logger/log"
"gopkg.in/fsnotify.v1"
"wireguard-dashboard/command"
"wireguard-dashboard/config"
"wireguard-dashboard/utils" "wireguard-dashboard/utils"
) )
@ -15,7 +18,7 @@ func Wireguard() wireguard {
// @description: 应用配置 // @description: 应用配置
// @receiver wireguard // @receiver wireguard
// @return err // @return err
func (wireguard) Apply(templateFilePath, configFilePath string, data any) (err error) { func (w wireguard) Apply(templateFilePath, configFilePath string, data any) (err error) {
parseTemplate, err := utils.Template().Parse(templateFilePath) parseTemplate, err := utils.Template().Parse(templateFilePath)
if err != nil { if err != nil {
@ -29,5 +32,56 @@ func (wireguard) Apply(templateFilePath, configFilePath string, data any) (err e
return err return err
} }
// 判断服务端重启规则
switch config.Config.Wireguard.ListenConfig {
case "auto":
w.watchListConfig(configFilePath)
}
return nil return nil
} }
// watchListConfig
// @description: 监听配置文件变化
// @receiver wireguard
// @return err
func (wireguard) watchListConfig(filePath string) {
go func() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Errorf("创建文件监控失败: %v", err.Error())
return
}
defer watcher.Close()
done := make(chan bool)
go func() {
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Op == fsnotify.Write {
command.RestartWireguard(true)
}
// 打印监听事件
log.Errorf("监听事件是:%s", event.String())
case _, ok := <-watcher.Errors:
if !ok {
return
}
}
}
}()
if err = watcher.Add(filePath); err != nil {
log.Errorf("添加[%s]监听失败: %v", filePath, err.Error())
return
}
<-done
}()
}

View File

@ -3,8 +3,9 @@ package config
var Config *config var Config *config
type config struct { type config struct {
Http *http `yaml:"http"` Http *http `yaml:"http"`
Database *database `yaml:"database"` Database *database `yaml:"database"`
Redis *redis `yaml:"redis"` Redis *redis `yaml:"redis"`
File *file `yaml:"file"` File *file `yaml:"file"`
Wireguard wireguard `yaml:"wireguard"`
} }

5
config/wireguard.go Normal file
View File

@ -0,0 +1,5 @@
package config
type wireguard struct {
ListenConfig string `json:"listenConfig" yaml:"listenConfig"`
}

5
go.mod
View File

@ -5,6 +5,7 @@ go 1.21
require ( require (
gitee.ltd/lxh/logger v1.0.15 gitee.ltd/lxh/logger v1.0.15
github.com/cowardmrx/go_aliyun_oss v1.0.7 github.com/cowardmrx/go_aliyun_oss v1.0.7
github.com/dustin/go-humanize v1.0.1
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/go-resty/resty/v2 v2.11.0 github.com/go-resty/resty/v2 v2.11.0
github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang-jwt/jwt/v5 v5.2.1
@ -15,6 +16,7 @@ require (
github.com/spf13/cast v1.6.0 github.com/spf13/cast v1.6.0
golang.org/x/crypto v0.21.0 golang.org/x/crypto v0.21.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
gopkg.in/fsnotify.v1 v1.4.7
gopkg.in/yaml.v3 v3.0.1 gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/mysql v1.5.4 gorm.io/driver/mysql v1.5.4
gorm.io/driver/postgres v1.5.6 gorm.io/driver/postgres v1.5.6
@ -30,7 +32,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/kit v0.12.0 // indirect
@ -69,7 +71,6 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.13.0 // indirect github.com/prometheus/client_golang v1.13.0 // indirect

5
go.sum
View File

@ -199,6 +199,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -626,8 +628,6 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
@ -1273,6 +1273,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=

View File

@ -91,6 +91,13 @@ func (clients) Delete(c *gin.Context) {
return return
} }
// 再同步一下配置文件
go func() {
if err := queues.PutAsyncWireguardConfigFile(""); err != nil {
log.Errorf("[下线客户端]同步配置文件失败: %v", err.Error())
}
}()
utils.GinResponse(c).OK() utils.GinResponse(c).OK()
} }

View File

@ -5,6 +5,7 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes" "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"strings" "strings"
"wireguard-dashboard/command"
"wireguard-dashboard/http/param" "wireguard-dashboard/http/param"
"wireguard-dashboard/model/entity" "wireguard-dashboard/model/entity"
"wireguard-dashboard/queues" "wireguard-dashboard/queues"
@ -89,3 +90,26 @@ func (server) GetServer(c *gin.Context) {
utils.GinResponse(c).OKWithData(data) utils.GinResponse(c).OKWithData(data)
} }
// ControlServer
// @description: 服务端控制器
// @receiver server
// @param c
func (server) ControlServer(c *gin.Context) {
var p param.ControlServer
if err := c.ShouldBind(&p); err != nil {
utils.GinResponse(c).FailedWithErr("参数错误", err)
return
}
switch p.Status {
case "START":
command.StartWireguard()
case "STOP":
command.StopWireguard()
case "RESTART":
command.RestartWireguard(false)
}
utils.GinResponse(c).OK()
}

View File

@ -31,3 +31,9 @@ type SaveClient struct {
Keys *template_data.Keys `json:"keys" form:"keys" binding:"omitempty"` Keys *template_data.Keys `json:"keys" form:"keys" binding:"omitempty"`
Enabled int `json:"enabled" form:"enabled" binding:"required,oneof=1 0"` Enabled int `json:"enabled" form:"enabled" binding:"required,oneof=1 0"`
} }
// ControlServer
// @description: 服务端控制
type ControlServer struct {
Status string `json:"status" form:"status" binding:"required,oneof=START STOP RESTART"`
}

View File

@ -9,7 +9,8 @@ import (
func ServerApi(r *gin.RouterGroup) { func ServerApi(r *gin.RouterGroup) {
apiGroup := r.Group("server", middleware.Authorization()) apiGroup := r.Group("server", middleware.Authorization())
{ {
apiGroup.GET("", api.Server().GetServer) // 获取服务端信息 apiGroup.GET("", api.Server().GetServer) // 获取服务端信息
apiGroup.POST("", middleware.Permission(), api.Server().SaveServer) // 新增/更新服务端信息 apiGroup.POST("", middleware.Permission(), api.Server().SaveServer) // 新增/更新服务端信息
apiGroup.POST("control-server", middleware.Permission(), api.Server().ControlServer) // 服务端操作控制
} }
} }