Skip to content
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

js_content before proxy_pass is not executed and thus cannot filter malicious requests #799

Open
dilyanpalauzov opened this issue Oct 13, 2024 · 2 comments
Labels

Comments

@dilyanpalauzov
Copy link

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.
@xeioex
Copy link
Contributor

xeioex commented Oct 15, 2024

Hi @dilyanpalauzov,

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.

yes, both js_content and proxy_pass install a content handler for request processing for a given location. nginx allows you to have only have a single content handler for a given location.

For DOS protection, have you considered limit_req and limit_conn modules? It is a recommended and effective approach to mitigate DOS attacks.

@dilyanpalauzov
Copy link
Author

Hello,

in my case I do not want to limit somehow the number of requests, I avoid them 100%. limit_req and limit_conn will not help here. What I did at the end was to modify the code of the webserver, which receives the requests from nginx and executes cgi-bin/z.

It would be better, if Nginx/njs had this option to limit traffic.

Greetings
// Dilyan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants