12 Commits

Author SHA1 Message Date
dependabot[bot]
e00514674c build(deps): bump google.golang.org/protobuf from 1.34.2 to 1.36.4
Bumps google.golang.org/protobuf from 1.34.2 to 1.36.4.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-24 15:53:12 +00:00
dependabot[bot]
b1f5ccfee8 build(deps): bump github.com/eko/gocache/store/go_cache/v4 (#701)
Bumps [github.com/eko/gocache/store/go_cache/v4](https://github.com/eko/gocache) from 4.2.1 to 4.2.2.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/store/redis/v4.2.1...store/redis/v4.2.2)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/store/go_cache/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-31 11:30:13 +08:00
dependabot[bot]
2f88334373 build(deps): bump golang.org/x/crypto from 0.25.0 to 0.28.0 (#704)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.25.0 to 0.28.0.
- [Commits](https://github.com/golang/crypto/compare/v0.25.0...v0.28.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-31 11:29:51 +08:00
dependabot[bot]
35e726e766 build(deps): bump golang.org/x/time from 0.5.0 to 0.7.0 (#703)
Bumps [golang.org/x/time](https://github.com/golang/time) from 0.5.0 to 0.7.0.
- [Commits](https://github.com/golang/time/compare/v0.5.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/time
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-31 11:29:31 +08:00
sakzri
4bbf3c9899 fix: handle domain with wildcards (#690) 2024-10-19 22:04:08 +08:00
RyarX
9391c759c9 New transports and api changes for V2RaySocks (#685)
* New transports and api changes for V2RaySocks

* version++
2024-10-19 22:03:05 +08:00
dependabot[bot]
eb16b709e2 build(deps): bump github.com/shirou/gopsutil/v3 from 3.24.2 to 3.24.5 (#666)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.24.2 to 3.24.5.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.24.2...v3.24.5)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 22:01:46 +08:00
dependabot[bot]
1f09502613 build(deps): bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (#665)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 22:01:24 +08:00
dependabot[bot]
0ae73a0eca build(deps): bump actions/download-artifact in /.github/workflows (#688)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4.1.7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3...v4.1.7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 22:00:58 +08:00
pings
63c1a18a7d Optimize and upgrade docking parameters (#696) 2024-10-19 22:00:11 +08:00
dependabot[bot]
34726d1659 build(deps): bump github.com/eko/gocache/lib/v4 from 4.1.5 to 4.1.6 (#668)
Bumps [github.com/eko/gocache/lib/v4](https://github.com/eko/gocache) from 4.1.5 to 4.1.6.
- [Release notes](https://github.com/eko/gocache/releases)
- [Commits](https://github.com/eko/gocache/compare/lib/v4.1.5...lib/v4.1.6)

---
updated-dependencies:
- dependency-name: github.com/eko/gocache/lib/v4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 21:59:06 +08:00
dependabot[bot]
5edc68d475 build(deps): bump github.com/redis/go-redis/v9 from 9.5.1 to 9.7.0 (#699)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.5.1 to 9.7.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.5.1...v9.7.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-19 21:57:38 +08:00
10 changed files with 343 additions and 430 deletions

View File

@@ -64,7 +64,7 @@ jobs:
- build
steps:
- name: Download digests
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4.1.7
with:
name: digests
path: /tmp/digests

View File

@@ -2,92 +2,71 @@ package gov2panel
import (
"bufio"
"encoding/json"
"context"
"errors"
"fmt"
"log"
"os"
"regexp"
"strconv"
"strings"
"sync/atomic"
"time"
log "github.com/sirupsen/logrus"
"github.com/bitly/go-simplejson"
"github.com/go-resty/resty/v2"
"github.com/gogf/gf/v2/util/gconv"
"github.com/XrayR-project/XrayR/api"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/gclient"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/infra/conf"
"github.com/XrayR-project/XrayR/api"
)
// APIClient create an api client to the panel.
// APIClient API config
type APIClient struct {
client *resty.Client
APIHost string
NodeID int
Key string
NodeType string
EnableVless bool
VlessFlow string
SpeedLimit float64
DeviceLimit int
ctx context.Context
APIHost string
NodeID int
Key string
NodeType string
EnableVless bool
VlessFlow string
Timeout int
SpeedLimit float64
DeviceLimit int
RuleListPath string
DisableCustomConfig bool
LocalRuleList []api.DetectRule
resp atomic.Value
eTags map[string]string
}
// New create an api instance
func New(apiConfig *api.Config) *APIClient {
client := resty.New()
client.SetRetryCount(3)
if apiConfig.Timeout > 0 {
client.SetTimeout(time.Duration(apiConfig.Timeout) * time.Second)
} else {
client.SetTimeout(5 * time.Second)
}
client.OnError(func(req *resty.Request, err error) {
if v, ok := err.(*resty.ResponseError); ok {
// v.Response contains the last response from the server
// v.Err contains the original error
log.Print(v.Err)
}
})
client.SetBaseURL(apiConfig.APIHost)
// Create Key for each requests
client.SetQueryParams(map[string]string{
"node_id": strconv.Itoa(apiConfig.NodeID),
"node_type": strings.ToLower(apiConfig.NodeType),
"token": apiConfig.Key,
})
// Read local rule list
localRuleList := readLocalRuleList(apiConfig.RuleListPath)
//https://goframe.org/pages/viewpage.action?pageId=1114381
apiClient := &APIClient{
client: client,
NodeID: apiConfig.NodeID,
Key: apiConfig.Key,
APIHost: apiConfig.APIHost,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
VlessFlow: apiConfig.VlessFlow,
SpeedLimit: apiConfig.SpeedLimit,
DeviceLimit: apiConfig.DeviceLimit,
LocalRuleList: localRuleList,
eTags: make(map[string]string),
ctx: context.Background(),
APIHost: apiConfig.APIHost,
NodeID: apiConfig.NodeID,
Key: apiConfig.Key,
NodeType: apiConfig.NodeType,
EnableVless: apiConfig.EnableVless,
VlessFlow: apiConfig.VlessFlow,
Timeout: apiConfig.Timeout,
DeviceLimit: apiConfig.DeviceLimit,
RuleListPath: apiConfig.RuleListPath,
DisableCustomConfig: apiConfig.DisableCustomConfig,
LocalRuleList: readLocalRuleList(apiConfig.RuleListPath), //加载本地路由规则
}
return apiClient
}
// readLocalRuleList reads the local rule list file
func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
LocalRuleList = make([]api.DetectRule, 0)
LocalRuleList = make([]api.DetectRule, 0)
if path != "" {
// open the file
file, err := os.Open(path)
defer file.Close()
// handle errors while opening
if err != nil {
log.Printf("Error when opening file: %s", err)
@@ -108,96 +87,77 @@ func readLocalRuleList(path string) (LocalRuleList []api.DetectRule) {
log.Fatalf("Error while reading file: %s", err)
return
}
file.Close()
}
return LocalRuleList
}
// Describe return a description of the client
func (c *APIClient) Describe() api.ClientInfo {
return api.ClientInfo{APIHost: c.APIHost, NodeID: c.NodeID, Key: c.Key, NodeType: c.NodeType}
}
// Debug set the client debug for client
func (c *APIClient) Debug() {
c.client.SetDebug(true)
}
func (c *APIClient) assembleURL(path string) string {
return c.APIHost + path
}
func (c *APIClient) parseResponse(res *resty.Response, path string, err error) (*simplejson.Json, error) {
if err != nil {
return nil, fmt.Errorf("request %s failed: %v", c.assembleURL(path), err)
}
if res.StatusCode() > 399 {
return nil, fmt.Errorf("request %s failed: %s, %v", c.assembleURL(path), res.String(), err)
}
rtn, err := simplejson.NewJson(res.Body())
if err != nil {
return nil, fmt.Errorf("ret %s invalid", res.String())
}
return rtn, nil
}
// GetNodeInfo will pull NodeInfo Config from panel
func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
server := new(serverConfig)
path := "/api/server/config"
res, err := c.client.R().
SetHeader("If-None-Match", c.eTags["node"]).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.NodeNotModified)
}
// update etag
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTags["node"] {
c.eTags["node"] = res.Header().Get("Etag")
}
nodeInfoResp, err := c.parseResponse(res, path, err)
apiPath := "/api/server/config"
reslutJson, err := c.sendRequest(
nil,
"POST",
apiPath,
g.Map{})
if err != nil {
return nil, err
}
b, _ := nodeInfoResp.Encode()
json.Unmarshal(b, server)
if gconv.Uint32(server.Port) == 0 {
if reslutJson.Get("data").String() == "" {
return nil, errors.New("gov2panel node config data is null")
}
if reslutJson.Get("data.port").Int() == 0 {
return nil, errors.New("server port must > 0")
}
c.resp.Store(server)
switch c.NodeType {
case "V2ray", "Vmess", "Vless":
nodeInfo, err = c.parseV2rayNodeResponse(server)
case "Trojan":
nodeInfo, err = c.parseTrojanNodeResponse(server)
case "Shadowsocks":
nodeInfo, err = c.parseSSNodeResponse(server)
default:
return nil, fmt.Errorf("unsupported node type: %s", c.NodeType)
}
nodeInfo = new(api.NodeInfo)
err = reslutJson.Get("data").Scan(nodeInfo)
if err != nil {
return nil, fmt.Errorf("parse node info failed: %s, \nError: %v", res.String(), err)
return nil, fmt.Errorf("parse node info failed: \nError: %v", err)
}
routes := make([]route, 0)
err = reslutJson.Get("data.routes").Scan(&routes)
if err != nil {
return nil, fmt.Errorf("parse node routes failed: \nError: %v", err)
}
nodeInfo.NodeType = c.NodeType
nodeInfo.NodeID = c.NodeID
nodeInfo.EnableVless = c.EnableVless
nodeInfo.VlessFlow = c.VlessFlow
nodeInfo.AlterID = 0
nodeInfo.NameServerConfig = parseDNSConfig(routes)
return nodeInfo, nil
}
func parseDNSConfig(routes []route) (nameServerList []*conf.NameServerConfig) {
nameServerList = make([]*conf.NameServerConfig, 0)
for i := range routes {
if routes[i].Action == "dns" {
nameServerList = append(nameServerList, &conf.NameServerConfig{
Address: &conf.Address{Address: net.ParseAddress(routes[i].ActionValue)},
Domains: routes[i].Match,
})
}
}
return
}
// GetUserList will pull user form panel
func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
var users []*user
path := "/api/server/user"
apiPath := "/api/server/user"
switch c.NodeType {
case "V2ray", "Trojan", "Shadowsocks", "Vmess", "Vless":
@@ -206,29 +166,17 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
return nil, fmt.Errorf("unsupported node type: %s", c.NodeType)
}
res, err := c.client.R().
SetHeader("If-None-Match", c.eTags["users"]).
ForceContentType("application/json").
Get(path)
// Etag identifier for a specific version of a resource. StatusCode = 304 means no changed
if res.StatusCode() == 304 {
return nil, errors.New(api.UserNotModified)
}
// update etag
if res.Header().Get("Etag") != "" && res.Header().Get("Etag") != c.eTags["users"] {
c.eTags["users"] = res.Header().Get("Etag")
}
usersResp, err := c.parseResponse(res, path, err)
reslutJson, err := c.sendRequest(
nil,
"GET",
apiPath,
g.Map{})
if err != nil {
return nil, err
}
b, _ := usersResp.Get("users").Encode()
json.Unmarshal(b, &users)
if len(users) == 0 {
return nil, errors.New("users is null")
}
var users []*user
reslutJson.Get("data.users").Scan(&users)
userList := make([]api.UserInfo, len(users))
for i := 0; i < len(users); i++ {
@@ -255,148 +203,126 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
return &userList, nil
}
// ReportUserTraffic reports the user traffic
func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
path := "/api/server/push"
func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
return
}
res, err := c.client.R().SetBody(userTraffic).ForceContentType("application/json").Post(path)
_, err = c.parseResponse(res, path, err)
func (c *APIClient) ReportNodeOnlineUsers(onlineUser *[]api.OnlineUser) (err error) {
return
}
// ReportUserTraffic reports the user traffic
func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) (err error) {
apiPath := "/api/server/push"
reslutJson, err := c.sendRequest(
nil,
"POST",
apiPath,
g.Map{
"data": userTraffic,
})
if err != nil {
return err
}
return nil
}
// GetNodeRule implements the API interface
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
routes := c.resp.Load().(*serverConfig).Routes
ruleList := c.LocalRuleList
for i := range routes {
if routes[i].Action == "block" {
ruleList = append(ruleList, api.DetectRule{
ID: i,
Pattern: regexp.MustCompile(strings.Join(routes[i].Match, "|")),
})
}
}
return &ruleList, nil
}
// ReportNodeStatus implements the API interface
func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
return nil
}
// ReportNodeOnlineUsers implements the API interface
func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) error {
return nil
}
// ReportIllegal implements the API interface
func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
return nil
}
// parseTrojanNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseTrojanNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
// Create GeneralNodeInfo
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: gconv.Uint32(s.Port),
TransportProtocol: "tcp",
EnableTLS: true,
Host: s.Host,
ServiceName: s.Sni,
NameServerConfig: s.parseDNSConfig(),
}
return nodeInfo, nil
}
// parseSSNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseSSNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
var header json.RawMessage
if s.Obfs == "http" {
path := "/"
if p := s.ObfsSettings.Path; p != "" {
if strings.HasPrefix(p, "/") {
path = p
} else {
path += p
}
}
h := simplejson.New()
h.Set("type", "http")
h.SetPath([]string{"request", "path"}, path)
header, _ = h.Encode()
}
// Create GeneralNodeInfo
return &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: gconv.Uint32(s.Port),
TransportProtocol: "tcp",
CypherMethod: s.Encryption,
ServerKey: s.ServerKey, // shadowsocks2022 share key
NameServerConfig: s.parseDNSConfig(),
Header: header,
}, nil
}
// parseV2rayNodeResponse parse the response for the given nodeInfo format
func (c *APIClient) parseV2rayNodeResponse(s *serverConfig) (*api.NodeInfo, error) {
var (
header json.RawMessage
enableTLS bool
)
switch s.Net {
case "tcp":
if s.Header != nil {
if httpHeader, err := s.Header.MarshalJSON(); err != nil {
return nil, err
} else {
header = httpHeader
}
}
}
if s.TLS == "tls" {
enableTLS = true
}
// Create GeneralNodeInfo
return &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: gconv.Uint32(s.Port),
AlterID: 0,
TransportProtocol: s.Net,
EnableTLS: enableTLS,
Path: s.Path,
Host: s.Host,
EnableVless: c.EnableVless,
VlessFlow: c.VlessFlow,
ServiceName: s.Sni,
Header: header,
NameServerConfig: s.parseDNSConfig(),
}, nil
}
func (s *serverConfig) parseDNSConfig() (nameServerList []*conf.NameServerConfig) {
for i := range s.Routes {
if s.Routes[i].Action == "dns" {
nameServerList = append(nameServerList, &conf.NameServerConfig{
Address: &conf.Address{Address: net.ParseAddress(s.Routes[i].ActionValue)},
Domains: s.Routes[i].Match,
})
}
if reslutJson.Get("code").Int() != 0 {
return errors.New(reslutJson.Get("message").String())
}
return
}
func (c *APIClient) Describe() api.ClientInfo {
return api.ClientInfo{APIHost: c.APIHost, NodeID: c.NodeID, Key: c.Key, NodeType: c.NodeType}
}
// GetNodeRule implements the API interface
func (c *APIClient) GetNodeRule() (*[]api.DetectRule, error) {
ruleList := c.LocalRuleList
apiPath := "/api/server/config"
reslutJson, err := c.sendRequest(
nil,
"POST",
apiPath,
g.Map{})
if err != nil {
return nil, err
}
routes := make([]route, 0)
err = reslutJson.Get("data.routes").Scan(&routes)
if err != nil {
return nil, fmt.Errorf("parse node routes failed: \nError: %v", err)
}
for i := range routes {
if routes[i].Action == "block" {
for _, v := range routes[i].Match {
ruleList = append(ruleList, api.DetectRule{
ID: i,
Pattern: regexp.MustCompile(v),
})
}
}
}
return &ruleList, nil
}
func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) (err error) {
return
}
func (c *APIClient) Debug() {
}
// request 统一请求接口
func (c *APIClient) sendRequest(headerM map[string]string, method string, url string, data g.Map) (reslutJson *gjson.Json, err error) {
url = c.APIHost + url
client := gclient.New()
var gResponse *gclient.Response
if c.Timeout > 0 {
client.SetTimeout(time.Duration(c.Timeout) * time.Second) //方法用于设置当前请求超时时间
} else {
client.SetTimeout(5 * time.Second)
}
client.Retry(3, 10*time.Second) //方法用于设置请求失败时重连次数和重连间隔。
client.SetHeaderMap(headerM)
client.SetHeader("Content-Type", "application/json")
data["token"] = c.Key
data["node_id"] = c.NodeID
switch method {
case "GET":
gResponse, err = client.Get(c.ctx, url, data)
case "POST":
gResponse, err = client.Post(c.ctx, url, data)
default:
err = fmt.Errorf("unsupported method: %s", method)
return
}
if err != nil {
return
}
defer gResponse.Close()
reslutJson = gjson.New(gResponse.ReadAllString())
if reslutJson == nil {
err = fmt.Errorf("http reslut to json, err : %s", gResponse.ReadAllString())
}
if reslutJson.Get("code").Int() != 0 {
err = errors.New(reslutJson.Get("message").String())
return
}
return

View File

@@ -5,56 +5,31 @@ import (
"github.com/XrayR-project/XrayR/api"
"github.com/XrayR-project/XrayR/api/gov2panel"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/util/gconv"
)
func CreateClient() api.API {
apiConfig := &api.Config{
APIHost: "http://localhost:8080",
Key: "123456",
NodeID: 1,
NodeID: 90,
NodeType: "V2ray",
}
client := gov2panel.New(apiConfig)
return client
}
func TestGetV2rayNodeInfo(t *testing.T) {
func TestGetNodeInfo(t *testing.T) {
client := CreateClient()
nodeInfo, err := client.GetNodeInfo()
if err != nil {
t.Error(err)
}
t.Log(nodeInfo)
}
func TestGetSSNodeInfo(t *testing.T) {
apiConfig := &api.Config{
APIHost: "http://127.0.0.1:668",
Key: "qwertyuiopasdfghjkl",
NodeID: 1,
NodeType: "Shadowsocks",
}
client := gov2panel.New(apiConfig)
nodeInfo, err := client.GetNodeInfo()
if err != nil {
t.Error(err)
}
t.Log(nodeInfo)
}
func TestGetTrojanNodeInfo(t *testing.T) {
apiConfig := &api.Config{
APIHost: "http://127.0.0.1:668",
Key: "qwertyuiopasdfghjkl",
NodeID: 1,
NodeType: "Trojan",
}
client := gov2panel.New(apiConfig)
nodeInfo, err := client.GetNodeInfo()
if err != nil {
t.Error(err)
}
t.Log(nodeInfo)
nodeInfoJson := gjson.New(nodeInfo)
t.Log(nodeInfoJson.String())
t.Log(nodeInfoJson.String())
}
func TestGetUserList(t *testing.T) {
@@ -65,6 +40,7 @@ func TestGetUserList(t *testing.T) {
t.Error(err)
}
t.Log(len(*userList))
t.Log(userList)
}
@@ -74,24 +50,30 @@ func TestReportReportUserTraffic(t *testing.T) {
if err != nil {
t.Error(err)
}
t.Log(userList)
generalUserTraffic := make([]api.UserTraffic, len(*userList))
for i, userInfo := range *userList {
generalUserTraffic[i] = api.UserTraffic{
UID: userInfo.UID,
Upload: 1111,
Download: 2222,
Upload: 1073741824,
Download: 1073741824,
}
}
// client.Debug()
t.Log(gconv.String(generalUserTraffic))
client = CreateClient()
err = client.ReportUserTraffic(&generalUserTraffic)
if err != nil {
t.Error(err)
}
t.Error(err)
}
func TestGetNodeRule(t *testing.T) {
client := CreateClient()
client.Debug()
ruleList, err := client.GetNodeRule()
if err != nil {
t.Error(err)

View File

@@ -1,35 +1,9 @@
package gov2panel
import "encoding/json"
type serverConfig struct {
v2ray
shadowsocks
//---
Routes []route `json:"routes"`
Header *json.RawMessage `json:"header"`
}
type v2ray struct {
Port string `json:"port"`
Scy string `json:"scy"`
Net string `json:"net"`
Type string `json:"type"`
Host string `json:"host"`
Path string `json:"path"`
TLS string `json:"tls"`
Sni string `json:"sni"`
Alpn string `json:"alpn"`
}
type shadowsocks struct {
Encryption string `json:"encryption"`
Obfs string `json:"obfs"`
ObfsSettings struct {
Path string `json:"path"`
Host string `json:"host"`
} `json:"obfs_settings"`
ServerKey string `json:"server_key"`
type user struct {
Id int `json:"id"`
Uuid string `json:"uuid"`
SpeedLimit int `json:"speed_limit"`
}
type route struct {
@@ -38,9 +12,3 @@ type route struct {
Action string `json:"action"`
ActionValue string `json:"action_value"`
}
type user struct {
Id int `json:"id"`
Uuid string `json:"uuid"`
SpeedLimit int `json:"speed_limit"`
}

View File

@@ -1,7 +1,7 @@
package v2raysocks
type UserTraffic struct {
UID int `json:"user_id"`
UID int `json:"uid"`
Upload int64 `json:"u"`
Download int64 `json:"d"`
}
@@ -19,6 +19,10 @@ type NodeOnline struct {
IP string `json:"ip"`
}
type IllegalItem struct {
UID int `json:"uid"`
}
type REALITYConfig struct {
Dest string `json:"dest,omitempty"`
ProxyProtocolVer uint64 `json:"proxy_protocol_ver,omitempty"`

View File

@@ -159,8 +159,8 @@ func (c *APIClient) GetNodeInfo() (nodeInfo *api.NodeInfo, err error) {
res, err := c.client.R().
SetHeader("If-None-Match", c.eTags["config"]).
SetQueryParams(map[string]string{
"act": "config",
"nodetype": nodeType,
"act": "config",
"node_type": nodeType,
}).
ForceContentType("application/json").
Get(c.APIHost)
@@ -213,8 +213,8 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
res, err := c.client.R().
SetHeader("If-None-Match", c.eTags["user"]).
SetQueryParams(map[string]string{
"act": "user",
"nodetype": nodeType,
"act": "user",
"node_type": nodeType,
}).
ForceContentType("application/json").
Get(c.APIHost)
@@ -239,22 +239,21 @@ func (c *APIClient) GetUserList() (UserList *[]api.UserInfo, err error) {
user.UID = response.Get("data").GetIndex(i).Get("id").MustInt()
switch c.NodeType {
case "Shadowsocks":
user.Email = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("secret").MustString()
user.Passwd = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("secret").MustString()
user.Method = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("cipher").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("speed_limit").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("shadowsocks_user").Get("device_limit").MustInt()
user.Email = response.Get("data").GetIndex(i).Get("secret").MustString()
user.Passwd = response.Get("data").GetIndex(i).Get("secret").MustString()
user.Method = response.Get("data").GetIndex(i).Get("cipher").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt()
case "Trojan":
user.UUID = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString()
user.Email = response.Get("data").GetIndex(i).Get("trojan_user").Get("password").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("trojan_user").Get("speed_limit").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("trojan_user").Get("device_limit").MustInt()
user.UUID = response.Get("data").GetIndex(i).Get("password").MustString()
user.Email = response.Get("data").GetIndex(i).Get("password").MustString()
user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt()
case "V2ray", "Vmess", "Vless":
user.UUID = response.Get("data").GetIndex(i).Get("v2ray_user").Get("uuid").MustString()
user.Email = response.Get("data").GetIndex(i).Get("v2ray_user").Get("email").MustString()
user.AlterID = uint16(response.Get("data").GetIndex(i).Get("v2ray_user").Get("alter_id").MustUint64())
user.SpeedLimit = response.Get("data").GetIndex(i).Get("v2ray_user").Get("speed_limit").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("v2ray_user").Get("device_limit").MustInt()
user.UUID = response.Get("data").GetIndex(i).Get("uuid").MustString()
user.Email = user.UUID + "@x.com"
user.SpeedLimit = response.Get("data").GetIndex(i).Get("st").MustUint64() * 1000000 / 8
user.DeviceLimit = response.Get("data").GetIndex(i).Get("dt").MustInt()
}
if c.SpeedLimit > 0 {
user.SpeedLimit = uint64((c.SpeedLimit * 1000000) / 8)
@@ -283,8 +282,8 @@ func (c *APIClient) ReportUserTraffic(userTraffic *[]api.UserTraffic) error {
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "submit",
"nodetype": strings.ToLower(c.NodeType),
"act": "submit",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(data).
ForceContentType("application/json").
@@ -327,8 +326,8 @@ func (c *APIClient) ReportNodeStatus(nodeStatus *api.NodeStatus) (err error) {
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "nodestatus",
"nodetype": strings.ToLower(c.NodeType),
"act": "nodestatus",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(systemload).
ForceContentType("application/json").
@@ -350,8 +349,8 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "onlineusers",
"nodetype": strings.ToLower(c.NodeType),
"act": "onlineusers",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(data).
ForceContentType("application/json").
@@ -365,6 +364,26 @@ func (c *APIClient) ReportNodeOnlineUsers(onlineUserList *[]api.OnlineUser) erro
// ReportIllegal implements the API interface
func (c *APIClient) ReportIllegal(detectResultList *[]api.DetectResult) error {
data := make([]IllegalItem, len(*detectResultList))
for i, r := range *detectResultList {
data[i] = IllegalItem{
UID: r.UID,
}
}
res, err := c.client.R().
SetQueryParam("node_id", strconv.Itoa(c.NodeID)).
SetQueryParams(map[string]string{
"act": "illegal",
"node_type": strings.ToLower(c.NodeType),
}).
SetBody(data).
ForceContentType("application/json").
Post(c.APIHost)
_, err = c.parseResponse(res, "", err)
if err != nil {
return err
}
return nil
}
@@ -423,7 +442,7 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
var enableTLS bool
var enableVless bool
var enableReality bool
var alterID uint16 = 0
var vlessFlow string
tmpInboundInfo := nodeInfoResponse.Get("inbounds").MustArray()
marshalByte, _ := json.Marshal(tmpInboundInfo[0].(map[string]interface{}))
@@ -436,6 +455,12 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
case "ws":
path = inboundInfo.Get("streamSettings").Get("wsSettings").Get("path").MustString()
host = inboundInfo.Get("streamSettings").Get("wsSettings").Get("headers").Get("Host").MustString()
case "httpupgrade":
host = inboundInfo.Get("streamSettings").Get("httpupgradeSettings").Get("Host").MustString()
path = inboundInfo.Get("streamSettings").Get("httpupgradeSettings").Get("path").MustString()
case "splithttp":
host = inboundInfo.Get("streamSettings").Get("splithttpSettings").Get("Host").MustString()
path = inboundInfo.Get("streamSettings").Get("splithttpSettings").Get("path").MustString()
case "grpc":
if data, ok := inboundInfo.Get("streamSettings").Get("grpcSettings").CheckGet("serviceName"); ok {
serviceName = data.MustString()
@@ -448,12 +473,11 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
header = httpHeader
}
}
}
enableTLS = inboundInfo.Get("streamSettings").Get("security").MustString() == "tls"
enableVless = inboundInfo.Get("streamSettings").Get("security").MustString() == "reality"
enableReality = enableVless
enableVless = inboundInfo.Get("protocol").MustString() == "vless"
enableReality = inboundInfo.Get("streamSettings").Get("security").MustString() == "reality"
realityConfig := new(api.REALITYConfig)
if enableVless {
@@ -470,19 +494,26 @@ func (c *APIClient) ParseV2rayNodeResponse(nodeInfoResponse *simplejson.Json) (*
}
}
// XTLS only supports TLS and REALITY directly for now
if transportProtocol == "tcp" && enableReality {
vlessFlow = "xtls-rprx-vision"
} else {
vlessFlow = c.VlessFlow
}
// Create GeneralNodeInfo
// AlterID will be updated after next sync
nodeInfo := &api.NodeInfo{
NodeType: c.NodeType,
NodeID: c.NodeID,
Port: port,
AlterID: alterID,
AlterID: 0,
TransportProtocol: transportProtocol,
EnableTLS: enableTLS,
Path: path,
Host: host,
EnableVless: enableVless,
VlessFlow: c.VlessFlow,
VlessFlow: vlessFlow,
ServiceName: serviceName,
Header: header,
EnableREALITY: enableReality,

View File

@@ -7,7 +7,7 @@ import (
)
var (
version = "0.9.4"
version = "0.9.5"
codename = "XrayR"
intro = "A Xray backend that supports many panels"
)

View File

@@ -149,8 +149,8 @@ func (l *LegoCMD) RenewCert() (CertPath string, KeyPath string, ok bool, err err
}
func checkCertFile(domain string) (string, string, error) {
keyPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.key", domain))
certPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.crt", domain))
keyPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.key", sanitizedDomain(domain)))
certPath := path.Join(defaultPath, "certificates", fmt.Sprintf("%s.crt", sanitizedDomain(domain)))
if _, err := os.Stat(keyPath); os.IsNotExist(err) {
return "", "", fmt.Errorf("cert key failed: %s", domain)
}

28
go.mod
View File

@@ -6,8 +6,8 @@ require (
dario.cat/mergo v1.0.0
github.com/bitly/go-simplejson v0.5.1
github.com/deckarep/golang-set v1.8.0
github.com/eko/gocache/lib/v4 v4.1.5
github.com/eko/gocache/store/go_cache/v4 v4.2.1
github.com/eko/gocache/lib/v4 v4.1.6
github.com/eko/gocache/store/go_cache/v4 v4.2.2
github.com/eko/gocache/store/redis/v4 v4.2.1
github.com/fsnotify/fsnotify v1.7.0
github.com/go-acme/lego/v4 v4.16.1
@@ -15,19 +15,19 @@ require (
github.com/gogf/gf/v2 v2.7.0
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/r3labs/diff/v2 v2.15.1
github.com/redis/go-redis/v9 v9.5.1
github.com/redis/go-redis/v9 v9.7.0
github.com/sagernet/sing v0.4.1
github.com/sagernet/sing-shadowsocks v0.2.7
github.com/shirou/gopsutil/v3 v3.24.2
github.com/shirou/gopsutil/v3 v3.24.5
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
github.com/xtls/xray-core v1.8.20
golang.org/x/crypto v0.25.0
golang.org/x/crypto v0.28.0
golang.org/x/net v0.27.0
golang.org/x/time v0.5.0
google.golang.org/protobuf v1.34.2
golang.org/x/time v0.7.0
google.golang.org/protobuf v1.36.4
)
require (
@@ -85,6 +85,7 @@ require (
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/civo/civogo v0.3.63 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/cloudflare/circl v1.3.9 // indirect
github.com/cloudflare/cloudflare-go v0.90.0 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect
@@ -95,6 +96,7 @@ require (
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
github.com/exoscale/egoscale v1.19.0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/flosch/pongo2/v4 v4.0.2 // indirect
@@ -135,6 +137,7 @@ require (
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
github.com/gorilla/css v1.0.1 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -173,6 +176,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/microcosm-cc/bluemonday v1.0.26 // indirect
github.com/miekg/dns v1.1.61 // indirect
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
@@ -192,6 +196,7 @@ require (
github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/porkbun v0.3.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
@@ -212,6 +217,7 @@ require (
github.com/quic-go/quic-go v0.45.1 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sacloud/api-client-go v0.2.10 // indirect
github.com/sacloud/go-http v0.1.8 // indirect
@@ -273,9 +279,9 @@ require (
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/oauth2 v0.20.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/tools v0.22.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 // indirect

54
go.sum
View File

@@ -820,7 +820,7 @@ github.com/cpu/goacmedns v0.1.1 h1:DM3H2NiN2oam7QljgGY5ygy4yDXhK5Z4JUnqaugs2C4=
github.com/cpu/goacmedns v0.1.1/go.mod h1:MuaouqEhPAHxsbqjgnck5zeghuwBP1dLnPoobeGqugQ=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -843,10 +843,10 @@ github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j
github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eko/gocache/lib/v4 v4.1.5 h1:CeMQmdIzwBKKLRjk3FCDXzNFsQTyqJ01JLI7Ib0C9r8=
github.com/eko/gocache/lib/v4 v4.1.5/go.mod h1:XaNfCwW8KYW1bRZ/KoHA1TugnnkMz0/gT51NDIu7LSY=
github.com/eko/gocache/store/go_cache/v4 v4.2.1 h1:3xSksOamzCf+YZXz9l67gr6jOj3AA4hnk0mV4z3Jwbs=
github.com/eko/gocache/store/go_cache/v4 v4.2.1/go.mod h1:rd6tUbaBOdqgi5xT3+OGeU7lQuhVJGTapNWFlZou524=
github.com/eko/gocache/lib/v4 v4.1.6 h1:5WWIGISKhE7mfkyF+SJyWwqa4Dp2mkdX8QsZpnENqJI=
github.com/eko/gocache/lib/v4 v4.1.6/go.mod h1:HFxC8IiG2WeRotg09xEnPD72sCheJiTSr4Li5Ameg7g=
github.com/eko/gocache/store/go_cache/v4 v4.2.2 h1:tAI9nl6TLoJyKG1ujF0CS0n/IgTEMl+NivxtR5R3/hw=
github.com/eko/gocache/store/go_cache/v4 v4.2.2/go.mod h1:T9zkHokzr8K9EiC7RfMbDg6HSwaV6rv3UdcNu13SGcA=
github.com/eko/gocache/store/redis/v4 v4.2.1 h1:uPAgZIn7knH6a55tO4ETN9V93VD3Rcyx0ZIyozEqC0I=
github.com/eko/gocache/store/redis/v4 v4.2.1/go.mod h1:JoLkNA5yeGNQUwINAM9529cDNQCo88WwiKlO9e/+39I=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -1292,7 +1292,6 @@ github.com/liquidweb/liquidweb-cli v0.7.0 h1:7j1r1U0MZa1TXiWo3IMU5V1YQwnBHMVxU+x
github.com/liquidweb/liquidweb-cli v0.7.0/go.mod h1:+uU7L6BhaQtgo4cYKhhsP5UNCq/imNvjBjlf76Vqpb0=
github.com/liquidweb/liquidweb-go v1.6.4 h1:6S0m3hHSpiLqGD7AFSb7lH/W/qr1wx+tKil9fgIbjMc=
github.com/liquidweb/liquidweb-go v1.6.4/go.mod h1:B934JPIIcdA+uTq2Nz5PgOtG6CuCaEvQKe/Ge/5GgZ4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
@@ -1464,7 +1463,6 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
@@ -1513,8 +1511,8 @@ github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjC
github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/r3labs/diff/v2 v2.15.1 h1:EOrVqPUzi+njlumoqJwiS/TgGgmZo83619FNDB9xQUg=
github.com/r3labs/diff/v2 v2.15.1/go.mod h1:I8noH9Fc2fjSaMxqF3G2lhDdC0b+JXCfyx85tWFM9kc=
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
@@ -1565,8 +1563,8 @@ github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y=
github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk=
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
@@ -1635,8 +1633,8 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -1685,10 +1683,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.878 h1:Bgzv
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.878/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.878 h1:M+xjSie8aQLDFdjHszCkz0m8TKJDg5sf2rjfxv8jYIQ=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.878/go.mod h1:h6PMyIaU05XQ3bX3KLKixsZfwd6kS4RWU5QSC48OV6Y=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -1842,8 +1838,8 @@ golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -2036,8 +2032,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -2153,12 +2149,11 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -2172,8 +2167,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -2193,8 +2188,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2202,8 +2197,9 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -2580,8 +2576,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
google.golang.org/protobuf v1.36.4 h1:6A3ZDJHn/eNqc1i+IdefRzy/9PokBTPvcqMySR7NNIM=
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=