diff --git a/web/public/js/components.js b/web/public/js/components.js index d7bd5a21..fdd1a61e 100644 --- a/web/public/js/components.js +++ b/web/public/js/components.js @@ -88,7 +88,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio -`}),Vue.component("node-ddos-protection-config-box",{props:["v-ddos-protection-config","v-default-configs","v-is-node","v-cluster-is-on"],data:function(){let e=this.vDdosProtectionConfig;return null==(e=null==e?{tcp:{isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,allowIPList:[],ports:[]}}:e).tcp&&(e.tcp={isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,allowIPList:[],ports:[]}),{config:e,defaultConfigs:this.vDefaultConfigs,isNode:this.vIsNode,isAddingPort:!1}},methods:{changeTCPPorts:function(e){this.config.tcp.ports=e},changeTCPAllowIPList:function(e){this.config.tcp.allowIPList=e}},template:`
+
`}),Vue.component("node-ddos-protection-config-box",{props:["v-ddos-protection-config","v-default-configs","v-is-node","v-cluster-is-on"],data:function(){let e=this.vDdosProtectionConfig;return null==(e=null==e?{tcp:{isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,denyNewConnectionsRate:0,allowIPList:[],ports:[]}}:e).tcp&&(e.tcp={isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,denyNewConnectionsRate:0,allowIPList:[],ports:[]}),{config:e,defaultConfigs:this.vDefaultConfigs,isNode:this.vIsNode,isAddingPort:!1}},methods:{changeTCPPorts:function(e){this.config.tcp.ports=e},changeTCPAllowIPList:function(e){this.config.tcp.allowIPList=e}},template:`

功能说明:此功能为试验性质,目前仅能防御简单的DDoS攻击,试验期间建议仅在被攻击时启用,仅支持已安装nftables v0.9以上的Linux系统。

@@ -131,6 +131,31 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio

单个IP可以创建TCP新连接的速率。如果为0,则默认为{{defaultConfigs.tcpNewConnectionsRate}};最小值为{{defaultConfigs.tcpNewConnectionsMinRate}}。

+ + 单IP TCP新连接速率黑名单 + +
+
+
+ 超过 + + 个新连接/每分钟 +
+
+
+ 屏蔽 +
+
+
+ + +
+
+
+ +

单个IP可以如果在单位时间内创建的TCP连接数超过这个值,就自动加入到nftables黑名单中。如果为0,则默认为{{defaultConfigs.tcpDenyNewConnectionsRate}};最小值为{{defaultConfigs.tcpDenyNewConnectionsMinRate}};默认屏蔽{{defaultConfigs.tcpDenyNewConnectionsRateTimeout}}秒。

+ + TCP端口列表 @@ -427,7 +452,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
-
`}),Vue.component("ns-node-ddos-protection-config-box",{props:["v-ddos-protection-config","v-default-configs","v-is-node","v-cluster-is-on"],data:function(){let e=this.vDdosProtectionConfig;return null==(e=null==e?{tcp:{isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,allowIPList:[],ports:[]}}:e).tcp&&(e.tcp={isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,allowIPList:[],ports:[]}),{config:e,defaultConfigs:this.vDefaultConfigs,isNode:this.vIsNode,isAddingPort:!1}},methods:{changeTCPPorts:function(e){this.config.tcp.ports=e},changeTCPAllowIPList:function(e){this.config.tcp.allowIPList=e}},template:`
+
`}),Vue.component("ns-node-ddos-protection-config-box",{props:["v-ddos-protection-config","v-default-configs","v-is-node","v-cluster-is-on"],data:function(){let e=this.vDdosProtectionConfig;return null==(e=null==e?{tcp:{isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,denyNewConnectionsRate:0,allowIPList:[],ports:[]}}:e).tcp&&(e.tcp={isPrior:!1,isOn:!1,maxConnections:0,maxConnectionsPerIP:0,newConnectionsRate:0,denyNewConnectionsRate:0,allowIPList:[],ports:[]}),{config:e,defaultConfigs:this.vDefaultConfigs,isNode:this.vIsNode,isAddingPort:!1}},methods:{changeTCPPorts:function(e){this.config.tcp.ports=e},changeTCPAllowIPList:function(e){this.config.tcp.allowIPList=e}},template:`

