From 0d1df5f9051b43b4a08b3352ff54281d3725e9b7 Mon Sep 17 00:00:00 2001 From: Chang lue Tsen Date: Sun, 28 Sep 2025 19:05:54 +0900 Subject: [PATCH] feat(config): enhance NodeConfig with TrafficReportThreshold, IPStrategy, DNS, Block, and Outbound fields --- adapter/client.go | 11 +- apis/node/node.api | 11 +- apis/types.api | 110 +++++++++------ .../database/02114_node_config.down.sql | 0 .../migrate/database/02114_node_config.up.sql | 8 ++ initialize/node.go | 36 ++++- internal/config/config.go | 85 +++++++++++- .../queryServerProtocolConfigHandler.go | 10 +- .../logic/admin/system/getNodeConfigLogic.go | 43 +++++- .../admin/system/updateNodeConfigLogic.go | 4 +- .../server/queryServerProtocolConfigLogic.go | 48 ++++++- internal/model/node/server.go | 5 + internal/types/types.go | 128 +++++++++++------- pkg/tool/convert.go | 11 ++ 14 files changed, 395 insertions(+), 115 deletions(-) create mode 100644 initialize/migrate/database/02114_node_config.down.sql create mode 100644 initialize/migrate/database/02114_node_config.up.sql diff --git a/adapter/client.go b/adapter/client.go index 8f5457b..e456898 100644 --- a/adapter/client.go +++ b/adapter/client.go @@ -59,9 +59,9 @@ type Proxy struct { Multiplex string // Obfs - Obfs string // obfs, 'none', 'http', 'tls' - ObfsHost string // obfs host - ObfsPath string // obfs path + //Obfs string // obfs, 'none', 'http', 'tls' + //ObfsHost string // obfs host + //ObfsPath string // obfs path // Vless XhttpMode string // xhttp mode @@ -76,6 +76,11 @@ type Proxy struct { EncryptionPrivateKey string // encryption private key EncryptionClientPadding string // encryption client padding EncryptionPassword string // encryption password + + Ratio float64 // Traffic ratio, default is 1 + CertMode string // Certificate mode, `none`|`http`|`dns`|`self` + CertDNSProvider string // DNS provider for certificate + CertDNSEnv string // Environment for DNS provider } type User struct { diff --git a/apis/node/node.api b/apis/node/node.api index 2952162..c59e6f0 100644 --- a/apis/node/node.api +++ b/apis/node/node.api @@ -94,11 +94,18 @@ type ( Users []OnlineUser `json:"users"` } QueryServerConfigRequest { - ServerID int64 `path:"server_id"` - SecretKey string `header:"secret_key"` + ServerID int64 `path:"server_id"` + SecretKey string `form:"secret_key"` + Protocols []string `form:"protocols,omitempty"` } QueryServerConfigResponse { + TrafficReportThreshold int64 `json:"traffic_report_threshold"` + IPStrategy string `json:"ip_strategy"` + DNS []NodeDNS `json:"dns"` + Block []string `json:"block"` + Outbound []NodeOutbound `json:"outbound"` Protocols []Protocol `json:"protocols"` + Total int64 `json:"total"` } ) diff --git a/apis/types.api b/apis/types.api index 6d246a0..cf34a27 100644 --- a/apis/types.api +++ b/apis/types.api @@ -152,9 +152,27 @@ type ( EnableResetPasswordVerify bool `json:"enable_reset_password_verify"` } NodeConfig { - NodeSecret string `json:"node_secret"` - NodePullInterval int64 `json:"node_pull_interval"` - NodePushInterval int64 `json:"node_push_interval"` + NodeSecret string `json:"node_secret"` + NodePullInterval int64 `json:"node_pull_interval"` + NodePushInterval int64 `json:"node_push_interval"` + TrafficReportThreshold int64 `json:"traffic_report_threshold"` + IPStrategy string `json:"ip_strategy"` + DNS []NodeDNS `json:"dns"` + Block []string `json:"block"` + Outbound []NodeOutbound `json:"outbound"` + } + NodeDNS { + Proto string `json:"proto"` + Address string `json:"address"` + Domains []string `json:"domains"` + } + NodeOutbound { + Name string `json:"name"` + Protocol string `json:"protocol"` + Address string `json:"address"` + Port int64 `json:"port"` + Password string `json:"password"` + Rules []string `json:"rules"` } InviteConfig { ForcedInvite bool `json:"forced_invite"` @@ -770,49 +788,53 @@ type ( Timestamp int64 `json:"timestamp"` } Protocol { - Type string `json:"type"` - Port uint16 `json:"port"` - Enable bool `json:"enable"` - Security string `json:"security,omitempty"` - SNI string `json:"sni,omitempty"` - AllowInsecure bool `json:"allow_insecure,omitempty"` - Fingerprint string `json:"fingerprint,omitempty"` - RealityServerAddr string `json:"reality_server_addr,omitempty"` - RealityServerPort int `json:"reality_server_port,omitempty"` - RealityPrivateKey string `json:"reality_private_key,omitempty"` - RealityPublicKey string `json:"reality_public_key,omitempty"` - RealityShortId string `json:"reality_short_id,omitempty"` - Transport string `json:"transport,omitempty"` - Host string `json:"host,omitempty"` - Path string `json:"path,omitempty"` - ServiceName string `json:"service_name,omitempty"` - Cipher string `json:"cipher,omitempty"` - ServerKey string `json:"server_key,omitempty"` - Flow string `json:"flow,omitempty"` - HopPorts string `json:"hop_ports,omitempty"` - HopInterval int `json:"hop_interval,omitempty"` - ObfsPassword string `json:"obfs_password,omitempty"` - DisableSNI bool `json:"disable_sni,omitempty"` - ReduceRtt bool `json:"reduce_rtt,omitempty"` - UDPRelayMode string `json:"udp_relay_mode,omitempty"` - CongestionController string `json:"congestion_controller,omitempty"` - Multiplex string `json:"multiplex,omitempty"` // mux, eg: off/low/medium/high - PaddingScheme string `json:"padding_scheme,omitempty"` // padding scheme - UpMbps int `json:"up_mbps,omitempty"` // upload speed limit - DownMbps int `json:"down_mbps,omitempty"` // download speed limit - Obfs string `json:"obfs,omitempty"` // obfs, 'none', 'http', 'tls' - ObfsHost string `json:"obfs_host,omitempty"` // obfs host - ObfsPath string `json:"obfs_path,omitempty"` // obfs path - XhttpMode string `json:"xhttp_mode,omitempty"` // xhttp mode - XhttpExtra string `json:"xhttp_extra,omitempty"` // xhttp extra path - Encryption string `json:"encryption,omitempty"` // encryption,'none', 'mlkem768x25519plus' - EncryptionMode string `json:"encryption_mode,omitempty"` // encryption mode,'native', 'xorpub', 'random' - EncryptionRtt string `json:"encryption_rtt,omitempty"` // encryption rtt,'0rtt', '1rtt' - EncryptionTicket string `json:"encryption_ticket,omitempty"` // encryption ticket + Type string `json:"type"` + Port uint16 `json:"port"` + Enable bool `json:"enable"` + Security string `json:"security,omitempty"` + SNI string `json:"sni,omitempty"` + AllowInsecure bool `json:"allow_insecure,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + RealityServerAddr string `json:"reality_server_addr,omitempty"` + RealityServerPort int `json:"reality_server_port,omitempty"` + RealityPrivateKey string `json:"reality_private_key,omitempty"` + RealityPublicKey string `json:"reality_public_key,omitempty"` + RealityShortId string `json:"reality_short_id,omitempty"` + Transport string `json:"transport,omitempty"` + Host string `json:"host,omitempty"` + Path string `json:"path,omitempty"` + ServiceName string `json:"service_name,omitempty"` + Cipher string `json:"cipher,omitempty"` + ServerKey string `json:"server_key,omitempty"` + Flow string `json:"flow,omitempty"` + HopPorts string `json:"hop_ports,omitempty"` + HopInterval int `json:"hop_interval,omitempty"` + ObfsPassword string `json:"obfs_password,omitempty"` + DisableSNI bool `json:"disable_sni,omitempty"` + ReduceRtt bool `json:"reduce_rtt,omitempty"` + UDPRelayMode string `json:"udp_relay_mode,omitempty"` + CongestionController string `json:"congestion_controller,omitempty"` + Multiplex string `json:"multiplex,omitempty"` // mux, eg: off/low/medium/high + PaddingScheme string `json:"padding_scheme,omitempty"` // padding scheme + UpMbps int `json:"up_mbps,omitempty"` // upload speed limit + DownMbps int `json:"down_mbps,omitempty"` // download speed limit + Obfs string `json:"obfs,omitempty"` // obfs, 'none', 'http', 'tls' + ObfsHost string `json:"obfs_host,omitempty"` // obfs host + ObfsPath string `json:"obfs_path,omitempty"` // obfs path + XhttpMode string `json:"xhttp_mode,omitempty"` // xhttp mode + XhttpExtra string `json:"xhttp_extra,omitempty"` // xhttp extra path + Encryption string `json:"encryption,omitempty"` // encryption,'none', 'mlkem768x25519plus' + EncryptionMode string `json:"encryption_mode,omitempty"` // encryption mode,'native', 'xorpub', 'random' + EncryptionRtt string `json:"encryption_rtt,omitempty"` // encryption rtt,'0rtt', '1rtt' + EncryptionTicket string `json:"encryption_ticket,omitempty"` // encryption ticket EncryptionServerPadding string `json:"encryption_server_padding,omitempty"` // encryption server padding - EncryptionPrivateKey string `json:"encryption_private_key,omitempty"` // encryption private key + EncryptionPrivateKey string `json:"encryption_private_key,omitempty"` // encryption private key EncryptionClientPadding string `json:"encryption_client_padding,omitempty"` // encryption client padding - EncryptionPassword string `json:"encryption_password,omitempty"` // encryption password + EncryptionPassword string `json:"encryption_password,omitempty"` // encryption password + Ratio float64 `json:"ratio,omitempty"` // Traffic ratio, default is 1 + CertMode string `json:"cert_mode,omitempty"` // Certificate mode, `none`|`http`|`dns`|`self` + CertDNSProvider string `json:"cert_dns_provider,omitempty"` // DNS provider for certificate + CertDNSEnv string `json:"cert_dns_env,omitempty"` // Environment for DNS provider } ) diff --git a/initialize/migrate/database/02114_node_config.down.sql b/initialize/migrate/database/02114_node_config.down.sql new file mode 100644 index 0000000..e69de29 diff --git a/initialize/migrate/database/02114_node_config.up.sql b/initialize/migrate/database/02114_node_config.up.sql new file mode 100644 index 0000000..1289647 --- /dev/null +++ b/initialize/migrate/database/02114_node_config.up.sql @@ -0,0 +1,8 @@ +INSERT +IGNORE INTO `system` (`category`, `key`, `value`, `type`, `desc`, `created_at`, `updated_at`) +VALUE + ('server', 'TrafficReportThreshold', '0', 'int', 'Traffic report threshold', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'), + ('server', 'IPStrategy', '', 'string', 'IP Strategy', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'), + ('server', 'DNS', '', 'string', 'DNS', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'), + ('server', 'Block', '', 'string', 'Block', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'), + ('server', 'Outbound', '', 'string', 'Proxy Outbound', '2025-04-22 14:25:16.637','2025-04-22 14:25:16.637'); \ No newline at end of file diff --git a/initialize/node.go b/initialize/node.go index da7c3fb..8fde566 100644 --- a/initialize/node.go +++ b/initialize/node.go @@ -3,7 +3,6 @@ package initialize import ( "context" "encoding/json" - "github.com/perfect-panel/server/pkg/logger" "github.com/perfect-panel/server/internal/config" @@ -19,9 +18,40 @@ func Node(ctx *svc.ServiceContext) { if err != nil { panic(err) } - var nodeConfig config.NodeConfig + var nodeConfig config.NodeDBConfig tool.SystemConfigSliceReflectToStruct(configs, &nodeConfig) - ctx.Config.Node = nodeConfig + c := config.NodeConfig{ + NodeSecret: nodeConfig.NodeSecret, + NodePullInterval: nodeConfig.NodePullInterval, + NodePushInterval: nodeConfig.NodePushInterval, + IPStrategy: nodeConfig.IPStrategy, + TrafficReportThreshold: nodeConfig.TrafficReportThreshold, + } + if nodeConfig.DNS != "" { + var dns []config.NodeDNS + err = json.Unmarshal([]byte(nodeConfig.DNS), &dns) + if err != nil { + logger.Errorf("[Node] Unmarshal DNS config error: %s", err.Error()) + panic(err) + } + c.DNS = dns + } + if nodeConfig.Block != "" { + var block []string + _ = json.Unmarshal([]byte(nodeConfig.Block), &block) + c.Block = tool.RemoveDuplicateElements(block...) + } + if nodeConfig.Outbound != "" { + var outbound []config.NodeOutbound + err = json.Unmarshal([]byte(nodeConfig.Outbound), &outbound) + if err != nil { + logger.Errorf("[Node] Unmarshal Outbound config error: %s", err.Error()) + panic(err) + } + c.Outbound = outbound + } + + ctx.Config.Node = c // Manager initialization if ctx.DB.Model(&system.System{}).Where("`key` = ?", "NodeMultiplierConfig").Find(&system.System{}).RowsAffected == 0 { diff --git a/internal/config/config.go b/internal/config/config.go index 18e5268..4d2dde5 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,6 +1,7 @@ package config import ( + "encoding/json" "github.com/perfect-panel/server/pkg/logger" "github.com/perfect-panel/server/pkg/orm" ) @@ -105,9 +106,76 @@ type SiteConfig struct { } type NodeConfig struct { - NodeSecret string `yaml:"NodeSecret" default:""` - NodePullInterval int64 `yaml:"NodePullInterval" default:"60"` - NodePushInterval int64 `yaml:"NodePushInterval" default:"60"` + NodeSecret string `yaml:"NodeSecret" default:""` + NodePullInterval int64 `yaml:"NodePullInterval" default:"60"` + NodePushInterval int64 `yaml:"NodePushInterval" default:"60"` + TrafficReportThreshold int64 `yaml:"TrafficReportThreshold" default:"0"` + IPStrategy string `yaml:"IPStrategy" default:""` + DNS []NodeDNS `yaml:"DNS"` + Block []string `yaml:"Block" ` + Outbound []NodeOutbound `yaml:"Outbound"` +} + +func (n *NodeConfig) Marshal() ([]byte, error) { + type Alias NodeConfig + return json.Marshal(&struct { + *Alias + }{ + Alias: (*Alias)(n), + }) +} + +func (n *NodeConfig) Unmarshal(data []byte) error { + type Alias NodeConfig + aux := &struct { + *Alias + }{ + Alias: (*Alias)(n), + } + return json.Unmarshal(data, &aux) +} + +type NodeDNS struct { + Proto string `json:"proto"` + Address string `json:"address"` + Domains []string `json:"domains"` +} + +func (n *NodeDNS) Marshal() ([]byte, error) { + type Alias NodeDNS + return json.Marshal(&struct { + *Alias + }{ + Alias: (*Alias)(n), + }) +} + +func (n *NodeDNS) Unmarshal(data []byte) error { + type Alias NodeDNS + aux := &struct { + *Alias + }{ + Alias: (*Alias)(n), + } + return json.Unmarshal(data, &aux) +} + +type NodeOutbound struct { + Name string `json:"name"` + Protocol string `json:"protocol"` + Address string `json:"address"` + Port int64 `json:"port"` + Password string `json:"password"` + Rules []string `json:"rules"` +} + +func (n *NodeOutbound) Marshal() ([]byte, error) { + type Alias NodeOutbound + return json.Marshal(&struct { + *Alias + }{ + Alias: (*Alias)(n), + }) } type File struct { @@ -152,3 +220,14 @@ type Log struct { AutoClear bool `yaml:"AutoClear" default:"true"` ClearDays int64 `yaml:"ClearDays" default:"7"` } + +type NodeDBConfig struct { + NodeSecret string + NodePullInterval int64 + NodePushInterval int64 + TrafficReportThreshold int64 + IPStrategy string + DNS string + Block string + Outbound string +} diff --git a/internal/handler/server/queryServerProtocolConfigHandler.go b/internal/handler/server/queryServerProtocolConfigHandler.go index 1514efa..5d382a6 100644 --- a/internal/handler/server/queryServerProtocolConfigHandler.go +++ b/internal/handler/server/queryServerProtocolConfigHandler.go @@ -1,6 +1,7 @@ package server import ( + "fmt" "net/http" "strconv" @@ -26,14 +27,15 @@ func QueryServerProtocolConfigHandler(svcCtx *svc.ServiceContext) func(c *gin.Co } req.ServerID = serverID - key := c.GetHeader("secret_key") - if key == "" || key != svcCtx.Config.Node.NodeSecret { - logger.Debugf("[QueryServerProtocolConfigHandler] - secret_key error: %s", key) - c.String(http.StatusUnauthorized, "Unauthorized") + if err = c.ShouldBindQuery(&req); err != nil { + logger.Debugf("[QueryServerProtocolConfigHandler] - ShouldBindQuery error: %v, Query: %v", err, c.Request.URL.Query()) + c.String(http.StatusBadRequest, "Invalid Params") c.Abort() return } + fmt.Printf("[QueryServerProtocolConfigHandler] - ShouldBindQuery request: %+v\n", req) + l := server.NewQueryServerProtocolConfigLogic(c.Request.Context(), svcCtx) resp, err := l.QueryServerProtocolConfig(&req) result.HttpResult(c, resp, err) diff --git a/internal/logic/admin/system/getNodeConfigLogic.go b/internal/logic/admin/system/getNodeConfigLogic.go index b33e180..1212b1a 100644 --- a/internal/logic/admin/system/getNodeConfigLogic.go +++ b/internal/logic/admin/system/getNodeConfigLogic.go @@ -2,7 +2,8 @@ package system import ( "context" - + "encoding/json" + "github.com/perfect-panel/server/internal/config" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/logger" @@ -26,15 +27,45 @@ func NewGetNodeConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Get } func (l *GetNodeConfigLogic) GetNodeConfig() (*types.NodeConfig, error) { - resp := &types.NodeConfig{} - // get server config from db configs, err := l.svcCtx.SystemModel.GetNodeConfig(l.ctx) if err != nil { l.Errorw("[GetNodeConfigLogic] GetNodeConfig get server config error: ", logger.Field("error", err.Error())) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "GetNodeConfig get server config error: %v", err.Error()) } - // reflect to response - tool.SystemConfigSliceReflectToStruct(configs, resp) - return resp, nil + var dbConfig config.NodeDBConfig + tool.SystemConfigSliceReflectToStruct(configs, &dbConfig) + c := &types.NodeConfig{ + NodeSecret: dbConfig.NodeSecret, + NodePullInterval: dbConfig.NodePullInterval, + NodePushInterval: dbConfig.NodePushInterval, + IPStrategy: dbConfig.IPStrategy, + TrafficReportThreshold: dbConfig.TrafficReportThreshold, + } + + if dbConfig.DNS != "" { + var dns []types.NodeDNS + err = json.Unmarshal([]byte(dbConfig.DNS), &dns) + if err != nil { + logger.Errorf("[Node] Unmarshal DNS config error: %s", err.Error()) + panic(err) + } + c.DNS = dns + } + if dbConfig.Block != "" { + var block []string + _ = json.Unmarshal([]byte(dbConfig.Block), &block) + c.Block = tool.RemoveDuplicateElements(block...) + } + if dbConfig.Outbound != "" { + var outbound []types.NodeOutbound + err = json.Unmarshal([]byte(dbConfig.Outbound), &outbound) + if err != nil { + logger.Errorf("[Node] Unmarshal Outbound config error: %s", err.Error()) + panic(err) + } + c.Outbound = outbound + } + + return c, nil } diff --git a/internal/logic/admin/system/updateNodeConfigLogic.go b/internal/logic/admin/system/updateNodeConfigLogic.go index 128342f..dbbba84 100644 --- a/internal/logic/admin/system/updateNodeConfigLogic.go +++ b/internal/logic/admin/system/updateNodeConfigLogic.go @@ -41,7 +41,9 @@ func (l *UpdateNodeConfigLogic) UpdateNodeConfig(req *types.NodeConfig) error { // Get the field name fieldName := t.Field(i).Name // Get the field value to string - fieldValue := tool.ConvertValueToString(v.Field(i)) + var fieldValue string + + fieldValue = tool.ConvertValueToString(v.Field(i)) // Update the server config err = db.Model(&system.System{}).Where("`category` = 'server' and `key` = ?", fieldName).Update("value", fieldValue).Error if err != nil { diff --git a/internal/logic/server/queryServerProtocolConfigLogic.go b/internal/logic/server/queryServerProtocolConfigLogic.go index 6322959..4521c55 100644 --- a/internal/logic/server/queryServerProtocolConfigLogic.go +++ b/internal/logic/server/queryServerProtocolConfigLogic.go @@ -41,7 +41,53 @@ func (l *QueryServerProtocolConfigLogic) QueryServerProtocolConfig(req *types.Qu } tool.DeepCopy(&protocols, dst) + // filter by req.Protocols + + if len(req.Protocols) > 0 { + var filtered []types.Protocol + protocolSet := make(map[string]struct{}) + for _, p := range req.Protocols { + protocolSet[p] = struct{}{} + } + for _, p := range protocols { + if _, exists := protocolSet[p.Type]; exists { + filtered = append(filtered, p) + } + } + protocols = filtered + } + + var dns []types.NodeDNS + if len(l.svcCtx.Config.Node.DNS) > 0 { + for _, d := range l.svcCtx.Config.Node.DNS { + dns = append(dns, types.NodeDNS{ + Proto: d.Proto, + Address: d.Address, + Domains: d.Domains, + }) + } + } + var outbound []types.NodeOutbound + if len(l.svcCtx.Config.Node.Outbound) > 0 { + for _, o := range l.svcCtx.Config.Node.Outbound { + outbound = append(outbound, types.NodeOutbound{ + Name: o.Name, + Protocol: o.Protocol, + Address: o.Address, + Port: o.Port, + Password: o.Password, + Rules: o.Rules, + }) + } + } + return &types.QueryServerConfigResponse{ - Protocols: protocols, + TrafficReportThreshold: l.svcCtx.Config.Node.TrafficReportThreshold, + IPStrategy: l.svcCtx.Config.Node.IPStrategy, + DNS: dns, + Block: l.svcCtx.Config.Node.Block, + Outbound: outbound, + Protocols: protocols, + Total: int64(len(protocols)), }, nil } diff --git a/internal/model/node/server.go b/internal/model/node/server.go index 5042f7f..e800ea8 100644 --- a/internal/model/node/server.go +++ b/internal/model/node/server.go @@ -144,6 +144,11 @@ type Protocol struct { EncryptionPrivateKey string `json:"encryption_private_key,omitempty"` // encryption private key EncryptionClientPadding string `json:"encryption_client_padding,omitempty"` // encryption client padding EncryptionPassword string `json:"encryption_password,omitempty"` // encryption password + + Ratio float64 `json:"ratio,omitempty"` // Traffic ratio, default is 1 + CertMode string `json:"cert_mode,omitempty"` // Certificate mode, `none`|`http`|`dns`|`self` + CertDNSProvider string `json:"cert_dns_provider,omitempty"` // DNS provider for certificate + CertDNSEnv string `json:"cert_dns_env"` // Environment for DNS provider } // Marshal protocol to json diff --git a/internal/types/types.go b/internal/types/types.go index 965e2cb..3ef3552 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -1217,9 +1217,29 @@ type Node struct { } type NodeConfig struct { - NodeSecret string `json:"node_secret"` - NodePullInterval int64 `json:"node_pull_interval"` - NodePushInterval int64 `json:"node_push_interval"` + NodeSecret string `json:"node_secret"` + NodePullInterval int64 `json:"node_pull_interval"` + NodePushInterval int64 `json:"node_push_interval"` + TrafficReportThreshold int64 `json:"traffic_report_threshold"` + IPStrategy string `json:"ip_strategy"` + DNS []NodeDNS `json:"dns"` + Block []string `json:"block"` + Outbound []NodeOutbound `json:"outbound"` +} + +type NodeDNS struct { + Proto string `json:"proto"` + Address string `json:"address"` + Domains []string `json:"domains"` +} + +type NodeOutbound struct { + Name string `json:"name"` + Protocol string `json:"protocol"` + Address string `json:"address"` + Port int64 `json:"port"` + Password string `json:"password"` + Rules []string `json:"rules"` } type NodeRelay struct { @@ -1423,48 +1443,53 @@ type PrivacyPolicyConfig struct { } type Protocol struct { - Type string `json:"type"` - Port uint16 `json:"port"` - Security string `json:"security,omitempty"` - SNI string `json:"sni,omitempty"` - AllowInsecure bool `json:"allow_insecure,omitempty"` - Fingerprint string `json:"fingerprint,omitempty"` - RealityServerAddr string `json:"reality_server_addr,omitempty"` - RealityServerPort int `json:"reality_server_port,omitempty"` - RealityPrivateKey string `json:"reality_private_key,omitempty"` - RealityPublicKey string `json:"reality_public_key,omitempty"` - RealityShortId string `json:"reality_short_id,omitempty"` - Transport string `json:"transport,omitempty"` - Host string `json:"host,omitempty"` - Path string `json:"path,omitempty"` - ServiceName string `json:"service_name,omitempty"` - Cipher string `json:"cipher,omitempty"` - ServerKey string `json:"server_key,omitempty"` - Flow string `json:"flow,omitempty"` - HopPorts string `json:"hop_ports,omitempty"` - HopInterval int `json:"hop_interval,omitempty"` - ObfsPassword string `json:"obfs_password,omitempty"` - DisableSNI bool `json:"disable_sni,omitempty"` - ReduceRtt bool `json:"reduce_rtt,omitempty"` - UDPRelayMode string `json:"udp_relay_mode,omitempty"` - CongestionController string `json:"congestion_controller,omitempty"` - Multiplex string `json:"multiplex,omitempty"` // mux, eg: off/low/medium/high - PaddingScheme string `json:"padding_scheme,omitempty"` // padding scheme - UpMbps int `json:"up_mbps,omitempty"` // upload speed limit - DownMbps int `json:"down_mbps,omitempty"` // download speed limit - Obfs string `json:"obfs,omitempty"` // obfs, 'none', 'http', 'tls' - ObfsHost string `json:"obfs_host,omitempty"` // obfs host - ObfsPath string `json:"obfs_path,omitempty"` // obfs path - XhttpMode string `json:"xhttp_mode,omitempty"` // xhttp mode - XhttpExtra string `json:"xhttp_extra,omitempty"` // xhttp extra path - Encryption string `json:"encryption,omitempty"` // encryption,'none', 'mlkem768x25519plus' - EncryptionMode string `json:"encryption_mode,omitempty"` // encryption mode,'native', 'xorpub', 'random' - EncryptionRtt string `json:"encryption_rtt,omitempty"` // encryption rtt,'0rtt', '1rtt' - EncryptionTicket string `json:"encryption_ticket,omitempty"` // encryption ticket - EncryptionServerPadding string `json:"encryption_server_padding,omitempty"` // encryption server padding - EncryptionPrivateKey string `json:"encryption_private_key,omitempty"` // encryption private key - EncryptionClientPadding string `json:"encryption_client_padding,omitempty"` // encryption client padding - EncryptionPassword string `json:"encryption_password,omitempty"` // encryption password + Type string `json:"type"` + Port uint16 `json:"port"` + Enable bool `json:"enable"` + Security string `json:"security,omitempty"` + SNI string `json:"sni,omitempty"` + AllowInsecure bool `json:"allow_insecure,omitempty"` + Fingerprint string `json:"fingerprint,omitempty"` + RealityServerAddr string `json:"reality_server_addr,omitempty"` + RealityServerPort int `json:"reality_server_port,omitempty"` + RealityPrivateKey string `json:"reality_private_key,omitempty"` + RealityPublicKey string `json:"reality_public_key,omitempty"` + RealityShortId string `json:"reality_short_id,omitempty"` + Transport string `json:"transport,omitempty"` + Host string `json:"host,omitempty"` + Path string `json:"path,omitempty"` + ServiceName string `json:"service_name,omitempty"` + Cipher string `json:"cipher,omitempty"` + ServerKey string `json:"server_key,omitempty"` + Flow string `json:"flow,omitempty"` + HopPorts string `json:"hop_ports,omitempty"` + HopInterval int `json:"hop_interval,omitempty"` + ObfsPassword string `json:"obfs_password,omitempty"` + DisableSNI bool `json:"disable_sni,omitempty"` + ReduceRtt bool `json:"reduce_rtt,omitempty"` + UDPRelayMode string `json:"udp_relay_mode,omitempty"` + CongestionController string `json:"congestion_controller,omitempty"` + Multiplex string `json:"multiplex,omitempty"` // mux, eg: off/low/medium/high + PaddingScheme string `json:"padding_scheme,omitempty"` // padding scheme + UpMbps int `json:"up_mbps,omitempty"` // upload speed limit + DownMbps int `json:"down_mbps,omitempty"` // download speed limit + Obfs string `json:"obfs,omitempty"` // obfs, 'none', 'http', 'tls' + ObfsHost string `json:"obfs_host,omitempty"` // obfs host + ObfsPath string `json:"obfs_path,omitempty"` // obfs path + XhttpMode string `json:"xhttp_mode,omitempty"` // xhttp mode + XhttpExtra string `json:"xhttp_extra,omitempty"` // xhttp extra path + Encryption string `json:"encryption,omitempty"` // encryption,'none', 'mlkem768x25519plus' + EncryptionMode string `json:"encryption_mode,omitempty"` // encryption mode,'native', 'xorpub', 'random' + EncryptionRtt string `json:"encryption_rtt,omitempty"` // encryption rtt,'0rtt', '1rtt' + EncryptionTicket string `json:"encryption_ticket,omitempty"` // encryption ticket + EncryptionServerPadding string `json:"encryption_server_padding,omitempty"` // encryption server padding + EncryptionPrivateKey string `json:"encryption_private_key,omitempty"` // encryption private key + EncryptionClientPadding string `json:"encryption_client_padding,omitempty"` // encryption client padding + EncryptionPassword string `json:"encryption_password,omitempty"` // encryption password + Ratio float64 `json:"ratio,omitempty"` // Traffic ratio, default is 1 + CertMode string `json:"cert_mode,omitempty"` // Certificate mode, `none`|`http`|`dns`|`self` + CertDNSProvider string `json:"cert_dns_provider,omitempty"` // DNS provider for certificate + CertDNSEnv string `json:"cert_dns_env,omitempty"` // Environment for DNS provider } type PubilcRegisterConfig struct { @@ -1584,12 +1609,19 @@ type QueryQuotaTaskStatusResponse struct { } type QueryServerConfigRequest struct { - ServerID int64 `path:"server_id"` - SecretKey string `header:"secret_key"` + ServerID int64 `path:"server_id"` + SecretKey string `form:"secret_key"` + Protocols []string `form:"protocols,omitempty"` } type QueryServerConfigResponse struct { - Protocols []Protocol `json:"protocols"` + TrafficReportThreshold int64 `json:"traffic_report_threshold"` + IPStrategy string `json:"ip_strategy"` + DNS []NodeDNS `json:"dns"` + Block []string `json:"block"` + Outbound []NodeOutbound `json:"outbound"` + Protocols []Protocol `json:"protocols"` + Total int64 `json:"total"` } type QuerySubscribeGroupListResponse struct { diff --git a/pkg/tool/convert.go b/pkg/tool/convert.go index fa93055..0079620 100644 --- a/pkg/tool/convert.go +++ b/pkg/tool/convert.go @@ -1,6 +1,7 @@ package tool import ( + "encoding/json" "fmt" "reflect" "strconv" @@ -26,6 +27,16 @@ func ConvertValueToString(value reflect.Value) string { default: return "" } + case reflect.Struct, reflect.Map, reflect.Slice, reflect.Array: + bytes, err := json.Marshal(value.Interface()) + if err != nil { + fmt.Println("Error marshaling struct:", err.Error()) + return "" + } + if string(bytes) == "null" { + return "" + } + return string(bytes) default: return "" }