Re: My variable seems to never expire...
Mikaël Pirio <[email protected]>
| Newsgroups | gmane.comp.apache.mod-security.user |
|---|---|
| Message-ID | <CAG1WCxiYGx+kTMBbJnHWgkf=bf8dtZEevz+LcSmUwq8fUeQ=-w@mail.gmail.com> |
@christian yes, the initial workaround about `expirevar` is from @theseion (
https://github.com/SpiderLabs/ModSecurity/issues/1803#issuecomment-474884652).
In my conf, I've added a rule (see rule: 5, the second part) to init my
session.api_req_counter__expire_timestamp variable once.
If my recipe can help somebody, here the modsec and nginx (to add X-Limit-*
headers) configuration:
ModSec conf :
#
# Rate-limiting rules identified by PHPSESSIONID on /api requests
#
# Variables:
# SESSION:API_REQ_COUNTER counter of API requests
# TX:API_REQ_COUNTER_MAX max number of API requests which can pass
in %{tx.api_req_counter_timeout} seconds
# TX:API_REQ_COUNTER_TIMEOUT period in seconds a blocked PHP session id
will be blocked on API requests
#
# As a precondition for these rules, please set the following 2 variables:
# - TX:API_REQ_COUNTER_MAX
# - TX:API_REQ_COUNTER_TIMEOUT
#
# Define TX:API_REQ_COUNTER_MAX and TX_REQ_COUNTER_TIMEOUT
SecAction \
"id:1,\
phase:1,\
nolog,\
pass,\
t:none,\
setvar:tx.api_req_counter_timeout=60,\
setvar:tx.api_req_counter_max=100"
#
# Define SESSION
#
SecRule REQUEST_COOKIES:PHPSESSID "!^$" \
"id:2,\
phase:1,\
pass,\
nolog,\
setsid:%{REQUEST_COOKIES.PHPSESSID}"
###################################################
# TEMPORARY WORKAROUND FOR not working `expirevar`
###################################################
# Expire variables
SecRule &SESSION:API_REQ_COUNTER__EXPIRE_TIMESTAMP "@eq 1" \
"id:3,\
phase:1,\
pass,\
t:none,\
nolog,\
chain"
SecRule SESSION:API_REQ_COUNTER__EXPIRE_TIMESTAMP "@lt %{TIME_EPOCH}" \
"setvar:'!session.api_req_counter',\
setvar:'!session.api_req_counter__expire_timestamp'"
###################################################
###################################################
#
# If it's an API request:
# 1. Identify API requests
# 2. update counter
# 3. if session:api_req_counter__expire_timestamp is not define, define it
#
SecRule REQUEST_URI "@beginsWith /api/" \
"id:4,\
phase:1,\
pass,\
nolog,\
setvar:'tx.is_api_req=1',\
setvar:'session.api_req_counter=+1',\
expirevar:'session.api_req_counter=%{tx.api_req_counter_timeout}',\
chain"
SecRule &SESSION:API_REQ_COUNTER__EXPIRE_TIMESTAMP "@eq 0" \
"setvar:'session.api_req_counter__expire_timestamp=%{TIME_EPOCH}',\
setvar:'session.api_req_counter__expire_timestamp=+%{tx.api_req_counter_timeout}'"
#
# If max counter is reached AND it's an API request, deny it
#
SecRule SESSION:API_REQ_COUNTER "@gt %{tx.api_req_counter_max}" \
"id:5,\
deny,\
status:429,\
log,\
msg:'RATELIMITED',\
chain"
SecRule TX:IS_API_REQ "@eq 1"
SecRule TX:IS_API_REQ "@eq 1" \
"id:6,\
phase:1,\
pass,\
nolog,\
setenv:'ratelimit_limit=%{tx.api_req_counter_max}',\
setenv:'ratelimit_counter=%{session.api_req_counter}',\
setenv:'ratelimit_reset=%{session.api_req_counter__expire_timestamp}'"
Nginx Conf (i use the module lua
https://openresty.org/en/lua-nginx-module.html) :
...
location /api/ {
set_by_lua $ratelimit_limit 'return os.getenv("ratelimit_limit")';
set_by_lua $ratelimit_remaining 'return os.getenv("ratelimit_limit")
- os.getenv("ratelimit_counter")';
set_by_lua $ratelimit_reset 'return os.getenv("ratelimit_reset")';
add_header X-RateLimit-Limit "$ratelimit_limit";
add_header X-RateLimit-Remaining "$ratelimit_remaining";
add_header X-RateLimit-Reset "$ratelimit_reset";
...
}
...
_______________________________________________
mod-security-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mod-security-users
Commercial ModSecurity Rules and Support from Trustwave's SpiderLabs:
http://www.modsecurity.org/projects/commercial/rules/
http://www.modsecurity.org/projects/commercial/support/