功能说明:此功能为试验性质,目前仅能防御简单的DDoS攻击,试验期间建议仅在被攻击时启用,仅支持已安装nftables v0.9以上的Linux系统。

@@ -470,6 +495,31 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio

单个IP可以创建TCP新连接的速率。如果为0,则默认为{{defaultConfigs.tcpNewConnectionsRate}};最小值为{{defaultConfigs.tcpNewConnectionsMinRate}}。

+ + 单IP TCP新连接速率黑名单 + +
+
+
+ 超过 + + 个新连接/每分钟 +
+
+
+ 屏蔽 +
+
+
+ + +
+
+
+ +

单个IP可以如果在单位时间内创建的TCP连接数超过这个值,就自动加入到nftables黑名单中。如果为0,则默认为{{defaultConfigs.tcpDenyNewConnectionsRate}};最小值为{{defaultConfigs.tcpDenyNewConnectionsMinRate}};默认屏蔽{{defaultConfigs.tcpDenyNewConnectionsRateTimeout}}秒。

+ + TCP端口列表 @@ -1469,7 +1519,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio 单IP最大并发连接数 -

单IP最大连接数,统计单个IP总连接数时不区分服务,超出此限制则响应用户429代码。为0表示不限制。

+

单IP最大连接数,统计单个IP总连接数时不区分服务,超出此限制则响应用户429代码。为0表示不限制。当前设置的并发连接数过低,可能会影响正常用户访问,建议不小于3。

@@ -1688,7 +1738,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio -
`}),Vue.component("http-firewall-checkpoint-cc",{props:["v-checkpoint"],data:function(){let e=[],t=60,i=1e3,s=!1,n={},o=(null==(n=null!=window.parent.UPDATING_RULE?window.parent.UPDATING_RULE.checkpointOptions:n)&&(n={}),0==(e=null!=n.keys?n.keys:e).length&&(e=["${remoteAddr}","${requestPath}"]),null!=n.period&&(t=n.period),null!=n.threshold&&(i=n.threshold),null!=n.ignoreCommonFiles&&"boolean"==typeof n.ignoreCommonFiles&&(s=n.ignoreCommonFiles),this);return setTimeout(function(){o.change()},100),{keys:e,period:t,threshold:i,ignoreCommonFiles:s,options:{},value:i}},watch:{period:function(){this.change()},threshold:function(){this.change()},ignoreCommonFiles:function(){this.change()}},methods:{changeKeys:function(e){this.keys=e,this.change()},change:function(){let e=parseInt(this.period.toString()),t=((isNaN(e)||e<=0)&&(e=60),parseInt(this.threshold.toString())),i=((isNaN(t)||t<=0)&&(t=1e3),this.value=t,this.ignoreCommonFiles);"boolean"!=typeof i&&(i=!1),this.vCheckpoint.options=[{code:"keys",value:this.keys},{code:"period",value:e},{code:"threshold",value:t},{code:"ignoreCommonFiles",value:i}]}},template:`
+
`}),Vue.component("http-firewall-checkpoint-cc",{props:["v-checkpoint"],data:function(){let e=[],t=60,i=1e3,s=!1,n={},o=(null==(n=null!=window.parent.UPDATING_RULE?window.parent.UPDATING_RULE.checkpointOptions:n)&&(n={}),0==(e=null!=n.keys?n.keys:e).length&&(e=["${remoteAddr}","${requestPath}"]),null!=n.period&&(t=n.period),null!=n.threshold&&(i=n.threshold),null!=n.ignoreCommonFiles&&"boolean"==typeof n.ignoreCommonFiles&&(s=n.ignoreCommonFiles),this);return setTimeout(function(){o.change()},100),{keys:e,period:t,threshold:i,ignoreCommonFiles:s,options:{},value:i}},watch:{period:function(){this.change()},threshold:function(){this.change()},ignoreCommonFiles:function(){this.change()}},methods:{changeKeys:function(e){this.keys=e,this.change()},change:function(){let e=parseInt(this.period.toString()),t=((isNaN(e)||e<=0)&&(e=60),parseInt(this.threshold.toString())),i=((isNaN(t)||t<=0)&&(t=1e3),this.value=t,this.ignoreCommonFiles);"boolean"!=typeof i&&(i=!1),this.vCheckpoint.options=[{code:"keys",value:this.keys},{code:"period",value:e},{code:"threshold",value:t},{code:"ignoreCommonFiles",value:i}]},thresholdTooLow:function(){let e=parseInt(this.threshold.toString());return 0<(e=isNaN(e)||e<=0?1e3:e)&&e<5}},template:`
@@ -1711,6 +1761,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio @@ -1747,10 +1798,10 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
阈值 * +

