-
Notifications
You must be signed in to change notification settings - Fork 282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ModSecurity header phase runs before nginx rate limiting #293
Comments
Hello @brandonpayton , Interesting question. The nginx phase to which REQUEST_HEADERS is attached has been that way since the inception of ModSecurity-nginx, so I would want to tread cautiously here. It would be interesting to understand more about the logic of the current nginx phase assignments and the potential tradeoffs of any change. For example, why is the ngx_http_limit_req_module running so late? The documentation states that realip assignments are already done in the NGX_HTTP_POST_READ_PHASE (which is before NGX_HTTP_REWRITE_PHASE), so why does it wait until the NGX_HTTP_PREACCESS_PHASE? And: Are there things we would lose by shifting REQUEST_HEADERS to be later than it currently runs? It's not clear to me that ngx_http_limit_req_module ought to run before any ModSecurity processing. Both that module and ModSecurity's REQUEST_HEADERS need to have received the request headers (the former presumably because it may need to adjust ip based on headers like X-Forwarded-For). But some ModSecurity rules might (again, conceptually) need less information, (e.g. the URI) to act. Nevertheless, it may be that REQUEST_HEADERS is currently running earlier than ideal, and it should be changed universally. Or maybe not. I agree that the workaround suggested in your first bullet point is not ideal. On the surface a quick find-and-replace would do the trick but: |
Hi @martinhsv, Thank you for your thoughtful response. I appreciate your time and am sorry for the delay in responding here.
Agreed.
Since the limit_conn and limit_req directives can be configured per nginx location, it seems important that actions in the REWRITE phase take place first to influence which location is ultimately the effective location for the request. Only then can
Not sure, but I agree this is a possibility.
It's possible ModSecurity users' preferences may vary in this case. For us, it is natural to prefer that ModSecurity only examine requests that aren't already rejected by nginx because, in those cases, we spend less CPU per rejected request. Would this be a place where it would be good to support another directive or a build-time option that will allow users to express their preference? Currently, we are simply running a patched build that moves the ModSecurity REQUEST_HEADERS and REQUEST_BODY phases to the nginx ACCESS phase (it turned out that PREACCESS was too early because ModSecurity was still running before the nginx limit-related modules). In addition, even with these custom changes, there are times where ModSecurity continues to run for limited requests so we currently address that with nginx maps and another patch (which I plan to submit soon) that allows ModSecurity-nginx to enabled/disabled dynamically per request. If ModSecurity-nginx would support a way to say "give nginx request limiting priority", then the relevant logic could also explicitly check relevant nginx request flags and skip processing when nginx-limited. What do you think? |
As a user, we would like to skip the cost of ModSecurity rule processing for requests that are rate-limited by nginx. Today, the ModSecurity header phase is processed before the ngx_http_limit_req_module considers rate limiting.
This is due to how each module hooks into the nginx request phases. The ngx_http_limit_req_module enforces rate limiting in the NGX_HTTP_PREACCESS_PHASE, but ModSecurity-nginx processes the ModSecurity header phase earlier, during the NGX_HTTP_REWRITE_PHASE.
Some workarounds are:
Even with these workarounds, it seems like it might make sense to be able to rate-limit prior to ModSec processing. Is this something we could consider changing or making configurable?
The text was updated successfully, but these errors were encountered: