diff --git a/internal/web/actions/default/clusters/cluster/init.go b/internal/web/actions/default/clusters/cluster/init.go index f28e9997..866dd67d 100644 --- a/internal/web/actions/default/clusters/cluster/init.go +++ b/internal/web/actions/default/clusters/cluster/init.go @@ -5,6 +5,7 @@ import ( "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/groups" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/cache" + ddosProtection "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/dns" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/ssh" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/settings/system" @@ -56,6 +57,8 @@ func init() { GetPost("/settings/ssh", new(ssh.IndexAction)). GetPost("/settings/ssh/test", new(ssh.TestAction)). GetPost("/settings/thresholds", new(thresholds.IndexAction)). + GetPost("/settings/ddos-protection", new(ddosProtection.IndexAction)). + Post("/settings/ddos-protection/status", new(ddosProtection.StatusAction)). // 分组相关 Prefix("/clusters/cluster/groups"). diff --git a/internal/web/actions/default/clusters/cluster/node/nodeutils/utils.go b/internal/web/actions/default/clusters/cluster/node/nodeutils/utils.go index 977a5262..bb2496f4 100644 --- a/internal/web/actions/default/clusters/cluster/node/nodeutils/utils.go +++ b/internal/web/actions/default/clusters/cluster/node/nodeutils/utils.go @@ -23,6 +23,11 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod } var node = nodeResp.Node + info, err := parentAction.RPC().NodeRPC().FindEnabledNodeConfigInfo(parentAction.AdminContext(), &pb.FindEnabledNodeConfigInfoRequest{NodeId: nodeId}) + if err != nil { + return nil, err + } + var groupMap maps.Map if node.NodeGroup != nil { groupMap = maps.Map{ @@ -60,30 +65,38 @@ func InitNodeInfo(parentAction *actionutils.ParentAction, nodeId int64) (*pb.Nod "name": "DNS设置", "url": prefix + "/settings/dns?" + query, "isActive": menuItem == "dns", - "isOn": len(node.DnsRoutes) > 0, + "isOn": info.HasDNSInfo, }, { "name": "缓存设置", "url": prefix + "/settings/cache?" + query, "isActive": menuItem == "cache", - "isOn": len(node.CacheDiskDir) > 0 || - (node.MaxCacheDiskCapacity != nil && node.MaxCacheDiskCapacity.Count > 0) || - (node.MaxCacheMemoryCapacity != nil && node.MaxCacheMemoryCapacity.Count > 0), + "isOn": info.HasCacheInfo, + }, + { + "name": "DDOS防护", + "url": prefix + "/settings/ddos-protection?" + query, + "isActive": menuItem == "ddosProtection", + "isOn": info.HasDDoSProtection, + }, + { + "name": "-", + "url": "", }, } - menuItems = filterMenuItems(menuItems, menuItem, prefix, query) + menuItems = filterMenuItems(menuItems, menuItem, prefix, query, info) menuItems = append(menuItems, []maps.Map{ { "name": "SSH设置", "url": prefix + "/settings/ssh?" + query, "isActive": menuItem == "ssh", - "isOn": node.NodeLogin != nil, + "isOn": info.HasSSH, }, { "name": "系统设置", "url": prefix + "/settings/system?" + query, "isActive": menuItem == "system", - "isOn": node.MaxCPU > 0, + "isOn": info.HasSystemSettings, }, }...) parentAction.Data["leftMenuItems"] = menuItems diff --git a/internal/web/actions/default/clusters/cluster/node/nodeutils/utils_ext.go b/internal/web/actions/default/clusters/cluster/node/nodeutils/utils_ext.go index 5e18eac7..560c9d08 100644 --- a/internal/web/actions/default/clusters/cluster/node/nodeutils/utils_ext.go +++ b/internal/web/actions/default/clusters/cluster/node/nodeutils/utils_ext.go @@ -5,9 +5,10 @@ package nodeutils import ( + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/maps" ) -func filterMenuItems(menuItems []maps.Map, menuItem string, prefix string, query string) []maps.Map { +func filterMenuItems(menuItems []maps.Map, menuItem string, prefix string, query string, info *pb.FindEnabledNodeConfigInfoResponse) []maps.Map { return menuItems } diff --git a/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection/index.go b/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection/index.go new file mode 100644 index 00000000..e35771bd --- /dev/null +++ b/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection/index.go @@ -0,0 +1,133 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ddosProtection + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/nodeutils" + "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/types" + "net" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "node", "update") + this.SecondMenu("ddosProtection") +} + +func (this *IndexAction) RunGet(params struct { + ClusterId int64 + NodeId int64 +}) { + _, err := nodeutils.InitNodeInfo(this.Parent(), params.NodeId) + if err != nil { + this.ErrorPage(err) + return + } + + this.Data["nodeId"] = params.NodeId + + // 集群设置 + clusterProtectionResp, err := this.RPC().NodeClusterRPC().FindNodeClusterDDoSProtection(this.AdminContext(), &pb.FindNodeClusterDDoSProtectionRequest{NodeClusterId: params.ClusterId}) + if err != nil { + this.ErrorPage(err) + return + } + var clusterDDoSProtectionIsOn = false + if len(clusterProtectionResp.DdosProtectionJSON) > 0 { + var clusterDDoSProtection = &ddosconfigs.ProtectionConfig{} + err = json.Unmarshal(clusterProtectionResp.DdosProtectionJSON, clusterDDoSProtection) + if err != nil { + this.ErrorPage(err) + return + } + clusterDDoSProtectionIsOn = clusterDDoSProtection.IsOn() + } + + this.Data["clusterDDoSProtectionIsOn"] = clusterDDoSProtectionIsOn + + // 节点设置 + ddosProtectionResp, err := this.RPC().NodeRPC().FindNodeDDoSProtection(this.AdminContext(), &pb.FindNodeDDoSProtectionRequest{NodeId: params.NodeId}) + if err != nil { + this.ErrorPage(err) + return + } + var ddosProtectionConfig = ddosconfigs.DefaultProtectionConfig() + if len(ddosProtectionResp.DdosProtectionJSON) > 0 { + err = json.Unmarshal(ddosProtectionResp.DdosProtectionJSON, ddosProtectionConfig) + if err != nil { + this.ErrorPage(err) + return + } + } + this.Data["config"] = ddosProtectionConfig + this.Data["defaultConfigs"] = nodeconfigs.DefaultConfigs + + this.Show() +} + +func (this *IndexAction) RunPost(params struct { + NodeId int64 + DdosProtectionJSON []byte + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("修改节点 %d 的DDOS防护设置", params.NodeId) + + var ddosProtectionConfig = &ddosconfigs.ProtectionConfig{} + err := json.Unmarshal(params.DdosProtectionJSON, ddosProtectionConfig) + if err != nil { + this.ErrorPage(err) + return + } + + err = ddosProtectionConfig.Init() + if err != nil { + this.Fail("配置校验失败:" + err.Error()) + } + + // 校验参数 + if ddosProtectionConfig.TCP != nil { + var tcpConfig = ddosProtectionConfig.TCP + if tcpConfig.MaxConnectionsPerIP > 0 && tcpConfig.MaxConnectionsPerIP < nodeconfigs.DefaultTCPMinConnectionsPerIP { + this.FailField("tcpMaxConnectionsPerIP", "TCP: 单IP TCP最大连接数不能小于"+types.String(nodeconfigs.DefaultTCPMinConnectionsPerIP)) + } + + if tcpConfig.NewConnectionsRate > 0 && tcpConfig.NewConnectionsRate < nodeconfigs.DefaultTCPNewConnectionsMinRate { + this.FailField("tcpNewConnectionsRate", "TCP: 单IP连接速率不能小于"+types.String(nodeconfigs.DefaultTCPNewConnectionsMinRate)) + } + + // Port + for _, portConfig := range tcpConfig.Ports { + if portConfig.Port > 65535 { + this.Fail("端口号" + types.String(portConfig.Port) + "不能大于65535") + } + } + + // IP + for _, ipConfig := range tcpConfig.AllowIPList { + if net.ParseIP(ipConfig.IP) == nil { + this.Fail("白名单IP '" + ipConfig.IP + "' 格式错误") + } + } + } + + _, err = this.RPC().NodeRPC().UpdateNodeDDoSProtection(this.AdminContext(), &pb.UpdateNodeDDoSProtectionRequest{ + NodeId: params.NodeId, + DdosProtectionJSON: params.DdosProtectionJSON, + }) + if err != nil { + this.ErrorPage(err) + return + } + this.Success() +} diff --git a/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection/status.go b/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection/status.go new file mode 100644 index 00000000..fa5d4d4e --- /dev/null +++ b/internal/web/actions/default/clusters/cluster/node/settings/ddos-protection/status.go @@ -0,0 +1,27 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ddosProtection + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" + "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" +) + +type StatusAction struct { + actionutils.ParentAction +} + +func (this *StatusAction) RunPost(params struct { + NodeId int64 +}) { + results, err := nodeutils.SendMessageToNodeIds(this.AdminContext(), []int64{params.NodeId}, messageconfigs.MessageCodeCheckLocalFirewall, &messageconfigs.CheckLocalFirewallMessage{ + Name: "nftables", + }, 10) + if err != nil { + this.ErrorPage(err) + return + } + this.Data["results"] = results + this.Success() +} diff --git a/internal/web/actions/default/clusters/cluster/node/settings/ssh/index.go b/internal/web/actions/default/clusters/cluster/node/settings/ssh/index.go index 2df68f54..892db726 100644 --- a/internal/web/actions/default/clusters/cluster/node/settings/ssh/index.go +++ b/internal/web/actions/default/clusters/cluster/node/settings/ssh/index.go @@ -32,6 +32,8 @@ func (this *IndexAction) RunGet(params struct { return } + this.Data["hostIsAutoFilled"] = false + // 登录信息 var loginMap maps.Map = nil if node.NodeLogin != nil { @@ -79,6 +81,7 @@ func (this *IndexAction) RunGet(params struct { return } if len(addressesResp.NodeIPAddresses) > 0 { + this.Data["hostIsAutoFilled"] = true loginMap = maps.Map{ "id": 0, "name": "", @@ -100,6 +103,7 @@ func (this *IndexAction) RunGet(params struct { return } if len(addressesResp.NodeIPAddresses) > 0 { + this.Data["hostIsAutoFilled"] = true loginParams["host"] = addressesResp.NodeIPAddresses[0].Ip } } diff --git a/internal/web/actions/default/clusters/cluster/settings/ddos-protection/index.go b/internal/web/actions/default/clusters/cluster/settings/ddos-protection/index.go new file mode 100644 index 00000000..161e3bfd --- /dev/null +++ b/internal/web/actions/default/clusters/cluster/settings/ddos-protection/index.go @@ -0,0 +1,106 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ddosProtection + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/types" + "net" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "setting", "") + this.SecondMenu("ddosProtection") +} + +func (this *IndexAction) RunGet(params struct { + ClusterId int64 +}) { + this.Data["clusterId"] = params.ClusterId + + protectionResp, err := this.RPC().NodeClusterRPC().FindNodeClusterDDoSProtection(this.AdminContext(), &pb.FindNodeClusterDDoSProtectionRequest{NodeClusterId: params.ClusterId}) + if err != nil { + this.ErrorPage(err) + return + } + + var ddosProtectionConfig = ddosconfigs.DefaultProtectionConfig() + if len(protectionResp.DdosProtectionJSON) > 0 { + err = json.Unmarshal(protectionResp.DdosProtectionJSON, ddosProtectionConfig) + if err != nil { + this.ErrorPage(err) + return + } + } + this.Data["config"] = ddosProtectionConfig + this.Data["defaultConfigs"] = nodeconfigs.DefaultConfigs + + this.Show() +} + +func (this *IndexAction) RunPost(params struct { + ClusterId int64 + DdosProtectionJSON []byte + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("修改集群 %d 的DDOS防护设置", params.ClusterId) + + var ddosProtectionConfig = &ddosconfigs.ProtectionConfig{} + err := json.Unmarshal(params.DdosProtectionJSON, ddosProtectionConfig) + if err != nil { + this.ErrorPage(err) + return + } + + err = ddosProtectionConfig.Init() + if err != nil { + this.Fail("配置校验失败:" + err.Error()) + } + + // 校验参数 + if ddosProtectionConfig.TCP != nil { + var tcpConfig = ddosProtectionConfig.TCP + if tcpConfig.MaxConnectionsPerIP > 0 && tcpConfig.MaxConnectionsPerIP < nodeconfigs.DefaultTCPMinConnectionsPerIP { + this.FailField("tcpMaxConnectionsPerIP", "TCP: 单IP TCP最大连接数不能小于"+types.String(nodeconfigs.DefaultTCPMinConnectionsPerIP)) + } + + if tcpConfig.NewConnectionsRate > 0 && tcpConfig.NewConnectionsRate < nodeconfigs.DefaultTCPNewConnectionsMinRate { + this.FailField("tcpNewConnectionsRate", "TCP: 单IP连接速率不能小于"+types.String(nodeconfigs.DefaultTCPNewConnectionsMinRate)) + } + + // Port + for _, portConfig := range tcpConfig.Ports { + if portConfig.Port > 65535 { + this.Fail("端口号" + types.String(portConfig.Port) + "不能大于65535") + } + } + + // IP + for _, ipConfig := range tcpConfig.AllowIPList { + if net.ParseIP(ipConfig.IP) == nil { + this.Fail("白名单IP '" + ipConfig.IP + "' 格式错误") + } + } + } + + _, err = this.RPC().NodeClusterRPC().UpdateNodeClusterDDoSProtection(this.AdminContext(), &pb.UpdateNodeClusterDDoSProtectionRequest{ + NodeClusterId: params.ClusterId, + DdosProtectionJSON: params.DdosProtectionJSON, + }) + if err != nil { + this.ErrorPage(err) + return + } + this.Success() +} diff --git a/internal/web/actions/default/clusters/cluster/settings/ddos-protection/status.go b/internal/web/actions/default/clusters/cluster/settings/ddos-protection/status.go new file mode 100644 index 00000000..194dad27 --- /dev/null +++ b/internal/web/actions/default/clusters/cluster/settings/ddos-protection/status.go @@ -0,0 +1,71 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +package ddosProtection + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" + "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/ddosconfigs" + "github.com/iwind/TeaGo/maps" +) + +type StatusAction struct { + actionutils.ParentAction +} + +func (this *StatusAction) Init() { + this.Nav("", "setting", "") + this.SecondMenu("ddosProtection") +} + +func (this *StatusAction) RunGet(params struct { + ClusterId int64 +}) { + this.Data["clusterId"] = params.ClusterId + + this.Show() +} + +func (this *StatusAction) RunPost(params struct { + ClusterId int64 +}) { + results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodeCheckLocalFirewall, &messageconfigs.CheckLocalFirewallMessage{ + Name: "nftables", + }, 10) + if err != nil { + this.ErrorPage(err) + return + } + + var resultMaps = []maps.Map{} + for _, result := range results { + var resultMap = maps.Map{ + "isOk": result.IsOK, + "message": result.Message, + "nodeId": result.NodeId, + "nodeName": result.NodeName, + } + + nodeResp, err := this.RPC().NodeRPC().FindNodeDDoSProtection(this.AdminContext(), &pb.FindNodeDDoSProtectionRequest{NodeId: result.NodeId}) + if err != nil { + this.ErrorPage(err) + return + } + if len(nodeResp.DdosProtectionJSON) > 0 { + var ddosProtection = ddosconfigs.DefaultProtectionConfig() + err = json.Unmarshal(nodeResp.DdosProtectionJSON, ddosProtection) + if err != nil { + this.ErrorPage(err) + return + } + resultMap["isPrior"] = !ddosProtection.IsPriorEmpty() + } + resultMaps = append(resultMaps, resultMap) + } + + this.Data["results"] = resultMaps + this.Success() +} diff --git a/internal/web/actions/default/clusters/cluster/settings/index.go b/internal/web/actions/default/clusters/cluster/settings/index.go index ef96319c..4cc5aa04 100644 --- a/internal/web/actions/default/clusters/cluster/settings/index.go +++ b/internal/web/actions/default/clusters/cluster/settings/index.go @@ -66,34 +66,31 @@ func (this *IndexAction) RunGet(params struct { this.Data["timeZoneLocation"] = nodeconfigs.FindTimeZoneLocation(cluster.TimeZone) this.Data["cluster"] = maps.Map{ - "id": cluster.Id, - "name": cluster.Name, - "installDir": cluster.InstallDir, - "timeZone": cluster.TimeZone, - "nodeMaxThreads": cluster.NodeMaxThreads, - "nodeTCPMaxConnections": cluster.NodeTCPMaxConnections, - "autoOpenPorts": cluster.AutoOpenPorts, + "id": cluster.Id, + "name": cluster.Name, + "installDir": cluster.InstallDir, + "timeZone": cluster.TimeZone, + "nodeMaxThreads": cluster.NodeMaxThreads, + "autoOpenPorts": cluster.AutoOpenPorts, } // 默认值 this.Data["defaultNodeMaxThreads"] = nodeconfigs.DefaultMaxThreads this.Data["defaultNodeMaxThreadsMin"] = nodeconfigs.DefaultMaxThreadsMin this.Data["defaultNodeMaxThreadsMax"] = nodeconfigs.DefaultMaxThreadsMax - this.Data["defaultNodeTCPMaxConnections"] = nodeconfigs.DefaultTCPMaxConnections this.Show() } // RunPost 保存设置 func (this *IndexAction) RunPost(params struct { - ClusterId int64 - Name string - GrantId int64 - InstallDir string - TimeZone string - NodeMaxThreads int32 - NodeTCPMaxConnections int32 - AutoOpenPorts bool + ClusterId int64 + Name string + GrantId int64 + InstallDir string + TimeZone string + NodeMaxThreads int32 + AutoOpenPorts bool Must *actions.Must }) { @@ -112,14 +109,13 @@ func (this *IndexAction) RunPost(params struct { } _, err := this.RPC().NodeClusterRPC().UpdateNodeCluster(this.AdminContext(), &pb.UpdateNodeClusterRequest{ - NodeClusterId: params.ClusterId, - Name: params.Name, - NodeGrantId: params.GrantId, - InstallDir: params.InstallDir, - TimeZone: params.TimeZone, - NodeMaxThreads: params.NodeMaxThreads, - NodeTCPMaxConnections: params.NodeTCPMaxConnections, - AutoOpenPorts: params.AutoOpenPorts, + NodeClusterId: params.ClusterId, + Name: params.Name, + NodeGrantId: params.GrantId, + InstallDir: params.InstallDir, + TimeZone: params.TimeZone, + NodeMaxThreads: params.NodeMaxThreads, + AutoOpenPorts: params.AutoOpenPorts, }) if err != nil { this.ErrorPage(err) diff --git a/internal/web/actions/default/clusters/cluster/settings/init.go b/internal/web/actions/default/clusters/cluster/settings/init.go index c58f58bc..1b498f83 100644 --- a/internal/web/actions/default/clusters/cluster/settings/init.go +++ b/internal/web/actions/default/clusters/cluster/settings/init.go @@ -3,6 +3,7 @@ package settings import ( "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/cache" + ddosProtection "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/ddos-protection" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/dns" firewallActions "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/firewall-actions" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/settings/health" @@ -79,6 +80,13 @@ func init() { // WebP Prefix("/clusters/cluster/settings/webp"). GetPost("", new(webp.IndexAction)). + + // DDOS Protection + Prefix("/clusters/cluster/settings/ddos-protection"). + GetPost("", new(ddosProtection.IndexAction)). + GetPost("/status", new(ddosProtection.StatusAction)). + + // EndAll() }) } diff --git a/internal/web/actions/default/clusters/clusterutils/cluster_helper.go b/internal/web/actions/default/clusters/clusterutils/cluster_helper.go index 23614752..8f508b49 100644 --- a/internal/web/actions/default/clusters/clusterutils/cluster_helper.go +++ b/internal/web/actions/default/clusters/clusterutils/cluster_helper.go @@ -117,6 +117,13 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, info *pb.F "isOn": info != nil && info.HasFirewallActions, }) + items = append(items, maps.Map{ + "name": "DDOS防护", + "url": "/clusters/cluster/settings/ddos-protection?clusterId=" + clusterId, + "isActive": selectedItem == "ddosProtection", + "isOn": info != nil && info.HasDDoSProtection, + }) + items = append(items, maps.Map{ "name": "健康检查", "url": "/clusters/cluster/settings/health?clusterId=" + clusterId, @@ -136,6 +143,11 @@ func (this *ClusterHelper) createSettingMenu(cluster *pb.NodeCluster, info *pb.F "isActive": selectedItem == "webp", "isOn": info != nil && info.WebpIsOn, }) + + items = append(items, maps.Map{ + "name": "-", + }) + items = append(items, maps.Map{ "name": "统计指标", "url": "/clusters/cluster/settings/metrics?clusterId=" + clusterId, diff --git a/web/public/js/components/cluster/ddos-protection-ip-list-config-box.js b/web/public/js/components/cluster/ddos-protection-ip-list-config-box.js new file mode 100644 index 00000000..699e0db9 --- /dev/null +++ b/web/public/js/components/cluster/ddos-protection-ip-list-config-box.js @@ -0,0 +1,112 @@ +Vue.component("ddos-protection-ip-list-config-box", { + props: ["v-ip-list"], + data: function () { + let list = this.vIpList + if (list == null) { + list = [] + } + return { + list: list, + isAdding: false, + addingIP: { + ip: "", + description: "" + } + } + }, + methods: { + add: function () { + this.isAdding = true + let that = this + setTimeout(function () { + that.$refs.addingIPInput.focus() + }) + }, + confirm: function () { + let ip = this.addingIP.ip + if (ip.length == 0) { + this.warn("请输入IP") + return + } + + let exists = false + this.list.forEach(function (v) { + if (v.ip == ip) { + exists = true + } + }) + if (exists) { + this.warn("IP '" + ip + "'已经存在") + return + } + + let that = this + Tea.Vue.$post("/ui/validateIPs") + .params({ + ips: [ip] + }) + .success(function () { + that.list.push({ + ip: ip, + description: that.addingIP.description + }) + that.notifyChange() + that.cancel() + }) + .fail(function () { + that.warn("请输入正确的IP") + }) + }, + cancel: function () { + this.isAdding = false + this.addingIP = { + ip: "", + description: "" + } + }, + remove: function (index) { + this.list.$remove(index) + this.notifyChange() + }, + warn: function (message) { + let that = this + teaweb.warn(message, function () { + that.$refs.addingIPInput.focus() + }) + }, + notifyChange: function () { + this.$emit("change", this.list) + } + }, + template: `
功能说明:此功能为试验性质,目前仅能防御简单的DDoS攻击,试验期间建议仅在被攻击时启用,仅支持已安装
| 启用 | +
+				 | 
+		
| 单节点TCP最大连接数 | +
+				 单个节点可以接受的TCP最大连接数。如果为0,则默认为{{defaultConfigs.tcpMaxConnections}}。 + | 
+		
| 单IP TCP最大连接数 | +
+				 单个IP可以连接到节点的TCP最大连接数。如果为0,则默认为{{defaultConfigs.tcpMaxConnectionsPerIP}};最小值为{{defaultConfigs.tcpMinConnectionsPerIP}}。 + | 
+		
| 单IP TCP新连接速率 | +
+				 
+					 
+				单个IP可以创建TCP新连接的速率。如果为0,则默认为{{defaultConfigs.tcpNewConnectionsRate}};最小值为{{defaultConfigs.tcpNewConnectionsMinRate}}。 + | 
+		
| TCP端口列表 | +
+				 默认为80和443两个端口。 + | 
+		
| IP白名单 | +
+				 在白名单中的IP不受当前设置的限制。 + | 
+		
修改此项配置后,需要重启节点进程才会生效。
边缘节点使用的DNS解析库。修改此项配置后,需要重启节点进程才会生效。
[已打开] 打开后可以覆盖父级或子级配置。
+[已打开] {{realDescription}}。
` diff --git a/web/views/@default/clusters/cluster/node/settings/ddos-protection/index.html b/web/views/@default/clusters/cluster/node/settings/ddos-protection/index.html new file mode 100644 index 00000000..c4bef9bb --- /dev/null +++ b/web/views/@default/clusters/cluster/node/settings/ddos-protection/index.html @@ -0,0 +1,17 @@ +{$layout} +{$template "/clusters/cluster/node/node_menu"} +{$template "/left_menu_with_menu"} + + \ No newline at end of file diff --git a/web/views/@default/clusters/cluster/node/settings/ddos-protection/index.js b/web/views/@default/clusters/cluster/node/settings/ddos-protection/index.js new file mode 100644 index 00000000..04112cb4 --- /dev/null +++ b/web/views/@default/clusters/cluster/node/settings/ddos-protection/index.js @@ -0,0 +1,15 @@ +Tea.context(function () { + this.success = NotifyReloadSuccess("保存成功") + this.checkResult = null + + this.$post(".status") + .params({ + nodeId: this.nodeId + }) + .success(function (resp) { + let results = resp.data.results + if (results.length > 0) { + this.checkResult = results[0] + } + }) +}) \ No newline at end of file diff --git a/web/views/@default/clusters/cluster/node/settings/ssh/index.html b/web/views/@default/clusters/cluster/node/settings/ssh/index.html index 2cfe75bc..bcf72628 100644 --- a/web/views/@default/clusters/cluster/node/settings/ssh/index.html +++ b/web/views/@default/clusters/cluster/node/settings/ssh/index.html @@ -13,7 +13,7 @@比如192.168.1.100
+已自动填充,需要保存。比如192.168.1.100。
取值在{{defaultNodeMaxThreadsMin}}和{{defaultNodeMaxThreadsMax}}之间;如果为0,则默认为{{defaultNodeMaxThreads}}。
如果为0,则默认为{{defaultNodeTCPMaxConnections}}。
-| 集群 | -节点 | +集群 | +节点 | 信息 | 操作 | {{task.error}} diff --git a/web/views/@default/servers/components/waf/policy.html b/web/views/@default/servers/components/waf/policy.html index d9995e38..fcaf873f 100644 --- a/web/views/@default/servers/components/waf/policy.html +++ b/web/views/@default/servers/components/waf/policy.html @@ -93,7 +93,7 @@ | 
|---|---|---|---|---|---|
| 记录日志 | +记录访问日志 | 默认 开启 diff --git a/web/views/@default/servers/components/waf/update.html b/web/views/@default/servers/components/waf/update.html index 1b8e594b..994cba9a 100644 --- a/web/views/@default/servers/components/waf/update.html +++ b/web/views/@default/servers/components/waf/update.html @@ -51,7 +51,7 @@ | |||
| 记录日志 | +记录访问日志 | 
                     
                      |