对于网站类应用来说,当前阈值设置的太低,有可能会影响用户正常访问。

-
`}),Vue.component("http-access-log-partitions-box",{props:["v-partition","v-day"],mounted:function(){let t=this;Tea.action("/servers/logs/partitionData").params({day:this.vDay}).success(function(e){t.partitions=[],e.data.partitions.reverse().forEach(function(e){t.partitions.push({code:e,isDisabled:!1})}),0 +`}),Vue.component("http-access-log-partitions-box",{props:["v-partition","v-day","v-query"],mounted:function(){let t=this;Tea.action("/servers/logs/partitionData").params({day:this.vDay}).success(function(e){t.partitions=[],e.data.partitions.reverse().forEach(function(e){t.partitions.push({code:e,isDisabled:!1,hasLogs:!1})}),0=t.partitions.length||(t.checkingPartition=i,t.checkLogs())}))}},template:`
`}),Vue.component("http-cache-refs-config-box",{props:["v-cache-refs","v-cache-config","v-cache-policy-id","v-web-id"],mounted:function(){let s=this;sortTable(function(e){let i=[];e.forEach(function(t){s.refs.forEach(function(e){e.id==t&&i.push(e)})}),s.updateRefs(i),s.change()})},data:function(){let e=this.vCacheRefs,t=(null==e&&(e=[]),0);return e.forEach(function(e){t++,e.id=t}),{refs:e,id:t}},methods:{addRef:function(e){window.UPDATING_CACHE_REF=null;let t=window.innerWidth,i=(1024 @@ -2165,7 +2216,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio

403 Forbidden

Request ID: \${requestId}.
-`;return{id:t,actions:this.vActions,configs:e,isAdding:!1,editingIndex:-1,action:null,actionCode:"",actionOptions:{},ipListLevels:[],blockTimeout:"",blockScope:"global",captchaLife:"",captchaMaxFails:"",captchaFailBlockTimeout:"",get302Life:"",post307Life:"",recordIPType:"black",recordIPLevel:"critical",recordIPTimeout:"",recordIPListId:0,recordIPListName:"",tagTags:[],pageStatus:403,pageBody:i,defaultPageBody:i,goGroupName:"",goGroupId:0,goGroup:null,goSetId:0,goSetName:""}},watch:{actionCode:function(i){this.action=this.actions.$find(function(e,t){return t.code==i}),this.actionOptions={}},blockTimeout:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.timeout=0:this.actionOptions.timeout=e},blockScope:function(e){this.actionOptions.scope=e},captchaLife:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.life=0:this.actionOptions.life=e},captchaMaxFails:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.maxFails=0:this.actionOptions.maxFails=e},captchaFailBlockTimeout:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.failBlockTimeout=0:this.actionOptions.failBlockTimeout=e},get302Life:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.life=0:this.actionOptions.life=e},post307Life:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.life=0:this.actionOptions.life=e},recordIPType:function(e){this.recordIPListId=0},recordIPTimeout:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.timeout=0:this.actionOptions.timeout=e},goGroupId:function(i){var e=this.vFirewallPolicy.inbound.groups.$find(function(e,t){return t.id==i});this.goGroup=e,this.goGroupName=null==e?"":e.name,this.goSetId=0,this.goSetName=""},goSetId:function(i){var e;null!=this.goGroup&&(null==(e=this.goGroup.sets.$find(function(e,t){return t.id==i}))?(this.goSetId=0,this.goSetName=""):this.goSetName=e.name)}},methods:{add:function(){this.action=null,this.actionCode="block",this.isAdding=!0,this.actionOptions={},this.blockTimeout="",this.blockScope="global",this.captchaLife="",this.captchaMaxFails="",this.captchaFailBlockTimeout="",this.get302Life="",this.post307Life="",this.recordIPLevel="critical",this.recordIPType="black",this.recordIPTimeout="",this.recordIPListId=0,this.recordIPListName="",this.tagTags=[],this.pageStatus=403,this.pageBody=this.defaultPageBody,this.goGroupName="",this.goGroupId=0,this.goGroup=null,this.goSetId=0,this.goSetName="";let i=this;this.action=this.vActions.$find(function(e,t){return t.code==i.actionCode}),this.scroll()},remove:function(e){this.isAdding=!1,this.editingIndex=-1,this.configs.$remove(e)},update:function(e,i){if(this.isAdding&&this.editingIndex==e)this.cancel();else{switch(this.add(),this.isAdding=!0,this.editingIndex=e,this.actionCode=i.code,i.code){case"block":this.blockTimeout="",(null!=i.options.timeout||0 +`;return{id:t,actions:this.vActions,configs:e,isAdding:!1,editingIndex:-1,action:null,actionCode:"",actionOptions:{},ipListLevels:[],blockTimeout:"",blockScope:"global",captchaLife:"",captchaMaxFails:"",captchaFailBlockTimeout:"",get302Life:"",post307Life:"",recordIPType:"black",recordIPLevel:"critical",recordIPTimeout:"",recordIPListId:0,recordIPListName:"",tagTags:[],pageStatus:403,pageBody:i,defaultPageBody:i,goGroupName:"",goGroupId:0,goGroup:null,goSetId:0,goSetName:"",jsCookieLife:"",jsCookieMaxFails:"",jsCookieFailBlockTimeout:""}},watch:{actionCode:function(i){this.action=this.actions.$find(function(e,t){return t.code==i}),this.actionOptions={}},blockTimeout:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.timeout=0:this.actionOptions.timeout=e},blockScope:function(e){this.actionOptions.scope=e},captchaLife:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.life=0:this.actionOptions.life=e},captchaMaxFails:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.maxFails=0:this.actionOptions.maxFails=e},captchaFailBlockTimeout:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.failBlockTimeout=0:this.actionOptions.failBlockTimeout=e},get302Life:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.life=0:this.actionOptions.life=e},post307Life:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.life=0:this.actionOptions.life=e},recordIPType:function(e){this.recordIPListId=0},recordIPTimeout:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.timeout=0:this.actionOptions.timeout=e},goGroupId:function(i){var e=this.vFirewallPolicy.inbound.groups.$find(function(e,t){return t.id==i});this.goGroup=e,this.goGroupName=null==e?"":e.name,this.goSetId=0,this.goSetName=""},goSetId:function(i){var e;null!=this.goGroup&&(null==(e=this.goGroup.sets.$find(function(e,t){return t.id==i}))?(this.goSetId=0,this.goSetName=""):this.goSetName=e.name)},jsCookieLife:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.life=0:this.actionOptions.life=e},jsCookieMaxFails:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.maxFails=0:this.actionOptions.maxFails=e},jsCookieFailBlockTimeout:function(e){e=parseInt(e),isNaN(e)?this.actionOptions.failBlockTimeout=0:this.actionOptions.failBlockTimeout=e}},methods:{add:function(){this.action=null,this.actionCode="block",this.isAdding=!0,this.actionOptions={},this.blockTimeout="",this.blockScope="global",this.captchaLife="",this.captchaMaxFails="",this.captchaFailBlockTimeout="",this.jsCookieLife="",this.jsCookieMaxFails="",this.jsCookieFailBlockTimeout="",this.get302Life="",this.post307Life="",this.recordIPLevel="critical",this.recordIPType="black",this.recordIPTimeout="",this.recordIPListId=0,this.recordIPListName="",this.tagTags=[],this.pageStatus=403,this.pageBody=this.defaultPageBody,this.goGroupName="",this.goGroupId=0,this.goGroup=null,this.goSetId=0,this.goSetName="";let i=this;this.action=this.vActions.$find(function(e,t){return t.code==i.actionCode}),this.scroll()},remove:function(e){this.isAdding=!1,this.editingIndex=-1,this.configs.$remove(e)},update:function(e,i){if(this.isAdding&&this.editingIndex==e)this.cancel();else{switch(this.add(),this.isAdding=!0,this.editingIndex=e,this.actionCode=i.code,i.code){case"block":this.blockTimeout="",(null!=i.options.timeout||0
@@ -2179,6 +2230,11 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio / 最多失败{{config.options.maxFails}}次 + + :有效期{{config.options.life}}秒 + / 最多失败{{config.options.maxFails}}次 + + :有效期{{config.options.life}}秒 @@ -2278,6 +2334,38 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio + + + 有效时间 + +
+ + +
+

验证通过后在这个时间内不再验证;如果为空或者为0表示默认。

+ + + + 最多失败次数 + +
+ + +
+

允许用户失败尝试的最多次数,超过这个次数将被自动加入黑名单;如果为空或者为0表示默认。

+ + + + 失败拦截时间 + +
+ + +
+

在达到最多失败次数(大于0)时,自动拦截的时间;如果为空或者为0表示默认。

+ + + 有效时间 @@ -4611,7 +4699,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
-`}),Vue.component("time-duration-box",{props:["v-name","v-value","v-count","v-unit"],mounted:function(){this.change()},data:function(){let e=this.vValue;return"number"!=typeof(e=null==e?{count:this.vCount,unit:this.vUnit}:e).count&&(e.count=-1),{duration:e,countString:0<=e.count?e.count.toString():""}},watch:{countString:function(e){var e=e.trim();0==e.length?this.duration.count=-1:(e=parseInt(e),isNaN(e)||(this.duration.count=e),this.change())}},methods:{change:function(){this.$emit("change",this.duration)}},template:`
+
`}),Vue.component("dot",{template:''}),Vue.component("time-duration-box",{props:["v-name","v-value","v-count","v-unit"],mounted:function(){this.change()},data:function(){let e=this.vValue;return"number"!=typeof(e=null==e?{count:this.vCount,unit:this.vUnit}:e).count&&(e.count=-1),{duration:e,countString:0<=e.count?e.count.toString():""}},watch:{countString:function(e){var e=e.trim();0==e.length?this.duration.count=-1:(e=parseInt(e),isNaN(e)||(this.duration.count=e),this.change())}},methods:{change:function(){this.$emit("change",this.duration)}},template:`
@@ -4685,7 +4773,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
`}),Vue.component("datepicker",{props:["v-name","v-value","v-bottom-left"],mounted:function(){let t=this;teaweb.datepicker(this.$refs.dayInput,function(e){t.day=e,t.change()},!!this.vBottomLeft)},data:function(){let e=this.vName,t=(null==e&&(e="day"),this.vValue);return null==t&&(t=""),{name:e,day:t}},methods:{change:function(){this.$emit("change",this.day)}},template:`
-
`}),Vue.component("sort-arrow",{props:["name"],data:function(){let e=window.location.toString(),n="",o=[];if(null!=window.location.search&&0  `}),Vue.component("user-link",{props:["v-user","v-keyword"],data:function(){let e=this.vUser;return{user:e=null==e?{id:0,username:"",fullname:""}:e}},template:`
+
`}),Vue.component("sort-arrow",{props:["name"],data:function(){let e=window.location.toString(),n="",t="",o=[];if(null!=window.location.search&&0  `}),Vue.component("user-link",{props:["v-user","v-keyword"],data:function(){let e=this.vUser;return{user:e=null==e?{id:0,username:"",fullname:""}:e}},template:`
{{user.fullname}}{{user.username}} [已删除]
`}),Vue.component("report-node-groups-selector",{props:["v-group-ids"],mounted:function(){let t=this;Tea.action("/clusters/monitors/groups/options").post().success(function(e){t.groups=e.data.groups.map(function(e){return e.isChecked=t.groupIds.$contains(e.id),e}),t.isLoaded=!0})},data:function(){var e=this.vGroupIds;return{groups:[],groupIds:e=null==e?[]:e,isLoaded:!1,allGroups:0==e.length}},methods:{check:function(e){e.isChecked=!e.isChecked,this.groupIds=[];let t=this;this.groups.forEach(function(e){e.isChecked&&t.groupIds.push(e.id)}),this.change()},change:function(){let t=this,s=[];this.groupIds.forEach(function(i){var e=t.groups.$find(function(e,t){return t.id==i});null!=e&&s.push({id:e.id,name:e.name})}),this.$emit("change",s)}},watch:{allGroups:function(e){e&&(this.groupIds=[],this.groups.forEach(function(e){e.isChecked=!1})),this.change()}},template:`
@@ -4994,7 +5082,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
`}),Vue.component("node-combo-box",{props:["v-cluster-id","v-node-id"],data:function(){let t=this;return Tea.action("/clusters/nodeOptions").params({clusterId:this.vClusterId}).post().success(function(e){t.nodes=e.data.nodes}),{nodes:[]}},template:`
-
`}),Vue.component("node-level-selector",{props:["v-node-level"],data:function(){let e=this.vNodeLevel;return{levels:[{name:"边缘节点",code:1,description:"普通的边缘节点。"},{name:"L2节点",code:2,description:"特殊的边缘节点,同时负责同组上一级节点的回源。"}],levelCode:e=null==e||e<1?1:e}},template:`
+
`}),Vue.component("node-level-selector",{props:["v-node-level"],data:function(){let e=this.vNodeLevel;return{levels:[{name:"边缘节点",code:1,description:"普通的边缘节点。"},{name:"L2节点",code:2,description:"特殊的边缘节点,同时负责同组上一级节点的回源。"}],levelCode:e=null==e||e<1?1:e}},watch:{levelCode:function(e){this.$emit("change",e)}},template:`
diff --git a/web/public/js/components.src.js b/web/public/js/components.src.js index 576de298..474a0cd3 100755 --- a/web/public/js/components.src.js +++ b/web/public/js/components.src.js @@ -449,6 +449,7 @@ Vue.component("node-ddos-protection-config-box", { maxConnections: 0, maxConnectionsPerIP: 0, newConnectionsRate: 0, + denyNewConnectionsRate: 0, allowIPList: [], ports: [] } @@ -463,6 +464,7 @@ Vue.component("node-ddos-protection-config-box", { maxConnections: 0, maxConnectionsPerIP: 0, newConnectionsRate: 0, + denyNewConnectionsRate: 0, allowIPList: [], ports: [] } @@ -528,6 +530,31 @@ Vue.component("node-ddos-protection-config-box", {

单个IP可以创建TCP新连接的速率。如果为0,则默认为{{defaultConfigs.tcpNewConnectionsRate}};最小值为{{defaultConfigs.tcpNewConnectionsMinRate}}。

+ + 单IP TCP新连接速率黑名单 + +
+
+
+ 超过 + + 个新连接/每分钟 +
+
+
+ 屏蔽 +
+
+
+ + +
+
+
+ +

单个IP可以如果在单位时间内创建的TCP连接数超过这个值,就自动加入到nftables黑名单中。如果为0,则默认为{{defaultConfigs.tcpDenyNewConnectionsRate}};最小值为{{defaultConfigs.tcpDenyNewConnectionsMinRate}};默认屏蔽{{defaultConfigs.tcpDenyNewConnectionsRateTimeout}}秒。

+ + TCP端口列表 @@ -1488,6 +1515,7 @@ Vue.component("ns-node-ddos-protection-config-box", { maxConnections: 0, maxConnectionsPerIP: 0, newConnectionsRate: 0, + denyNewConnectionsRate: 0, allowIPList: [], ports: [] } @@ -1502,6 +1530,7 @@ Vue.component("ns-node-ddos-protection-config-box", { maxConnections: 0, maxConnectionsPerIP: 0, newConnectionsRate: 0, + denyNewConnectionsRate: 0, allowIPList: [], ports: [] } @@ -1567,6 +1596,31 @@ Vue.component("ns-node-ddos-protection-config-box", {

单个IP可以创建TCP新连接的速率。如果为0,则默认为{{defaultConfigs.tcpNewConnectionsRate}};最小值为{{defaultConfigs.tcpNewConnectionsMinRate}}。

+ + 单IP TCP新连接速率黑名单 + +
+
+
+ 超过 + + 个新连接/每分钟 +
+
+
+ 屏蔽 +
+
+
+ + +
+
+
+ +

单个IP可以如果在单位时间内创建的TCP连接数超过这个值,就自动加入到nftables黑名单中。如果为0,则默认为{{defaultConfigs.tcpDenyNewConnectionsRate}};最小值为{{defaultConfigs.tcpDenyNewConnectionsMinRate}};默认屏蔽{{defaultConfigs.tcpDenyNewConnectionsRateTimeout}}秒。

+ + TCP端口列表 @@ -4217,7 +4271,7 @@ Vue.component("http-request-limit-config-box", { 单IP最大并发连接数 -

单IP最大连接数,统计单个IP总连接数时不区分服务,超出此限制则响应用户429代码。为0表示不限制。

+

单IP最大连接数,统计单个IP总连接数时不区分服务,超出此限制则响应用户429代码。为0表示不限制。当前设置的并发连接数过低,可能会影响正常用户访问,建议不小于3。

@@ -5198,6 +5252,13 @@ Vue.component("http-firewall-checkpoint-cc", { value: ignoreCommonFiles } ] + }, + thresholdTooLow: function () { + let threshold = parseInt(this.threshold.toString()) + if (isNaN(threshold) || threshold <= 0) { + threshold = 1000 + } + return threshold > 0 && threshold < 5 } }, template: `
@@ -5223,6 +5284,7 @@ Vue.component("http-firewall-checkpoint-cc", { 阈值 * +

对于网站类应用来说,当前阈值设置的太低,有可能会影响用户正常访问。

@@ -5335,7 +5397,7 @@ Vue.component("http-firewall-checkpoint-referer-block", { }) Vue.component("http-access-log-partitions-box", { - props: ["v-partition", "v-day"], + props: ["v-partition", "v-day", "v-query"], mounted: function () { let that = this Tea.action("/servers/logs/partitionData") @@ -5347,13 +5409,18 @@ Vue.component("http-access-log-partitions-box", { resp.data.partitions.reverse().forEach(function (v) { that.partitions.push({ code: v, - isDisabled: false + isDisabled: false, + hasLogs: false }) }) if (that.partitions.length > 0) { if (that.vPartition == null || that.vPartition < 0) { that.selectedPartition = that.partitions[0].code } + + if (that.partitions.length > 1) { + that.checkLogs() + } } }) .post() @@ -5361,7 +5428,8 @@ Vue.component("http-access-log-partitions-box", { data: function () { return { partitions: [], - selectedPartition: this.vPartition + selectedPartition: this.vPartition, + checkingPartition: 0 } }, methods: { @@ -5384,12 +5452,43 @@ Vue.component("http-access-log-partitions-box", { p.isDisabled = true } }) + }, + checkLogs: function () { + let that = this + let index = this.checkingPartition + let params = { + partition: index + } + let query = this.vQuery + if (query == null || query.length == 0) { + return + } + query.split("&").forEach(function (v) { + let param = v.split("=") + params[param[0]] = decodeURIComponent(param[1]) + }) + Tea.action("/servers/logs/hasLogs") + .params(params) + .post() + .success(function (response) { + if (response.data.hasLogs) { + // 因为是倒序,所以这里需要使用总长度减去index + that.partitions[that.partitions.length - 1 - index].hasLogs = true + } + + index++ + if (index >= that.partitions.length) { + return + } + that.checkingPartition = index + that.checkLogs() + }) } }, template: `` @@ -6560,8 +6659,11 @@ Vue.component("http-firewall-actions-box", { captchaLife: "", captchaMaxFails: "", captchaFailBlockTimeout: "", + get302Life: "", + post307Life: "", + recordIPType: "black", recordIPLevel: "critical", recordIPTimeout: "", @@ -6579,7 +6681,11 @@ Vue.component("http-firewall-actions-box", { goGroup: null, goSetId: 0, - goSetName: "" + goSetName: "", + + jsCookieLife: "", + jsCookieMaxFails: "", + jsCookieFailBlockTimeout: "" } }, watch: { @@ -6677,7 +6783,31 @@ Vue.component("http-firewall-actions-box", { } else { this.goSetName = set.name } - } + }, + jsCookieLife: function (v) { + v = parseInt(v) + if (isNaN(v)) { + this.actionOptions["life"] = 0 + } else { + this.actionOptions["life"] = v + } + }, + jsCookieMaxFails: function (v) { + v = parseInt(v) + if (isNaN(v)) { + this.actionOptions["maxFails"] = 0 + } else { + this.actionOptions["maxFails"] = v + } + }, + jsCookieFailBlockTimeout: function (v) { + v = parseInt(v) + if (isNaN(v)) { + this.actionOptions["failBlockTimeout"] = 0 + } else { + this.actionOptions["failBlockTimeout"] = v + } + }, }, methods: { add: function () { @@ -6689,10 +6819,17 @@ Vue.component("http-firewall-actions-box", { // 动作参数 this.blockTimeout = "" this.blockScope = "global" + this.captchaLife = "" this.captchaMaxFails = "" this.captchaFailBlockTimeout = "" + + this.jsCookieLife = "" + this.jsCookieMaxFails = "" + this.jsCookieFailBlockTimeout = "" + this.get302Life = "" + this.post307Life = "" this.recordIPLevel = "critical" @@ -6769,6 +6906,20 @@ Vue.component("http-firewall-actions-box", { this.captchaFailBlockTimeout = config.options.failBlockTimeout.toString() } break + case "js_cookie": + this.jsCookieLife = "" + if (config.options.life != null || config.options.life > 0) { + this.jsCookieLife = config.options.life.toString() + } + this.jsCookieMaxFails = "" + if (config.options.maxFails != null || config.options.maxFails > 0) { + this.jsCookieMaxFails = config.options.maxFails.toString() + } + this.jsCookieFailBlockTimeout = "" + if (config.options.failBlockTimeout != null || config.options.failBlockTimeout > 0) { + this.jsCookieFailBlockTimeout = config.options.failBlockTimeout.toString() + } + break case "notify": break case "get_302": @@ -7021,6 +7172,11 @@ Vue.component("http-firewall-actions-box", { / 最多失败{{config.options.maxFails}}次 + + :有效期{{config.options.life}}秒 + / 最多失败{{config.options.maxFails}}次 + + :有效期{{config.options.life}}秒 @@ -7120,6 +7276,38 @@ Vue.component("http-firewall-actions-box", { + + + 有效时间 + +
+ + +
+

验证通过后在这个时间内不再验证;如果为空或者为0表示默认。

+ + + + 最多失败次数 + +
+ + +
+

允许用户失败尝试的最多次数,超过这个次数将被自动加入黑名单;如果为空或者为0表示默认。

+ + + + 失败拦截时间 + +
+ + +
+

在达到最多失败次数(大于0)时,自动拦截的时间;如果为空或者为0表示默认。

+ + + 有效时间 @@ -13914,6 +14102,10 @@ Vue.component("combo-box", {
` }) +Vue.component("dot", { + template: '' +}) + Vue.component("time-duration-box", { props: ["v-name", "v-value", "v-count", "v-unit"], mounted: function () { @@ -14626,6 +14818,7 @@ Vue.component("sort-arrow", { data: function () { let url = window.location.toString() let order = "" + let iconTitle = "" let newArgs = [] if (window.location.search != null && window.location.search.length > 0) { let queryString = window.location.search.substring(1) @@ -14648,10 +14841,13 @@ Vue.component("sort-arrow", { } if (order == "asc") { newArgs.push(this.name + "=desc") + iconTitle = "当前正序排列" } else if (order == "desc") { newArgs.push(this.name + "=asc") + iconTitle = "当前倒序排列" } else { newArgs.push(this.name + "=desc") + iconTitle = "当前正序排列" } let qIndex = url.indexOf("?") @@ -14663,10 +14859,11 @@ Vue.component("sort-arrow", { return { order: order, - url: url + url: url, + iconTitle: iconTitle } }, - template: `  ` + template: `  ` }) Vue.component("user-link", { @@ -15747,6 +15944,11 @@ Vue.component("node-level-selector", { levelCode: levelCode } }, + watch: { + levelCode: function (code) { + this.$emit("change", code) + } + }, template: `