servewaf always answers rproxy well within its time limit (closes #182)
check / check (push) Successful in 6m23s
check / check (push) Successful in 6m23s
A question waits on GeoJS at most 800ms, the new default of SWWAF_LOOKUP_TIMEOUT. It does not wait at all when the checks will refuse it whatever GeoJS answers. Just before the Core Rule Set, servewaf refuses more than 50 cookies or 100 header fields with 431. Shared default changed: SWWAF_LOOKUP_TIMEOUT also applies to smallwebwaf with no command. Judgement call: SWWAF_REPUTATION_TIMEOUT stays 2s, since no request waits on the DNS blocklists or AbuseIPDB. Model: opus-5-5
This commit is contained in:
+28
-12
@@ -222,12 +222,12 @@ func requestHeaders(r *http.Request, names []string) map[string]string {
|
||||
// is known, before anything reaches the app, and before its body is read,
|
||||
// but for the part the Core Rule Set reads. It returns nil to let the
|
||||
// request through. The checks of checkClient come first, answered with
|
||||
// SWWAF_BAN_RESPONSE, or 403 for a block rule or the Core Rule Set, and
|
||||
// then the size limit, so that a request the rate limits count is counted
|
||||
// even when it is refused for its size. In observe mode a request
|
||||
// checkClient refuses goes on to the size limit like any other. A size or
|
||||
// time limit the Core Rule Set's reading of the body meets ends the
|
||||
// request in either mode. ctx is the request's own context.
|
||||
// SWWAF_BAN_RESPONSE, 403 for a block rule or the Core Rule Set, or 431 for
|
||||
// servewaf's header limits, and then the size limit, so that a request the
|
||||
// rate limits count is counted even when it is refused for its size. In
|
||||
// observe mode a request checkClient refuses goes on to the size limit like
|
||||
// any other. A size or time limit the Core Rule Set's reading of the body
|
||||
// meets ends the request in either mode. ctx is the request's own context.
|
||||
func (rq *request) check(ctx context.Context) *refusal {
|
||||
action := rq.checkClient(ctx)
|
||||
|
||||
@@ -243,6 +243,8 @@ func (rq *request) check(ctx context.Context) *refusal {
|
||||
rq.line.WouldAction = action
|
||||
case action == requestlog.ActionRuleBlocked || action == requestlog.ActionWAFBlocked:
|
||||
return &refusal{status: http.StatusForbidden, action: action}
|
||||
case action == requestlog.ActionTooLarge:
|
||||
return &refusal{status: http.StatusRequestHeaderFieldsTooLarge, action: action}
|
||||
default:
|
||||
return rq.banResponse(action)
|
||||
}
|
||||
@@ -271,9 +273,10 @@ func (rq *request) check(ctx context.Context) *refusal {
|
||||
// rate limits, unless the client is in SWWAF_RATE_LIMIT_EXEMPT_NETS or the
|
||||
// request's path is exempt under SWWAF_RATE_LIMIT_EXEMPT_PATHS, so that
|
||||
// every other request is counted, each of them by the client's limit
|
||||
// percentages, then SWWAF_TRAP_PATHS, then the rule files, and last the
|
||||
// Core Rule Set. A request exempt from the rate limits is exempt from the
|
||||
// byte limits too. ctx is the request's own context.
|
||||
// percentages, then SWWAF_TRAP_PATHS, then the rule files, then, in
|
||||
// servewaf, the header limits, and last the Core Rule Set. A request exempt
|
||||
// from the rate limits is exempt from the byte limits too. ctx is the
|
||||
// request's own context.
|
||||
func (rq *request) checkClient(ctx context.Context) string {
|
||||
cfg := rq.h.config
|
||||
if isInside(rq.client, cfg.AllowNets) {
|
||||
@@ -290,7 +293,7 @@ func (rq *request) checkClient(ctx context.Context) string {
|
||||
return requestlog.ActionBanned
|
||||
}
|
||||
|
||||
rq.lookUp(ctx)
|
||||
rq.lookUp(ctx, now)
|
||||
|
||||
// The lookup can wait for GeoJS, so the checks after it read the time
|
||||
// again: a request counted at the time it arrived could be counted
|
||||
@@ -314,8 +317,7 @@ func (rq *request) checkClient(ctx context.Context) string {
|
||||
return requestlog.ActionDenied
|
||||
}
|
||||
|
||||
rq.counted = !isInside(rq.client, cfg.RateLimitExemptNets) &&
|
||||
!pathExempt(rq.in, cfg.RateLimitExemptPaths)
|
||||
rq.counted = rq.countedByRateLimits()
|
||||
if rq.counted {
|
||||
rq.limitPercent, rq.bytesPercent = rq.limitPercentages()
|
||||
rq.line.LimitPercent, rq.line.LimitPercentSetting = rq.limitPercent.logged()
|
||||
@@ -335,9 +337,23 @@ func (rq *request) checkClient(ctx context.Context) string {
|
||||
return action
|
||||
}
|
||||
|
||||
if rq.overHeaderLimits() {
|
||||
return requestlog.ActionTooLarge
|
||||
}
|
||||
|
||||
return rq.checkCoreRuleSet()
|
||||
}
|
||||
|
||||
// countedByRateLimits reports whether the rate limits count the request: its
|
||||
// client is not in SWWAF_RATE_LIMIT_EXEMPT_NETS, and its path is not exempt
|
||||
// under SWWAF_RATE_LIMIT_EXEMPT_PATHS.
|
||||
func (rq *request) countedByRateLimits() bool {
|
||||
cfg := rq.h.config
|
||||
|
||||
return !isInside(rq.client, cfg.RateLimitExemptNets) &&
|
||||
!pathExempt(rq.in, cfg.RateLimitExemptPaths)
|
||||
}
|
||||
|
||||
// pathExempt reports whether r is exempt under prefixes,
|
||||
// SWWAF_RATE_LIMIT_EXEMPT_PATHS or SWWAF_WAF_EXEMPT_PATHS: whether its
|
||||
// path as sent, the path the app receives, not percent-decoded, starts
|
||||
|
||||
Reference in New Issue
Block a user