From 3b52ac0fd298c37f6c98f0282763b2c5e6128a33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E7=A5=A5=E8=B6=85?= Date: Wed, 15 Nov 2023 15:10:25 +0800 Subject: [PATCH] =?UTF-8?q?WAF=E4=BA=BA=E6=9C=BA=E8=AF=86=E5=88=AB?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E7=82=B9=E5=87=BB=E9=AA=8C=E8=AF=81=E5=92=8C?= =?UTF-8?q?=E6=BB=91=E5=8A=A8=E8=A7=A3=E9=94=81=E9=AA=8C=E8=AF=81/?= =?UTF-8?q?=E5=8D=95=E4=B8=AA=E7=BD=91=E7=AB=99=E5=8F=AF=E4=BB=A5=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E9=BB=98=E8=AE=A4=E7=9A=84=E4=BA=BA=E6=9C=BA=E8=AF=86?= =?UTF-8?q?=E5=88=AB=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/nodes/http_request_waf.go | 6 +- internal/waf/action_captcha.go | 23 ++ internal/waf/captcha_validator.go | 396 ++++++++++++++++++++++++++++- internal/waf/rule_group.go | 4 +- internal/waf/waf.go | 10 +- internal/waf/waf_manager.go | 1 + 6 files changed, 422 insertions(+), 18 deletions(-) diff --git a/internal/nodes/http_request_waf.go b/internal/nodes/http_request_waf.go index 4611de8..f9e3be7 100644 --- a/internal/nodes/http_request_waf.go +++ b/internal/nodes/http_request_waf.go @@ -257,7 +257,7 @@ func (this *HTTPRequest) checkWAFRequest(firewallPolicy *firewallconfigs.HTTPFir return } - goNext, hasRequestBody, ruleGroup, ruleSet, err := w.MatchRequest(this, this.writer) + goNext, hasRequestBody, ruleGroup, ruleSet, err := w.MatchRequest(this, this.writer, this.web.FirewallRef.DefaultCaptchaType) if forceLog && logRequestBody && hasRequestBody && ruleSet != nil && ruleSet.HasAttackActions() { this.wafHasRequestBody = true } @@ -307,7 +307,7 @@ func (this *HTTPRequest) doWAFResponse(resp *http.Response) (blocked bool) { } if this.web.FirewallPolicy != nil && this.web.FirewallPolicy.IsOn { - blocked := this.checkWAFResponse(this.web.FirewallPolicy, resp, forceLog, forceLogRequestBody, false) + blocked = this.checkWAFResponse(this.web.FirewallPolicy, resp, forceLog, forceLogRequestBody, false) if blocked { return true } @@ -315,7 +315,7 @@ func (this *HTTPRequest) doWAFResponse(resp *http.Response) (blocked bool) { // 公用的防火墙设置 if this.ReqServer.HTTPFirewallPolicy != nil && this.ReqServer.HTTPFirewallPolicy.IsOn { - blocked := this.checkWAFResponse(this.ReqServer.HTTPFirewallPolicy, resp, forceLog, forceLogRequestBody, this.web.FirewallRef.IgnoreGlobalRules) + blocked = this.checkWAFResponse(this.ReqServer.HTTPFirewallPolicy, resp, forceLog, forceLogRequestBody, this.web.FirewallRef.IgnoreGlobalRules) if blocked { return true } diff --git a/internal/waf/action_captcha.go b/internal/waf/action_captcha.go index cc19334..d9b3fc4 100644 --- a/internal/waf/action_captcha.go +++ b/internal/waf/action_captcha.go @@ -1,6 +1,7 @@ package waf import ( + "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs/firewallconfigs" "github.com/TeaOSLab/EdgeNode/internal/remotelogs" "github.com/TeaOSLab/EdgeNode/internal/utils" "github.com/TeaOSLab/EdgeNode/internal/waf/requests" @@ -27,6 +28,8 @@ type CaptchaAction struct { CountLetters int8 `yaml:"countLetters" json:"countLetters"` + CaptchaType firewallconfigs.CaptchaType `yaml:"captchaType" json:"captchaType"` + UIIsOn bool `yaml:"uiIsOn" json:"uiIsOn"` // 是否使用自定义UI UITitle string `yaml:"uiTitle" json:"uiTitle"` // 消息标题 UIPrompt string `yaml:"uiPrompt" json:"uiPrompt"` // 消息提示 @@ -36,6 +39,22 @@ type CaptchaAction struct { UIFooter string `yaml:"uiFooter" json:"uiFooter"` // 页脚 UIBody string `yaml:"uiBody" json:"uiBody"` // 内容轮廓 + OneClickUIIsOn bool `yaml:"oneClickUIIsOn" json:"oneClickUIIsOn"` // 是否使用自定义UI + OneClickUITitle string `yaml:"oneClickUITitle" json:"oneClickUITitle"` // 消息标题 + OneClickUIPrompt string `yaml:"oneClickUIPrompt" json:"oneClickUIPrompt"` // 消息提示 + OneClickUIShowRequestId bool `yaml:"oneClickUIShowRequestId" json:"oneClickUIShowRequestId"` // 是否显示请求ID + OneClickUICss string `yaml:"oneClickUICss" json:"oneClickUICss"` // CSS样式 + OneClickUIFooter string `yaml:"oneClickUIFooter" json:"oneClickUIFooter"` // 页脚 + OneClickUIBody string `yaml:"oneClickUIBody" json:"oneClickUIBody"` // 内容轮廓 + + SlideUIIsOn bool `yaml:"sliceUIIsOn" json:"sliceUIIsOn"` // 是否使用自定义UI + SlideUITitle string `yaml:"slideUITitle" json:"slideUITitle"` // 消息标题 + SlideUIPrompt string `yaml:"slideUIPrompt" json:"slideUIPrompt"` // 消息提示 + SlideUIShowRequestId bool `yaml:"SlideUIShowRequestId" json:"SlideUIShowRequestId"` // 是否显示请求ID + SlideUICss string `yaml:"slideUICss" json:"slideUICss"` // CSS样式 + SlideUIFooter string `yaml:"slideUIFooter" json:"slideUIFooter"` // 页脚 + SlideUIBody string `yaml:"slideUIBody" json:"slideUIBody"` // 内容轮廓 + Lang string `yaml:"lang" json:"lang"` // 语言,zh-CN, en-US ... AddToWhiteList bool `yaml:"addToWhiteList" json:"addToWhiteList"` // 是否加入到白名单 Scope string `yaml:"scope" json:"scope"` @@ -81,6 +100,10 @@ func (this *CaptchaAction) Init(waf *WAF) error { if len(this.Lang) == 0 { this.Lang = waf.DefaultCaptchaAction.Lang } + + if len(this.CaptchaType) == 0 { + this.CaptchaType = waf.DefaultCaptchaAction.CaptchaType + } } return nil diff --git a/internal/waf/captcha_validator.go b/internal/waf/captcha_validator.go index e327af4..7b86cef 100644 --- a/internal/waf/captcha_validator.go +++ b/internal/waf/captcha_validator.go @@ -3,11 +3,16 @@ package waf import ( "bytes" "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/fasttime" "github.com/TeaOSLab/EdgeNode/internal/waf/requests" "github.com/dchest/captcha" "github.com/iwind/TeaGo/logs" + "github.com/iwind/TeaGo/rands" "github.com/iwind/TeaGo/types" + stringutil "github.com/iwind/TeaGo/utils/string" "net/http" "strconv" "strings" @@ -23,7 +28,7 @@ func NewCaptchaValidator() *CaptchaValidator { return &CaptchaValidator{} } -func (this *CaptchaValidator) Run(req requests.Request, writer http.ResponseWriter) { +func (this *CaptchaValidator) Run(req requests.Request, writer http.ResponseWriter, defaultCaptchaType firewallconfigs.ServerCaptchaType) { var info = req.WAFRaw().URL.Query().Get("info") if len(info) == 0 { req.ProcessResponseHeaders(writer.Header(), http.StatusBadRequest) @@ -71,16 +76,39 @@ func (this *CaptchaValidator) Run(req requests.Request, writer http.ResponseWrit return } + var captchaType = captchaActionConfig.CaptchaType + if len(defaultCaptchaType) > 0 && defaultCaptchaType != firewallconfigs.ServerCaptchaTypeNone { + captchaType = defaultCaptchaType + } + if req.WAFRaw().Method == http.MethodPost && len(req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_ID")) > 0 { - this.validate(captchaActionConfig, policyId, groupId, setId, originURL, req, writer) + switch captchaType { + case firewallconfigs.CaptchaTypeOneClick: + this.validateOneClickForm(captchaActionConfig, policyId, groupId, setId, originURL, req, writer) + case firewallconfigs.CaptchaTypeSlide: + this.validateSlideForm(captchaActionConfig, policyId, groupId, setId, originURL, req, writer) + default: + this.validateVerifyCodeForm(captchaActionConfig, policyId, groupId, setId, originURL, req, writer) + } } else { // 增加计数 CaptchaIncreaseFails(req, captchaActionConfig, policyId, groupId, setId, CaptchaPageCodeShow) - this.show(captchaActionConfig, req, writer) + this.show(captchaActionConfig, req, writer, captchaType) } } -func (this *CaptchaValidator) show(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { +func (this *CaptchaValidator) show(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter, captchaType firewallconfigs.ServerCaptchaType) { + switch captchaType { + case firewallconfigs.CaptchaTypeOneClick: + this.showOneClickForm(actionConfig, req, writer) + case firewallconfigs.CaptchaTypeSlide: + this.showSlideForm(actionConfig, req, writer) + default: + this.showVerifyCodesForm(actionConfig, req, writer) + } +} + +func (this *CaptchaValidator) showVerifyCodesForm(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { // show captcha var countLetters = 6 if actionConfig.CountLetters > 0 && actionConfig.CountLetters <= 10 { @@ -168,7 +196,7 @@ func (this *CaptchaValidator) show(actionConfig *CaptchaAction, req requests.Req ` + `
-

` + msgPrompt + `

+

` + msgPrompt + `

@@ -176,7 +204,7 @@ func (this *CaptchaValidator) show(actionConfig *CaptchaAction, req requests.Req
` + requestIdBox + ` -` + msgFooter + `` +` + msgFooter // Body if actionConfig.UIIsOn { @@ -221,8 +249,7 @@ func (this *CaptchaValidator) show(actionConfig *CaptchaAction, req requests.Req _, _ = writer.Write([]byte(msgHTML)) } -func (this *CaptchaValidator) validate(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter) (allow bool) { - +func (this *CaptchaValidator) validateVerifyCodeForm(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter) (allow bool) { var captchaId = req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_ID") if len(captchaId) > 0 { var captchaCode = req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_CODE") @@ -255,3 +282,356 @@ func (this *CaptchaValidator) validate(actionConfig *CaptchaAction, policyId int return true } + +func (this *CaptchaValidator) showOneClickForm(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { + var lang = actionConfig.Lang + if len(lang) == 0 { + var acceptLanguage = req.WAFRaw().Header.Get("Accept-Language") + if len(acceptLanguage) > 0 { + langIndex := strings.Index(acceptLanguage, ",") + if langIndex > 0 { + lang = acceptLanguage[:langIndex] + } + } + } + if len(lang) == 0 { + lang = "en-US" + } + + var msgTitle string + var msgPrompt string + var msgRequestId string + + switch lang { + case "zh-CN": + msgTitle = "身份验证" + msgPrompt = "我不是机器人" + msgRequestId = "请求ID" + case "zh-TW": + msgTitle = "身份驗證" + msgPrompt = "我不是機器人" + msgRequestId = "請求ID" + default: + msgTitle = "Verify Yourself" + msgPrompt = "I'm not a robot" + msgRequestId = "Request ID" + } + + var msgCss = "" + var requestIdBox = `
` + msgRequestId + `: ` + req.Format("${requestId}") + `
` + var msgFooter = "" + + // 默认设置 + if actionConfig.OneClickUIIsOn { + if len(actionConfig.OneClickUIPrompt) > 0 { + msgPrompt = actionConfig.OneClickUIPrompt + } + if len(actionConfig.OneClickUITitle) > 0 { + msgTitle = actionConfig.OneClickUITitle + } + if len(actionConfig.OneClickUICss) > 0 { + msgCss = actionConfig.OneClickUICss + } + if !actionConfig.OneClickUIShowRequestId { + requestIdBox = "" + } + if len(actionConfig.OneClickUIFooter) > 0 { + msgFooter = actionConfig.OneClickUIFooter + } + } + + var captchaId = stringutil.Md5(req.WAFRemoteIP() + "@" + stringutil.Rand(32)) + var nonce = rands.Int64() + if !ttlcache.SharedInt64Cache.Write("WAF_CAPTCHA:"+captchaId, nonce, fasttime.Now().Unix()+600) { + return + } + + var body = `
+ +
+
+

` + msgPrompt + `

+
+
+` + requestIdBox + ` +` + msgFooter + + // Body + if actionConfig.OneClickUIIsOn { + if len(actionConfig.OneClickUIBody) > 0 { + var index = strings.Index(actionConfig.OneClickUIBody, "${body}") + if index < 0 { + body = actionConfig.OneClickUIBody + body + } else { + body = actionConfig.OneClickUIBody[:index] + body + actionConfig.OneClickUIBody[index+7:] // 7是"${body}"的长度 + } + } + } + + var msgHTML = ` + + + ` + msgTitle + ` + + + + + +` + body + ` + +` + + req.ProcessResponseHeaders(writer.Header(), http.StatusOK) + writer.Header().Set("Content-Type", "text/html; charset=utf-8") + writer.Header().Set("Content-Length", types.String(len(msgHTML))) + writer.WriteHeader(http.StatusOK) + _, _ = writer.Write([]byte(msgHTML)) +} + +func (this *CaptchaValidator) validateOneClickForm(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter) (allow bool) { + var captchaId = req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_ID") + var nonce = req.WAFRaw().FormValue("nonce") + if len(captchaId) > 0 { + var key = "WAF_CAPTCHA:" + captchaId + var cacheItem = ttlcache.SharedInt64Cache.Read(key) + ttlcache.SharedInt64Cache.Delete(key) + if cacheItem != nil { + // 清除计数 + CaptchaDeleteCacheKey(req) + + if cacheItem.Value == types.Int64(nonce) { + var life = CaptchaSeconds + if actionConfig.Life > 0 { + life = types.Int(actionConfig.Life) + } + + // 加入到白名单 + SharedIPWhiteList.RecordIP("set:"+strconv.FormatInt(setId, 10), actionConfig.Scope, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, false, groupId, setId, "") + + req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) + http.Redirect(writer, req.WAFRaw(), originURL, http.StatusSeeOther) + + return false + } + } else { + // 增加计数 + if !CaptchaIncreaseFails(req, actionConfig, policyId, groupId, setId, CaptchaPageCodeSubmit) { + return false + } + + req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) + http.Redirect(writer, req.WAFRaw(), req.WAFRaw().URL.String(), http.StatusSeeOther) + } + } + + return true +} + +func (this *CaptchaValidator) showSlideForm(actionConfig *CaptchaAction, req requests.Request, writer http.ResponseWriter) { + var lang = actionConfig.Lang + if len(lang) == 0 { + var acceptLanguage = req.WAFRaw().Header.Get("Accept-Language") + if len(acceptLanguage) > 0 { + langIndex := strings.Index(acceptLanguage, ",") + if langIndex > 0 { + lang = acceptLanguage[:langIndex] + } + } + } + if len(lang) == 0 { + lang = "en-US" + } + + var msgTitle string + var msgPrompt string + var msgRequestId string + + switch lang { + case "zh-CN": + msgTitle = "身份验证" + msgPrompt = "滑动上面方块到右侧解锁" + msgRequestId = "请求ID" + case "zh-TW": + msgTitle = "身份驗證" + msgPrompt = "滑動上面方塊到右側解鎖" + msgRequestId = "請求ID" + default: + msgTitle = "Verify Yourself" + msgPrompt = "Slide to Unlock" + msgRequestId = "Request ID" + } + + var msgCss = "" + var requestIdBox = `
` + msgRequestId + `: ` + req.Format("${requestId}") + `
` + var msgFooter = "" + + // 默认设置 + if actionConfig.OneClickUIIsOn { + if len(actionConfig.OneClickUIPrompt) > 0 { + msgPrompt = actionConfig.OneClickUIPrompt + } + if len(actionConfig.OneClickUITitle) > 0 { + msgTitle = actionConfig.OneClickUITitle + } + if len(actionConfig.OneClickUICss) > 0 { + msgCss = actionConfig.OneClickUICss + } + if !actionConfig.OneClickUIShowRequestId { + requestIdBox = "" + } + if len(actionConfig.OneClickUIFooter) > 0 { + msgFooter = actionConfig.OneClickUIFooter + } + } + + var captchaId = stringutil.Md5(req.WAFRemoteIP() + "@" + stringutil.Rand(32)) + var nonce = rands.Int64() + if !ttlcache.SharedInt64Cache.Write("WAF_CAPTCHA:"+captchaId, nonce, fasttime.Now().Unix()+600) { + return + } + + var body = `
+ +
+
+
+
+ +
+

` + msgPrompt + `

+
+` + requestIdBox + ` +` + msgFooter + + // Body + if actionConfig.OneClickUIIsOn { + if len(actionConfig.OneClickUIBody) > 0 { + var index = strings.Index(actionConfig.OneClickUIBody, "${body}") + if index < 0 { + body = actionConfig.OneClickUIBody + body + } else { + body = actionConfig.OneClickUIBody[:index] + body + actionConfig.OneClickUIBody[index+7:] // 7是"${body}"的长度 + } + } + } + + var msgHTML = ` + + + ` + msgTitle + ` + + + + + +` + body + ` + +` + + req.ProcessResponseHeaders(writer.Header(), http.StatusOK) + writer.Header().Set("Content-Type", "text/html; charset=utf-8") + writer.Header().Set("Content-Length", types.String(len(msgHTML))) + writer.WriteHeader(http.StatusOK) + _, _ = writer.Write([]byte(msgHTML)) +} + +func (this *CaptchaValidator) validateSlideForm(actionConfig *CaptchaAction, policyId int64, groupId int64, setId int64, originURL string, req requests.Request, writer http.ResponseWriter) (allow bool) { + var captchaId = req.WAFRaw().FormValue("GOEDGE_WAF_CAPTCHA_ID") + var nonce = req.WAFRaw().FormValue("nonce") + if len(captchaId) > 0 { + var key = "WAF_CAPTCHA:" + captchaId + var cacheItem = ttlcache.SharedInt64Cache.Read(key) + ttlcache.SharedInt64Cache.Delete(key) + if cacheItem != nil { + // 清除计数 + CaptchaDeleteCacheKey(req) + + if cacheItem.Value == types.Int64(nonce) { + var life = CaptchaSeconds + if actionConfig.Life > 0 { + life = types.Int(actionConfig.Life) + } + + // 加入到白名单 + SharedIPWhiteList.RecordIP("set:"+strconv.FormatInt(setId, 10), actionConfig.Scope, req.WAFServerId(), req.WAFRemoteIP(), time.Now().Unix()+int64(life), policyId, false, groupId, setId, "") + + req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) + http.Redirect(writer, req.WAFRaw(), originURL, http.StatusSeeOther) + + return false + } + } else { + // 增加计数 + if !CaptchaIncreaseFails(req, actionConfig, policyId, groupId, setId, CaptchaPageCodeSubmit) { + return false + } + + req.ProcessResponseHeaders(writer.Header(), http.StatusSeeOther) + http.Redirect(writer, req.WAFRaw(), req.WAFRaw().URL.String(), http.StatusSeeOther) + } + } + + return true +} diff --git a/internal/waf/rule_group.go b/internal/waf/rule_group.go index f21ae67..21cc235 100644 --- a/internal/waf/rule_group.go +++ b/internal/waf/rule_group.go @@ -74,7 +74,7 @@ func (this *RuleGroup) RemoveRuleSet(id int64) { this.RuleSets = result } -func (this *RuleGroup) MatchRequest(req requests.Request) (b bool, hasRequestBody bool, set *RuleSet, err error) { +func (this *RuleGroup) MatchRequest(req requests.Request) (b bool, hasRequestBody bool, resultSet *RuleSet, err error) { if !this.hasRuleSets { return } @@ -93,7 +93,7 @@ func (this *RuleGroup) MatchRequest(req requests.Request) (b bool, hasRequestBod return } -func (this *RuleGroup) MatchResponse(req requests.Request, resp *requests.Response) (b bool, hasRequestBody bool, set *RuleSet, err error) { +func (this *RuleGroup) MatchResponse(req requests.Request, resp *requests.Response) (b bool, hasRequestBody bool, resultSet *RuleSet, err error) { if !this.hasRuleSets { return } diff --git a/internal/waf/waf.go b/internal/waf/waf.go index 4559170..97433e4 100644 --- a/internal/waf/waf.go +++ b/internal/waf/waf.go @@ -242,7 +242,7 @@ func (this *WAF) MoveOutboundRuleGroup(fromIndex int, toIndex int) { this.Outbound = result } -func (this *WAF) MatchRequest(req requests.Request, writer http.ResponseWriter) (goNext bool, hasRequestBody bool, group *RuleGroup, sets *RuleSet, err error) { +func (this *WAF) MatchRequest(req requests.Request, writer http.ResponseWriter, defaultCaptchaType firewallconfigs.ServerCaptchaType) (goNext bool, hasRequestBody bool, resultGroup *RuleGroup, resultSet *RuleSet, err error) { if !this.hasInboundRules { return true, hasRequestBody, nil, nil, nil } @@ -251,7 +251,7 @@ func (this *WAF) MatchRequest(req requests.Request, writer http.ResponseWriter) var rawPath = req.WAFRaw().URL.Path if rawPath == CaptchaPath { req.DisableAccessLog() - captchaValidator.Run(req, writer) + captchaValidator.Run(req, writer, defaultCaptchaType) return } @@ -284,7 +284,7 @@ func (this *WAF) MatchRequest(req requests.Request, writer http.ResponseWriter) return true, hasRequestBody, nil, nil, nil } -func (this *WAF) MatchResponse(req requests.Request, rawResp *http.Response, writer http.ResponseWriter) (goNext bool, hasRequestBody bool, group *RuleGroup, set *RuleSet, err error) { +func (this *WAF) MatchResponse(req requests.Request, rawResp *http.Response, writer http.ResponseWriter) (goNext bool, hasRequestBody bool, resultGroup *RuleGroup, resultSet *RuleSet, err error) { if !this.hasOutboundRules { return true, hasRequestBody, nil, nil, nil } @@ -310,7 +310,7 @@ func (this *WAF) MatchResponse(req requests.Request, rawResp *http.Response, wri return true, hasRequestBody, nil, nil, nil } -// Save save to file path +// Save to file path func (this *WAF) Save(path string) error { if len(path) == 0 { return errors.New("path should not be empty") @@ -385,7 +385,7 @@ func (this *WAF) FindCheckpointInstance(prefix string) checkpoints.CheckpointInt return nil } -// Start start +// Start func (this *WAF) Start() { for _, checkpoint := range this.checkpointsMap { checkpoint.Start() diff --git a/internal/waf/waf_manager.go b/internal/waf/waf_manager.go index 59eac4c..644ab38 100644 --- a/internal/waf/waf_manager.go +++ b/internal/waf/waf_manager.go @@ -192,6 +192,7 @@ func (this *WAFManager) ConvertWAF(policy *firewallconfigs.HTTPFirewallPolicy) ( FailBlockTimeout: policy.CaptchaOptions.FailBlockTimeout, FailBlockScopeAll: policy.CaptchaOptions.FailBlockScopeAll, CountLetters: policy.CaptchaOptions.CountLetters, + CaptchaType: policy.CaptchaOptions.CaptchaType, UIIsOn: policy.CaptchaOptions.UIIsOn, UITitle: policy.CaptchaOptions.UITitle, UIPrompt: policy.CaptchaOptions.UIPrompt,