mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-13 23:10:25 +08:00
优化验证码失败次数统计
This commit is contained in:
@@ -13,7 +13,6 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
"github.com/TeaOSLab/EdgeNode/internal/rpc"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
"github.com/iwind/TeaGo/logs"
|
|
||||||
stringutil "github.com/iwind/TeaGo/utils/string"
|
stringutil "github.com/iwind/TeaGo/utils/string"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -64,7 +63,7 @@ func (this *UpgradeManager) Start() {
|
|||||||
goman.New(func() {
|
goman.New(func() {
|
||||||
err = this.restart()
|
err = this.restart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("UPGRADE_MANAGER", err.Error())
|
remotelogs.Error("UPGRADE_MANAGER", err.Error())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,17 +98,17 @@ func (this *CaptchaAction) WillChange() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *CaptchaAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, request requests.Request, writer http.ResponseWriter) (allow bool) {
|
func (this *CaptchaAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req requests.Request, writer http.ResponseWriter) (allow bool) {
|
||||||
// 是否在白名单中
|
// 是否在白名单中
|
||||||
if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, request.WAFServerId(), request.WAFRemoteIP()) {
|
if SharedIPWhiteList.Contains("set:"+types.String(set.Id), this.Scope, req.WAFServerId(), req.WAFRemoteIP()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
var refURL = request.WAFRaw().URL.String()
|
var refURL = req.WAFRaw().URL.String()
|
||||||
|
|
||||||
// 覆盖配置
|
// 覆盖配置
|
||||||
if strings.HasPrefix(refURL, CaptchaPath) {
|
if strings.HasPrefix(refURL, CaptchaPath) {
|
||||||
info := request.WAFRaw().URL.Query().Get("info")
|
info := req.WAFRaw().URL.Query().Get("info")
|
||||||
if len(info) > 0 {
|
if len(info) > 0 {
|
||||||
m, err := utils.SimpleDecryptMap(info)
|
m, err := utils.SimpleDecryptMap(info)
|
||||||
if err == nil && m != nil {
|
if err == nil && m != nil {
|
||||||
@@ -131,7 +131,10 @@ func (this *CaptchaAction) Perform(waf *WAF, group *RuleGroup, set *RuleSet, req
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Redirect(writer, request.WAFRaw(), CaptchaPath+"?info="+url.QueryEscape(info), http.StatusTemporaryRedirect)
|
// 占用一次失败次数
|
||||||
|
CaptchaIncreaseFails(req, this, waf.Id, group.Id, set.Id, CaptchaPageCodeInit)
|
||||||
|
|
||||||
|
http.Redirect(writer, req.WAFRaw(), CaptchaPath+"?info="+url.QueryEscape(info), http.StatusTemporaryRedirect)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
54
internal/waf/captcha_counter.go
Normal file
54
internal/waf/captcha_counter.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
|
||||||
|
|
||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/ttlcache"
|
||||||
|
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||||
|
"github.com/iwind/TeaGo/types"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CaptchaPageCode = string
|
||||||
|
|
||||||
|
const (
|
||||||
|
CaptchaPageCodeInit CaptchaPageCode = "init"
|
||||||
|
CaptchaPageCodeShow CaptchaPageCode = "show"
|
||||||
|
CaptchaPageCodeSubmit CaptchaPageCode = "submit"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CaptchaIncreaseFails 增加Captcha失败次数,以便后续操作
|
||||||
|
func CaptchaIncreaseFails(req requests.Request, actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, pageCode CaptchaPageCode) (goNext bool) {
|
||||||
|
var maxFails = actionConfig.MaxFails
|
||||||
|
var failBlockTimeout = actionConfig.FailBlockTimeout
|
||||||
|
if maxFails > 0 && failBlockTimeout > 0 {
|
||||||
|
if maxFails <= 3 {
|
||||||
|
maxFails = 3 // 不能小于3,防止意外刷新出现
|
||||||
|
}
|
||||||
|
var countFails = ttlcache.SharedCache.IncreaseInt64(CaptchaCacheKey(req, pageCode), 1, time.Now().Unix()+300, true)
|
||||||
|
if int(countFails) >= maxFails {
|
||||||
|
var useLocalFirewall = false
|
||||||
|
|
||||||
|
if actionConfig.FailBlockScopeAll {
|
||||||
|
useLocalFirewall = true
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedIPBlackList.RecordIP(IPTypeAll, firewallconfigs.FirewallScopeService, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(failBlockTimeout), policyId, useLocalFirewall, groupId, setId, "CAPTCHA验证连续失败")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptchaDeleteCacheKey 清除计数
|
||||||
|
func CaptchaDeleteCacheKey(req requests.Request) {
|
||||||
|
ttlcache.SharedCache.Delete(CaptchaCacheKey(req, CaptchaPageCodeInit))
|
||||||
|
ttlcache.SharedCache.Delete(CaptchaCacheKey(req, CaptchaPageCodeShow))
|
||||||
|
ttlcache.SharedCache.Delete(CaptchaCacheKey(req, CaptchaPageCodeSubmit))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptchaCacheKey 获取Captcha缓存Key
|
||||||
|
func CaptchaCacheKey(req requests.Request, pageCode CaptchaPageCode) string {
|
||||||
|
return "CAPTCHA:FAILS:" + pageCode + ":" + req.WAFRemoteIP() + ":" + types.String(req.WAFServerId())
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ package waf
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs"
|
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/ttlcache"
|
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
"github.com/TeaOSLab/EdgeNode/internal/utils"
|
||||||
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
||||||
"github.com/dchest/captcha"
|
"github.com/dchest/captcha"
|
||||||
@@ -70,7 +68,7 @@ func (this *CaptchaValidator) Run(req requests.Request, writer http.ResponseWrit
|
|||||||
this.validate(captchaActionConfig, policyId, groupId, setId, originURL, req, writer)
|
this.validate(captchaActionConfig, policyId, groupId, setId, originURL, req, writer)
|
||||||
} else {
|
} else {
|
||||||
// 增加计数
|
// 增加计数
|
||||||
this.IncreaseFails(req, captchaActionConfig, policyId, groupId, setId)
|
CaptchaIncreaseFails(req, captchaActionConfig, policyId, groupId, setId, CaptchaPageCodeShow)
|
||||||
this.show(captchaActionConfig, req, writer)
|
this.show(captchaActionConfig, req, writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,6 +127,29 @@ func (this *CaptchaValidator) show(actionConfig *CaptchaAction, req requests.Req
|
|||||||
var msgCss = ""
|
var msgCss = ""
|
||||||
var requestIdBox = `<address>` + msgRequestId + `: ` + req.Format("${requestId}") + `</address>`
|
var requestIdBox = `<address>` + msgRequestId + `: ` + req.Format("${requestId}") + `</address>`
|
||||||
var msgFooter = ""
|
var msgFooter = ""
|
||||||
|
|
||||||
|
// 默认设置
|
||||||
|
if actionConfig.UIIsOn {
|
||||||
|
if len(actionConfig.UIPrompt) > 0 {
|
||||||
|
msgPrompt = actionConfig.UIPrompt
|
||||||
|
}
|
||||||
|
if len(actionConfig.UIButtonTitle) > 0 {
|
||||||
|
msgButtonTitle = actionConfig.UIButtonTitle
|
||||||
|
}
|
||||||
|
if len(actionConfig.UITitle) > 0 {
|
||||||
|
msgTitle = actionConfig.UITitle
|
||||||
|
}
|
||||||
|
if len(actionConfig.UICss) > 0 {
|
||||||
|
msgCss = actionConfig.UICss
|
||||||
|
}
|
||||||
|
if !actionConfig.UIShowRequestId {
|
||||||
|
requestIdBox = ""
|
||||||
|
}
|
||||||
|
if len(actionConfig.UIFooter) > 0 {
|
||||||
|
msgFooter = actionConfig.UIFooter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var body = `<form method="POST">
|
var body = `<form method="POST">
|
||||||
<input type="hidden" name="GOEDGE_WAF_CAPTCHA_ID" value="` + captchaId + `"/>
|
<input type="hidden" name="GOEDGE_WAF_CAPTCHA_ID" value="` + captchaId + `"/>
|
||||||
<div class="ui-image">
|
<div class="ui-image">
|
||||||
@@ -145,26 +166,8 @@ func (this *CaptchaValidator) show(actionConfig *CaptchaAction, req requests.Req
|
|||||||
` + requestIdBox + `
|
` + requestIdBox + `
|
||||||
` + msgFooter + ``
|
` + msgFooter + ``
|
||||||
|
|
||||||
// 默认设置
|
// Body
|
||||||
if actionConfig.UIIsOn {
|
if actionConfig.UIIsOn {
|
||||||
if len(actionConfig.UITitle) > 0 {
|
|
||||||
msgTitle = actionConfig.UITitle
|
|
||||||
}
|
|
||||||
if len(actionConfig.UIPrompt) > 0 {
|
|
||||||
msgPrompt = actionConfig.UIPrompt
|
|
||||||
}
|
|
||||||
if len(actionConfig.UIButtonTitle) > 0 {
|
|
||||||
msgButtonTitle = actionConfig.UIButtonTitle
|
|
||||||
}
|
|
||||||
if len(actionConfig.UICss) > 0 {
|
|
||||||
msgCss = actionConfig.UICss
|
|
||||||
}
|
|
||||||
if !actionConfig.UIShowRequestId {
|
|
||||||
requestIdBox = ""
|
|
||||||
}
|
|
||||||
if len(actionConfig.UIFooter) > 0 {
|
|
||||||
msgFooter = actionConfig.UIFooter
|
|
||||||
}
|
|
||||||
if len(actionConfig.UIBody) > 0 {
|
if len(actionConfig.UIBody) > 0 {
|
||||||
var index = strings.Index(actionConfig.UIBody, "${body}")
|
var index = strings.Index(actionConfig.UIBody, "${body}")
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
@@ -208,7 +211,7 @@ func (this *CaptchaValidator) validate(actionConfig *CaptchaAction, policyId int
|
|||||||
var captchaCode = req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_CODE")
|
var captchaCode = req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_CODE")
|
||||||
if captcha.VerifyString(captchaId, captchaCode) {
|
if captcha.VerifyString(captchaId, captchaCode) {
|
||||||
// 清除计数
|
// 清除计数
|
||||||
ttlcache.SharedCache.Delete(this.cacheKey(req))
|
CaptchaDeleteCacheKey(req)
|
||||||
|
|
||||||
var life = CaptchaSeconds
|
var life = CaptchaSeconds
|
||||||
if actionConfig.Life > 0 {
|
if actionConfig.Life > 0 {
|
||||||
@@ -223,7 +226,7 @@ func (this *CaptchaValidator) validate(actionConfig *CaptchaAction, policyId int
|
|||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
// 增加计数
|
// 增加计数
|
||||||
if !this.IncreaseFails(req, actionConfig, policyId, groupId, setId) {
|
if !CaptchaIncreaseFails(req, actionConfig, policyId, groupId, setId, CaptchaPageCodeSubmit) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,30 +236,3 @@ func (this *CaptchaValidator) validate(actionConfig *CaptchaAction, policyId int
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncreaseFails 增加失败次数,以便后续操作
|
|
||||||
func (this *CaptchaValidator) IncreaseFails(req requests.Request, actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64) (goNext bool) {
|
|
||||||
var maxFails = actionConfig.MaxFails
|
|
||||||
var failBlockTimeout = actionConfig.FailBlockTimeout
|
|
||||||
if maxFails > 0 && failBlockTimeout > 0 {
|
|
||||||
// 加上展示的计数
|
|
||||||
maxFails *= 2
|
|
||||||
|
|
||||||
var countFails = ttlcache.SharedCache.IncreaseInt64(this.cacheKey(req), 1, time.Now().Unix()+300, true)
|
|
||||||
if int(countFails) >= maxFails {
|
|
||||||
var useLocalFirewall = false
|
|
||||||
|
|
||||||
if actionConfig.FailBlockScopeAll {
|
|
||||||
useLocalFirewall = true
|
|
||||||
}
|
|
||||||
|
|
||||||
SharedIPBlackList.RecordIP(IPTypeAll, firewallconfigs.FirewallScopeService, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(failBlockTimeout), policyId, useLocalFirewall, groupId, setId, "CAPTCHA验证连续失败")
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (this *CaptchaValidator) cacheKey(req requests.Request) string {
|
|
||||||
return "CAPTCHA:FAILS:" + req.WAFRemoteIP() + ":" + types.String(req.WAFServerId())
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user