实现自动SYN Flood防护

This commit is contained in:
GoEdgeLab
2022-01-10 19:54:29 +08:00
parent 0e531443f2
commit 81388d43e6
9 changed files with 186 additions and 18 deletions

View File

@@ -84,6 +84,7 @@ func (this *PolicyAction) RunGet(params struct {
if len(firewallPolicy.Mode) == 0 {
firewallPolicy.Mode = firewallconfigs.FirewallModeDefend
}
this.Data["firewallPolicy"] = maps.Map{
"id": firewallPolicy.Id,
"name": firewallPolicy.Name,
@@ -94,6 +95,7 @@ func (this *PolicyAction) RunGet(params struct {
"groups": internalGroups,
"blockOptions": firewallPolicy.BlockOptions,
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
"synFlood": firewallPolicy.SYNFlood,
}
// 正在使用此策略的集群

View File

@@ -48,6 +48,16 @@ func (this *UpdateAction) RunGet(params struct {
}
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{
"id": firewallPolicy.Id,
"name": firewallPolicy.Name,
@@ -56,6 +66,7 @@ func (this *UpdateAction) RunGet(params struct {
"mode": firewallPolicy.Mode,
"blockOptions": firewallPolicy.BlockOptions,
"useLocalFirewall": firewallPolicy.UseLocalFirewall,
"synFloodConfig": firewallPolicy.SYNFlood,
}
// 预置分组
@@ -89,6 +100,7 @@ func (this *UpdateAction) RunPost(params struct {
IsOn bool
Mode string
UseLocalFirewall bool
SynFloodJSON []byte
Must *actions.Must
}) {
@@ -115,6 +127,7 @@ func (this *UpdateAction) RunPost(params struct {
BlockOptionsJSON: params.BlockOptionsJSON,
Mode: params.Mode,
UseLocalFirewall: params.UseLocalFirewall,
SynFloodJSON: params.SynFloodJSON,
})
if err != nil {
this.ErrorPage(err)

View File

@@ -10,6 +10,7 @@ import (
func init() {
TeaGo.BeforeStart(func(server *TeaGo.Server) {
server.
Data("teaMenu", "servers").
Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)).
Helper(NewHelper()).
Prefix("/servers").

View File

@@ -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{
"id": item.Id,
"ipFrom": item.IpFrom,
@@ -149,6 +159,7 @@ func (this *IndexAction) RunGet(params struct {
"sourceGroup": sourceGroupMap,
"sourceSet": sourceSetMap,
"sourceServer": sourceServerMap,
"sourceNode": sourceNodeMap,
"list": listMap,
"policy": policyMap,
})

View File

@@ -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}} &raquo; {{item.sourceGroup.name}} &raquo; {{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}} &raquo; {{item.sourceGroup.name}} &raquo; {{item.sourceSet.name}}</span></a>
</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>
<a href="" @click.prevent="viewLogs(item.id)">日志</a> &nbsp;

View File

@@ -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>`
})

View File

@@ -4,7 +4,8 @@ Vue.component("http-firewall-block-options", {
return {
blockOptions: this.vBlockOptions,
statusCode: this.vBlockOptions.statusCode,
timeout: this.vBlockOptions.timeout
timeout: this.vBlockOptions.timeout,
isEditing: false
}
},
watch: {
@@ -25,9 +26,15 @@ Vue.component("http-firewall-block-options", {
}
}
},
methods: {
edit: function () {
this.isEditing = !this.isEditing
}
},
template: `<div>
<input type="hidden" name="blockOptionsJSON" :value="JSON.stringify(blockOptions)"/>
<table class="ui table">
<input type="hidden" name="blockOptionsJSON" :value="JSON.stringify(blockOptions)"/>
<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>
<td class="title">状态码</td>
<td>

View File

@@ -59,6 +59,39 @@
<p class="comment" v-if="firewallPolicy.useLocalFirewall">可以在合适的时候自动使用系统自带防火墙进行防御。</p>
</td>
</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>
<td>描述</td>
<td>

View File

@@ -43,26 +43,32 @@
<checkbox name="useLocalFirewall" v-model="firewallPolicy.useLocalFirewall"></checkbox>
<p class="comment">开启后,可以在合适的时候自动使用系统自带防火墙进行防御。</p>
</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>
<td colspan="2"><more-options-indicator></more-options-indicator></td>
</tr>
<tbody v-show="moreOptionsVisible">
<tr>
<td>描述</td>
<td>
<textarea name="description" rows="3" v-model="firewallPolicy.description"></textarea>
</td>
</tr>
<tr>
<td>是否启用</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isOn" value="1" v-model="firewallPolicy.isOn"/>
<label></label>
</div>
</td>
</tr>
<tr>
<td>描述</td>
<td>
<textarea name="description" rows="3" v-model="firewallPolicy.description"></textarea>
</td>
</tr>
<tr>
<td>是否启用</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="isOn" value="1" v-model="firewallPolicy.isOn"/>
<label></label>
</div>
</td>
</tr>
</tbody>
</table>
<submit-btn></submit-btn>