js_content
before proxy_pass is not executed and thus cannot filter malicious requests #799
Description
I want to mitigate a DOS attack by filtering incoming requests based on some criteria. If the criteria are met, then the request processing should continue (POST should be passed to proxy_pass
). If the criteria are not met, then I can return “200 Hello World!”, redirect to another page, or somehow avoid further handling. My current configuration does use proxy_pass
and works very good, except it cannot filter requests based on the desired criteria.
Is it possible to inspect the body of a HTTP request, and if it is OK, then to process the command in the Nginx configuration just after the NJS checks were done (thus handle the lines after js_content, like proxy_pass) ? Should the inspection be done in js_content
and what shall be executed in the script: to continue with the next directive in the nginx configuration, or to abort with “200 Hello World!”?
If this is not possible, how should I handle this use case? I had
location / {
proxy_pass http://127.0.0.2/cgi-bin/wa;
}
and this works very good. Now I do instead a.js
:
function filt(r) {
r.internalRedirect('/b')
}
export default {filt};
nginx config
location / {
js_content a.filt;
}
location /b {
internal;
proxy_pass http://127.0.0.2/cgi-bin/z;
}
If I call directly curl -D- http://127.0.0.2/cgi-bin/z?INDEX
there is no location header, but if I run the call over Nginx there is a 302 Location: https://server/b?INDEX
header. In the general case, the cgi-bin file will sometimes return and sometimes not return a location header. As /b is internal location, I could rewrite it with proxy_redirect http://127.0.0.2/cgi-bin/z /;
and then the reply to the client contains: 302 location: https://server/?INDEX
. This leads to a loop, as reply always has 302 location, the request goes again over "location /", then internalRediect('/b') and so on. Removing internal
does not help.
For me it seems impossible, when Nginx always includes Location header for proxy_pass after a (possibly internal) redirect within Nginx, to avoid sending 302 Location to the client. This locations cause the a.filt to be executed, in order to filter out the DOS attack, doing internal redirect,
If I put in the same location / { js_content …; and proxy_pass …; } then js_content is not executed (even if it contains a single .log() function) and there is no warnings or hints for this by nginx -t
. I have nginx 1.26.2 with njs 0.8.6.
- Please extent
js_content
to work together with and before proxy_pass, so that it can either redirect/rewrite the request to some URL, or continue with proxy_pass. - If in
location / { js_content …; and proxy_pass …; }
js_content is not supposed to do anything,nginx -t
should report it.
Activity