-
Story
-
Resolution: Unresolved
-
Major
-
None
-
None
-
None
-
False
-
-
False
-
-
Mitigate DDoS attacks with NGINX using the following techniques:
- Accept a limited number of incoming requests.
- Only allow each unique client IP address to make a login attempt every few seconds.
- Limit the number of connections for a single client.
- Assign a value for accepting the incoming requests similar to that of a typical user.
- Close slow connections that write data infrequently.
- These may be trying to keep connections open to reduce the server's capacity.
- Blacklist IP addresses used for attacks.
- Do not accept connections from these IP addresses.
- Whitelist IP addresses for specific sets of allowed users.
- Set caching parameters to enable caching to offload requests from the backend.
- Block requests that lead to attacks:
- Requests that limit connections to backend servers. - Requests used for range-based attacks. - Requests to handle high loads.
Please refer to the How-to section of this countermeasure for instructions on changing NGINX configurations.
Imported from SD Elements: https://redhat.sdelements.com/bunits/psse-secure-development/group-2-extended-functionality-offerings/openshift-pipelines/tasks/phase/deployment/37-T613/
How Tos:
NGINX: Limit the number of incoming requests
Assign a value for accepting the incoming requests, similar to that of a typical real user. Configure the number of requests allowed in a given time frame:
- The directive "limit_req_zone" is used to configure a shared memory zone called one to store the state of requests for the specified key. In this case, it's the client IP address ($binary_remote_addr).
- The directive "limit_req", which is in the location block (for /login.html), references the shared memory zone.
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m; server { ... location /login.html { limit_req zone=one; ... } }
NGINX: Limit the number of open connections
Limit the number of open connections for each client IP address:
- The limit_conn_zone directive configures a shared memory zone called addr which stores requests for the specified key, in this case the client IP address.
- The limit_conn directive, in the location block for /store, references the shared memory zone and sets a maximum of five connections from each client IP address.
limit_conn_zone $binary_remote_addr zone=addr:10m; server { ... location /store/ { limit_conn addr 5; ... } }
NGINX: Closing slow connections
Close slow connections that reduce server abilities. For example, configure NGINX to wait no more than 5 seconds between writes from the client for either headers or body as in the following example (the default values for each are 60 seconds):
server { client_body_timeout 5s;
client_header_timeout 5s; ... }
NGINX: Blacklisting
Configure NGINX/NGINX Plus to blacklist and deny IP addresses that are being used for attacks.
This example shows how to deny IP addresses in a range:
location / { deny 123.123.123.0/28; ... }
This example shows how to deny specific IP addresses:
location / { deny 123.123.123.3; deny 123.123.123.5; deny 123.123.123.7; ... }
NGINX: Whitelisting
Whitelist the range of IP addresses that are allowed to access a website or application.
Use the allow and deny directives together to specify the range of addresses that are allowed to access the site or application. The deny all directive is to deny all the addresses except for the ones specified by the allow directive:
location / { allow 192.168.1.0/24; deny all; ... }
NGINX: Enable caching
To avoid traffic spikes, enable caching. Here are some caching directives:
The proxy_cache_use_stale directive tells NGINX when it needs to fetch an update of a stale cached object.
The proxy_cache_key directive consists of embedded variables. Don't use the $query_string variable, because it is considered unsafe since an attacker can send random query strings and cause excessive caching.
NGINX: Block suspicious requests
Block requests that seem to be targeted, or have a value in the User-Agent header that does not look like normal traffic, or have a value in the Referrer header that seems to be associated with an attack.
This example shows how to deny all requests from /test.php :
location /test.php { deny all; }
This example shows how to block requests that can cause DDoS attacks. It blocks requests that have a user_agent header value of test or bar:
location / { if ($http_user_agent ~* test|bar) { return 403; } ... }
NGINX: Limit the connections to backend servers
NGINX can handle more simultaneous connections than the backend severs it is load balancing for. With NGINX Plus, you can limit the number of connections directed to each backend server, for example, to no more than 100 connections to each server:
upstream website { server 192.168.110.1:80 max_conns=100; server 192.168.110.2:80 max_conns=100; queue 10 timeout=30s; }
- The max_conns parameter specifies the maximum number of connections that NGINX Plus opens to a backend server.
- The queue directive limits the number of requests that are queued when all servers reach the maximum number of their connection limits.
- The timeout directive is the length of time in seconds that a request can remain in the queue.
NGINX: Dealing with range-based attack
HTTP requests with a large byte range in the Range header can cause the server to crash. To fix this issue, use the proxy_set_header directive to set the Range header to empty string " " which deletes the header before the HTTP request is forwarded to the Windows server named by the proxy_pass directive:
server { listen 80;
location / {
proxy_set_header Range "";
proxy_pass http://windowsserver:80;
}
NGINX: Handling high loads
DDoS can cause high traffic load. Here are some techniques for tuning NGINX for better performance:
- Tune your linux configuration and check the kernel log for error messages indicating that a setting is too low and adjust it accordingly.
- Change the setting for the backlog queue if you are getting an uneven level of performance. For example, specify the maximum number of connections that can be queued for acceptance by NGINX using net.core.somaxconn. Also the rate at which packets are buffered by the network can be increased using net.core.netdev_max_backlog to improve the performance on high bandwidth machines.
- Adjust the file descriptors setting for systems serving many connections. Use sys.fs.file_max to set the system-wide limit for file descriptors and nofile to set the user file descriptor limit in the /etc/security/limits.conf.
- Control the number of worker processes and the way they handle connections using the worker_processes*directive that indicates the number of NGINX worker processes. Set it to auto and set the maximum number of connections the worker process can handle simultaneously using the *worker_connection directive.
- Control keepalive connections using keepalive_requests which controls the number of requests a client can make over a single keepalive connection, and keepalive_timeout which controls how long an idle keepalive connection remains open.
- Enable access-log buffering by adding the buffer=size parameter to the access_log directive. This reduces the impact of logging on CPU and I/O cycles because the buffer collects a series of entries and writes them to a file in a single operation instead of performing a separate write operation for each log entry.
- Enable NGINX to use sendfile() system call to increase the speed of TCP data transfers. Sendfile() call copies data from one file descriptor to another. Include sendfile directive in the http context or a server or location context when configuring NGINX.
For more information, please refer to Tuning NGINX for Performance.
- links to