mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-14 04:10:26 +08:00
实现自动SYN Flood防护
This commit is contained in:
@@ -84,6 +84,7 @@ func (this *PolicyAction) RunGet(params struct {
|
|||||||
if len(firewallPolicy.Mode) == 0 {
|
if len(firewallPolicy.Mode) == 0 {
|
||||||
firewallPolicy.Mode = firewallconfigs.FirewallModeDefend
|
firewallPolicy.Mode = firewallconfigs.FirewallModeDefend
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Data["firewallPolicy"] = maps.Map{
|
this.Data["firewallPolicy"] = maps.Map{
|
||||||
"id": firewallPolicy.Id,
|
"id": firewallPolicy.Id,
|
||||||
"name": firewallPolicy.Name,
|
"name": firewallPolicy.Name,
|
||||||
@@ -94,6 +95,7 @@ func (this *PolicyAction) RunGet(params struct {
|
|||||||
"groups": internalGroups,
|
"groups": internalGroups,
|
||||||
"blockOptions": firewallPolicy.BlockOptions,
|
"blockOptions": firewallPolicy.BlockOptions,
|
||||||
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
|
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
|
||||||
|
"synFlood": firewallPolicy.SYNFlood,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 正在使用此策略的集群
|
// 正在使用此策略的集群
|
||||||
|
|||||||
@@ -48,6 +48,16 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
this.Data["modes"] = firewallconfigs.FindAllFirewallModes()
|
this.Data["modes"] = firewallconfigs.FindAllFirewallModes()
|
||||||
|
|
||||||
|
// syn flood
|
||||||
|
if firewallPolicy.SYNFlood == nil {
|
||||||
|
firewallPolicy.SYNFlood = &firewallconfigs.SYNFloodConfig{
|
||||||
|
IsOn: false,
|
||||||
|
MinAttempts: 10,
|
||||||
|
TimeoutSeconds: 600,
|
||||||
|
IgnoreLocal: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.Data["firewallPolicy"] = maps.Map{
|
this.Data["firewallPolicy"] = maps.Map{
|
||||||
"id": firewallPolicy.Id,
|
"id": firewallPolicy.Id,
|
||||||
"name": firewallPolicy.Name,
|
"name": firewallPolicy.Name,
|
||||||
@@ -56,6 +66,7 @@ func (this *UpdateAction) RunGet(params struct {
|
|||||||
"mode": firewallPolicy.Mode,
|
"mode": firewallPolicy.Mode,
|
||||||
"blockOptions": firewallPolicy.BlockOptions,
|
"blockOptions": firewallPolicy.BlockOptions,
|
||||||
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
|
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
|
||||||
|
"synFloodConfig": firewallPolicy.SYNFlood,
|
||||||
}
|
}
|
||||||
|
|
||||||
// 预置分组
|
// 预置分组
|
||||||
@@ -89,6 +100,7 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
IsOn bool
|
IsOn bool
|
||||||
Mode string
|
Mode string
|
||||||
UseLocalFirewall bool
|
UseLocalFirewall bool
|
||||||
|
SynFloodJSON []byte
|
||||||
|
|
||||||
Must *actions.Must
|
Must *actions.Must
|
||||||
}) {
|
}) {
|
||||||
@@ -115,6 +127,7 @@ func (this *UpdateAction) RunPost(params struct {
|
|||||||
BlockOptionsJSON: params.BlockOptionsJSON,
|
BlockOptionsJSON: params.BlockOptionsJSON,
|
||||||
Mode: params.Mode,
|
Mode: params.Mode,
|
||||||
UseLocalFirewall: params.UseLocalFirewall,
|
UseLocalFirewall: params.UseLocalFirewall,
|
||||||
|
SynFloodJSON: params.SynFloodJSON,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
this.ErrorPage(err)
|
this.ErrorPage(err)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
TeaGo.BeforeStart(func(server *TeaGo.Server) {
|
||||||
server.
|
server.
|
||||||
|
Data("teaMenu", "servers").
|
||||||
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
|
||||||
Helper(NewHelper()).
|
Helper(NewHelper()).
|
||||||
Prefix("/servers").
|
Prefix("/servers").
|
||||||
|
|||||||
@@ -133,6 +133,16 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// node
|
||||||
|
var sourceNodeMap = maps.Map{"id": 0}
|
||||||
|
if item.SourceNode != nil && item.SourceNode.NodeCluster != nil {
|
||||||
|
sourceNodeMap = maps.Map{
|
||||||
|
"id": item.SourceNode.Id,
|
||||||
|
"name": item.SourceNode.Name,
|
||||||
|
"clusterId": item.SourceNode.NodeCluster.Id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
itemMaps = append(itemMaps, maps.Map{
|
itemMaps = append(itemMaps, maps.Map{
|
||||||
"id": item.Id,
|
"id": item.Id,
|
||||||
"ipFrom": item.IpFrom,
|
"ipFrom": item.IpFrom,
|
||||||
@@ -149,6 +159,7 @@ func (this *IndexAction) RunGet(params struct {
|
|||||||
"sourceGroup": sourceGroupMap,
|
"sourceGroup": sourceGroupMap,
|
||||||
"sourceSet": sourceSetMap,
|
"sourceSet": sourceSetMap,
|
||||||
"sourceServer": sourceServerMap,
|
"sourceServer": sourceServerMap,
|
||||||
|
"sourceNode": sourceNodeMap,
|
||||||
"list": listMap,
|
"list": listMap,
|
||||||
"policy": policyMap,
|
"policy": policyMap,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -172,6 +172,9 @@ Vue.component("ip-list-table", {
|
|||||||
<a :href="'/servers/components/waf/group?firewallPolicyId=' + item.sourcePolicy.id + '&type=inbound&groupId=' + item.sourceGroup.id" v-if="item.sourcePolicy.serverId == 0"><span class="small "><i class="icon shield"></i>{{item.sourcePolicy.name}} » {{item.sourceGroup.name}} » {{item.sourceSet.name}}</span></a>
|
<a :href="'/servers/components/waf/group?firewallPolicyId=' + item.sourcePolicy.id + '&type=inbound&groupId=' + item.sourceGroup.id" v-if="item.sourcePolicy.serverId == 0"><span class="small "><i class="icon shield"></i>{{item.sourcePolicy.name}} » {{item.sourceGroup.name}} » {{item.sourceSet.name}}</span></a>
|
||||||
<a :href="'/servers/server/settings/waf/group?serverId=' + item.sourcePolicy.serverId + '&firewallPolicyId=' + item.sourcePolicy.id + '&type=inbound&groupId=' + item.sourceGroup.id" v-if="item.sourcePolicy.serverId > 0"><span class="small "><i class="icon shield"></i> {{item.sourcePolicy.name}} » {{item.sourceGroup.name}} » {{item.sourceSet.name}}</span></a>
|
<a :href="'/servers/server/settings/waf/group?serverId=' + item.sourcePolicy.serverId + '&firewallPolicyId=' + item.sourcePolicy.id + '&type=inbound&groupId=' + item.sourceGroup.id" v-if="item.sourcePolicy.serverId > 0"><span class="small "><i class="icon shield"></i> {{item.sourcePolicy.name}} » {{item.sourceGroup.name}} » {{item.sourceSet.name}}</span></a>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="item.sourceNode != null && item.sourceNode.id > 0" style="margin-top: 0.4em">
|
||||||
|
<a :href="'/clusters/cluster/node?clusterId=' + item.sourceNode.clusterId + '&nodeId=' + item.sourceNode.id"><span class="small"><i class="icon cloud"></i>{{item.sourceNode.name}}</span></a>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="" @click.prevent="viewLogs(item.id)">日志</a>
|
<a href="" @click.prevent="viewLogs(item.id)">日志</a>
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
Vue.component("firewall-syn-flood-config-box", {
|
||||||
|
props: ["v-syn-flood-config"],
|
||||||
|
data: function () {
|
||||||
|
let config = this.vSynFloodConfig
|
||||||
|
if (config == null) {
|
||||||
|
config = {
|
||||||
|
isOn: false,
|
||||||
|
minAttempts: 10,
|
||||||
|
timeoutSeconds: 600,
|
||||||
|
ignoreLocal: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
config: config,
|
||||||
|
isEditing: false,
|
||||||
|
minAttempts: config.minAttempts,
|
||||||
|
timeoutSeconds: config.timeoutSeconds
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
edit: function () {
|
||||||
|
this.isEditing = !this.isEditing
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
minAttempts: function (v) {
|
||||||
|
let count = parseInt(v)
|
||||||
|
if (isNaN(count)) {
|
||||||
|
count = 10
|
||||||
|
}
|
||||||
|
if (count < 3) {
|
||||||
|
count = 3
|
||||||
|
}
|
||||||
|
this.config.minAttempts = count
|
||||||
|
},
|
||||||
|
timeoutSeconds: function (v) {
|
||||||
|
let seconds = parseInt(v)
|
||||||
|
if (isNaN(seconds)) {
|
||||||
|
seconds = 10
|
||||||
|
}
|
||||||
|
if (seconds < 60) {
|
||||||
|
seconds = 60
|
||||||
|
}
|
||||||
|
this.config.timeoutSeconds = seconds
|
||||||
|
}
|
||||||
|
},
|
||||||
|
template: `<div>
|
||||||
|
<input type="hidden" name="synFloodJSON" :value="JSON.stringify(config)"/>
|
||||||
|
<a href="" @click.prevent="edit">
|
||||||
|
<span v-if="config.isOn">
|
||||||
|
已启用 / <span>空连接次数:{{config.minAttempts}}次/分钟</span> / 封禁时间:{{config.timeoutSeconds}}秒 <span v-if="config.ignoreLocal">/ 忽略局域网访问</span>
|
||||||
|
</span>
|
||||||
|
<span v-else>未启用</span>
|
||||||
|
<i class="icon angle" :class="{up: isEditing, down: !isEditing}"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<table class="ui table selectable" v-show="isEditing">
|
||||||
|
<tr>
|
||||||
|
<td class="title">是否启用</td>
|
||||||
|
<td>
|
||||||
|
<checkbox v-model="config.isOn"></checkbox>
|
||||||
|
<p class="comment">启用后,WAF将会尝试自动检测并阻止SYN Flood攻击。此功能需要节点已安装并启用Firewalld。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>空连接次数</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" v-model="minAttempts" style="width: 5em" maxlength="4"/>
|
||||||
|
<span class="ui label">次/分钟</span>
|
||||||
|
</div>
|
||||||
|
<p class="comment">超过此数字的"空连接"将被视为SYN Flood攻击,为了防止误判,此数值默认不小于3。</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>封禁时间</td>
|
||||||
|
<td>
|
||||||
|
<div class="ui input right labeled">
|
||||||
|
<input type="text" v-model="timeoutSeconds" style="width: 5em" maxlength="4"/>
|
||||||
|
<span class="ui label">秒</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>忽略局域网访问</td>
|
||||||
|
<td>
|
||||||
|
<checkbox v-model="config.ignoreLocal"></checkbox>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>`
|
||||||
|
})
|
||||||
@@ -4,7 +4,8 @@ Vue.component("http-firewall-block-options", {
|
|||||||
return {
|
return {
|
||||||
blockOptions: this.vBlockOptions,
|
blockOptions: this.vBlockOptions,
|
||||||
statusCode: this.vBlockOptions.statusCode,
|
statusCode: this.vBlockOptions.statusCode,
|
||||||
timeout: this.vBlockOptions.timeout
|
timeout: this.vBlockOptions.timeout,
|
||||||
|
isEditing: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -25,9 +26,15 @@ Vue.component("http-firewall-block-options", {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
edit: function () {
|
||||||
|
this.isEditing = !this.isEditing
|
||||||
|
}
|
||||||
|
},
|
||||||
template: `<div>
|
template: `<div>
|
||||||
<input type="hidden" name="blockOptionsJSON" :value="JSON.stringify(blockOptions)"/>
|
<input type="hidden" name="blockOptionsJSON" :value="JSON.stringify(blockOptions)"/>
|
||||||
<table class="ui table">
|
<a href="" @click.prevent="edit">状态码:{{statusCode}} / 提示内容:<span v-if="blockOptions.body != null && blockOptions.body.length > 0">[{{blockOptions.body.length}}字符]</span><span v-else class="disabled">[无]</span> / 超时时间:{{timeout}}秒 <i class="icon angle" :class="{up: isEditing, down: !isEditing}"></i></a>
|
||||||
|
<table class="ui table" v-show="isEditing">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="title">状态码</td>
|
<td class="title">状态码</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -59,6 +59,39 @@
|
|||||||
<p class="comment" v-if="firewallPolicy.useLocalFirewall">可以在合适的时候自动使用系统自带防火墙进行防御。</p>
|
<p class="comment" v-if="firewallPolicy.useLocalFirewall">可以在合适的时候自动使用系统自带防火墙进行防御。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>SYN Flood防御</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="firewallPolicy.synFlood == null || !firewallPolicy.synFlood.isOn" class="disabled">未启用</span>
|
||||||
|
<table class="ui table selectable" v-if="firewallPolicy.synFlood != null && firewallPolicy.synFlood.isOn">
|
||||||
|
<tr>
|
||||||
|
<td class="title">是否启用</td>
|
||||||
|
<td>
|
||||||
|
<span class="green">启用</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>空连接次数</td>
|
||||||
|
<td>
|
||||||
|
{{firewallPolicy.synFlood.minAttempts}}次/分钟
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>封禁时间</td>
|
||||||
|
<td>
|
||||||
|
{{firewallPolicy.synFlood.timeoutSeconds}}秒
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>忽略局域网访问</td>
|
||||||
|
<td>
|
||||||
|
<span v-if="firewallPolicy.synFlood.ignoreLocal" class="green">Y</span>
|
||||||
|
<span class="disabled" v-else>N</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>描述</td>
|
<td>描述</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -43,26 +43,32 @@
|
|||||||
<checkbox name="useLocalFirewall" v-model="firewallPolicy.useLocalFirewall"></checkbox>
|
<checkbox name="useLocalFirewall" v-model="firewallPolicy.useLocalFirewall"></checkbox>
|
||||||
<p class="comment">开启后,可以在合适的时候自动使用系统自带防火墙进行防御。</p>
|
<p class="comment">开启后,可以在合适的时候自动使用系统自带防火墙进行防御。</p>
|
||||||
</td>
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>SYN Flood防御</td>
|
||||||
|
<td>
|
||||||
|
<firewall-syn-flood-config-box :v-syn-flood-config="firewallPolicy.synFloodConfig"></firewall-syn-flood-config-box>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tbody v-show="moreOptionsVisible">
|
<tbody v-show="moreOptionsVisible">
|
||||||
<tr>
|
<tr>
|
||||||
<td>描述</td>
|
<td>描述</td>
|
||||||
<td>
|
<td>
|
||||||
<textarea name="description" rows="3" v-model="firewallPolicy.description"></textarea>
|
<textarea name="description" rows="3" v-model="firewallPolicy.description"></textarea>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>是否启用</td>
|
<td>是否启用</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui checkbox">
|
<div class="ui checkbox">
|
||||||
<input type="checkbox" name="isOn" value="1" v-model="firewallPolicy.isOn"/>
|
<input type="checkbox" name="isOn" value="1" v-model="firewallPolicy.isOn"/>
|
||||||
<label></label>
|
<label></label>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<submit-btn></submit-btn>
|
<submit-btn></submit-btn>
|
||||||
|
|||||||
Reference in New Issue
Block a user