diff --git a/http/api/client.go b/http/api/client.go index 3392513..a02677c 100644 --- a/http/api/client.go +++ b/http/api/client.go @@ -253,12 +253,6 @@ func (clients) GenerateQrCode(c *gin.Context) { // @receiver clients // @param c func (clients) Status(c *gin.Context) { - var p param.ClientStatusList - if err := c.ShouldBind(&p); err != nil { - utils.GinResponse(c).FailedWithErr("参数错误", err) - return - } - // 使用sdk拉取一下客户端信息 devices, err := client.WireguardClient.Devices() if err != nil { @@ -282,6 +276,7 @@ func (clients) Status(c *gin.Context) { ipAllocation = strings.TrimRight(ipAllocation, ",") isOnline := p.LastHandshakeTime.Minute() < 1 data = append(data, vo.ClientStatus{ + ID: clientInfo.Id, Name: clientInfo.Name, Email: clientInfo.Email, IpAllocation: ipAllocation, @@ -296,3 +291,51 @@ func (clients) Status(c *gin.Context) { utils.GinResponse(c).OKWithData(data) } + +// Offline +// @description: 强制下线指定客户端 +// @receiver clients +// @param c +func (clients) Offline(c *gin.Context) { + id := c.Param("id") + if id == "" || id == "undefined" { + utils.GinResponse(c).FailedWithMsg("参数错误") + return + } + + // 查询一下客户端信息 + clientInfo, err := repository.Client().GetById(id) + if err != nil { + utils.GinResponse(c).FailedWithMsg("获取信息失败") + return + } + + keys := template_data.Keys{} + _ = json.Unmarshal([]byte(clientInfo.Keys), &keys) + + connectInfo, err := utils.Wireguard().GetSpecClient(keys.PublicKey) + if err != nil { + utils.GinResponse(c).FailedWithMsg("获取客户端信息失败") + return + } + + if connectInfo == nil { + utils.GinResponse(c).FailedWithMsg("未获取到该客户端链接信息") + return + } + + // 获取到了,执行踢下线操作。此处踢下线就是禁用该客户端 + if err = repository.Client().Disabled(clientInfo.Id); err != nil { + utils.GinResponse(c).FailedWithErr("客户端下线失败: %v", err) + return + } + + // 再同步一下配置文件 + go func() { + if err = queues.PutAsyncWireguardConfigFile(clientInfo.ServerId); err != nil { + log.Errorf("[下线客户端]同步配置文件失败: %v", err.Error()) + } + }() + + utils.GinResponse(c).OK() +} diff --git a/model/vo/client.go b/model/vo/client.go index ef09616..7a8bb55 100644 --- a/model/vo/client.go +++ b/model/vo/client.go @@ -28,6 +28,7 @@ type Client struct { } type ClientStatus struct { + ID string `json:"id"` Name string `json:"name"` Email string `json:"email"` IpAllocation string `json:"IpAllocation"` diff --git a/repository/client.go b/repository/client.go index c7bc0c8..70d41f5 100644 --- a/repository/client.go +++ b/repository/client.go @@ -175,3 +175,12 @@ func (r clientRepo) GetByPublicKey(publicKey string) (data entity.Client, err er err = r.Model(&entity.Client{}).Where("keys->$.publicKey = ?", publicKey).Preload("Server").First(&data).Error return } + +// Disabled +// @description: 禁用客户端 +// @receiver r +// @param id +// @return err +func (r clientRepo) Disabled(id string) (err error) { + return r.Model(&entity.Client{}).Where("id = ?", id).Update("status", 0).Error +} diff --git a/route/client.go b/route/client.go index 8be0b6a..3f55af9 100644 --- a/route/client.go +++ b/route/client.go @@ -14,5 +14,7 @@ func ClientApi(r *gin.RouterGroup) { apiGroup.DELETE(":id", middleware.Permission(), api.Client().Delete) // 删除客户端 apiGroup.POST("download/:id", api.Client().Download) // 下载客户端配置文件 apiGroup.POST("generate-qrcode/:id", api.Client().GenerateQrCode) // 生成客户端二维码 + apiGroup.GET("status", api.Client().Status) // 获取客户端链接状态监听列表 + apiGroup.POST("offline/:id", api.Client().Offline) // 强制下线指定客户端 } } diff --git a/utils/wireguard.go b/utils/wireguard.go index d4b585b..c126575 100644 --- a/utils/wireguard.go +++ b/utils/wireguard.go @@ -1 +1,35 @@ package utils + +import ( + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "wireguard-dashboard/client" +) + +type wireguard struct{} + +func Wireguard() wireguard { + return wireguard{} +} + +// GetSpecClient +// @description: 获取指定客户端链接信息 +// @receiver wireguard +// @param pk +// @return *wgtypes.Peer +// @return error +func (wireguard) GetSpecClient(pk string) (*wgtypes.Peer, error) { + device, err := client.WireguardClient.Devices() + if err != nil { + return nil, err + } + + for _, v := range device { + for _, p := range v.Peers { + if p.PublicKey.String() == pk { + return &p, nil + } + } + } + + return nil, nil +}