1

i have a website running on node.js and express web server. i'm using nginx to run website on domain and also use ssl certificates. I searched google for how to protect server from ddos attacks using nginx and i found out that i should use limit_req attribute in my nginx conf file. but when i use this and i open website all other requests are failing, i mean i open the website and all external links are failing like css,js and image files, and in my console i see lot's of this error :

Failed to load resource: the server responded with a status of 503 (Service Temporarily Unavailable)

i know what the problem is, i'm limiting user requests to 10req/s and all external links and files are counting as a request and after 10 is reached all other reqs are failing, but i don't know how to handle it, i don't know if i should handle it from my express code or from nginx conf.

i know i should make all website request count once but i don't know how.

this is my nginx config :

    # HTTP - redirect all requests to HTTPS
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
    server {
            #listen 80 default_server;
            #listen [::]:80 default_server ipv6only=on;
            server_name www.example.com domain.com;
            return 301 https://example.com$request_uri;
    }
    map $sent_http_content_type $cacheable_types {
        ~image/  "max-age=864000";
        default       "";
    }
    server {
            listen 443;
            server_name www.examle.com;
            ssl on;
            # Use certificate and key provided by Let's Encrypt:
            ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
            ssl_session_timeout 5m;
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            ssl_prefer_server_ciphers on;
            ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
 location /{
          return 301 https://example.com$request_uri;
      }
server {
        listen 443;
        server_name example.com;
        ssl on;
        # Use certificate and key provided by Let's Encrypt:
        ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
        ssl_session_timeout 5m;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
      location /{
          limit_req zone=one;
          proxy_pass http://localhost:2000/;
      }
}

1 Answer 1

2

You're limiting everything being proxied to 10r/s. If you want to limit only pages you could define another location for css/js resources and not put a limit on them.

server {
  listen 443;

  location ~*  \.(jpg|jpeg|png|gif|css|js|ico)$ {
    limit_req zone=one;
    proxy_pass http://localhost:2000/;
  }

  location / {
    proxy_pass http://localhost:2000/;
  }
}

However, you probably shouldn't bother with it at all. A DDOS will overwhelm your Nginx server, taking everything offline anyway.

A better approach, if you really need DDOS protection, is to use a CDN like CloudFlare or CloudFront in front of your website. Ensure your IP isn't known, which can leak from other DNS records. CloudFront (AWS) has a lot of DDOS protection built in. CloudFlare paid plans will stand in front of a DDOS regardless of size. CloudFlare free will give it a go, but will give up if it gets too big.

1
  • Great :) Once you're happy with the answer please accept it. If you have follow up questions you can post a comment.
    – Tim
    Commented May 28, 2017 at 23:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .