DDoS attack on your web server can have the most unpleasant consequences for your infrastructure. Each attack should be considered as a separate case, and in the case of DDoS on your server, we recommend involving a qualified system administrator to solve this problem. In this article we will try to consider the most basic methods of preventing common attacks on web servers Apache/Nginx.

Apache

For this web server, the Ddos attack begins with the revelation of a large number of apache processes, your server may become unavailable due to exceeding the maximum number of processes, or due to shortage of RAM.

Let’s look at the sequence of actions and recommendations in case you encounter an attack.

     1.Diagnostics

If possible, you need to connect to the server via ssh. Using the ps and top commands, you can detect an increase in the number of httpd processes. In this case, you can stop apache or kill all httpd processes.

These commands will help determine the direction and status of all connections that are established on port 80 or on all ports:

netstat -na | grep ':80 '

netstat -na

Using the following commands, you can view the number of httpd processes and the number of connections on port 80. If a connection is detected that exceeds the average, you can  review that it is a DoS / DDoS attack.

ps aux | grep -с httpd

netstat -na | grep -с ":80 "

The Centos 7 operating system does not have the netstat command in the  image, but you can install netstat with the command:

yum instal net-tools

You can also use an alternative method, the ss command, which during output displays all connections to the web server:

ss -o '( dport = :http or sport = :http )'

With the following command, you can display the number of connections from one IP address to the web server and sort the list in ascending order:

ss -o '( dport = :http or sport = :http )' | awk '{print $6}' | cut -d : -f 1 | grep -v 'Address' | sort | uniq -c | sort -n 

With a high probability, http flood can be determined by side signs. With the following command, you can cause every 2 seconds to display a list of apache logs, and if there is a big increase with the size of the access file, you can determine that the attack goes to a particular site:

watch 'ls -laS /var/www/httpd-logs/'

The following commands can help detect DoS / DDoS using tcpdump.

tcpdump will write the first 200 packets that are waiting for connections on port 80 to the check.log file:

tcpdump -n port 80 -c 200 -w check.log

With this command you can parse the log file and sort it by ip and number of connections:

tcpdump -nr check.log | awk '{print $3}' |grep -oE '[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}' |sort |uniq -c |sort -rn

     2.Actions to stop the attack

First of all, you need to determine which site the attack is on.

Apache has a mod_status module, mod_status allows real-time monitoring of server load.

  • Connecting mod_status in Apache 2.4

In apache2.4, you need to edit the file /etc/apache2/mods-enabled/status.conf. Change section:

<Location /server-status>

               SetHandler server-status

               Require local

               #Require ip ----

</Location>

on

<Location /server-status>

               SetHandler server-status

</Location>

Check that the string is uncommented:

ExtendedStatus On

Restart apache:

service httpd restart
  • Mod_status connection in Apache 2.2

In apache2.2, edit /etc/httpd/conf/httpd.conf

Uncomment the lines, and if not, add them to the file:

#LoadModule status_module libexec/apache22/mod_status.so

#Include etc/apache22/extra/httpd-info.conf

Change section:

<Location /server-status>

               SetHandler server-status

               Order deny,allow

               Deny from all

               Allow from .examplesite.com

</Location>

on

<Location /server-status>

               SetHandler server-status

</Location>

Check that the string is uncommented:

ExtendedStatus On

Restart apache:

service httpd restart
  • Using server-status

And now at

http: //server-ip-address/server-status statistics of requests to it are available. 

For example, the attack occurs with empty GET / requests to the examplesite.com website and you need to disable it. You can do this by creating a .htaccess file in the root directory of the domain and writing it to the contents of the file:

Deny from All

Now, when accessing the site, 403 Forbidden error will be generated and the load on other sites will be significantly reduced.

     3.Additional settings

  • iptables 

Using the following command, you can filter the 80th port for a specific IP:

iptables -A INPUT -p tcp --src xxx.xxx.xxx.xxx --dport 80 -j DROP

Using the following combination, you can create a chain where all connections will be redirected to the 80th port of the server. All illegitimate IPs will be added to this chain:

iptables -N chainname

iptables -A INPUT -p tcp --dport 80 -j chainname

while true; do tail -10000 /var/www/httpd-logs/site.com.access.log | sort | cut -f 1 -d " " | uniq -c | awk '($1>50){print $2}' | xargs -tn 1 iptables -A dos -p tcp -j DROP --dport 80 -s; sleep 30; done
iptables -F INPUT — clear the table INPUT
iptables -F chainname— clear the table chainname
iptables -X chainname— delete the table chainname

Setting up using iptables can lead to duplicate rules in the chain. This can be avoided by using the ipset module.

  • ipset 
ipset -N chainname iphash

iptables -A INPUT -p tcp -m tcp --dport 80 -m set --set chainname src -j DROP

while true; do tail -10000 /var/www/httpd-logs/site.com.access.log | sort | cut -f 1 -d " " | uniq -c | awk '($1>50){print $2}' | xargs -tl -I _ ipset -A chainname _;sleep 30; done
  • ICMP-flood 

In this case, close icmp:

iptables -A INPUT -p icmp -j DROP --icmp-type 8

You can also limit the maximum number of half-open connections from one IP to a specific port, you must first install the desired module:

iptables -I INPUT -p tcp --syn --dport 80 -m iplimit --iplimit-above 10 -j DROP

The following combination can limit the maximum number of connections from one IP to a specific port:

/sbin/iptables  -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 3 -j REJECT
  • Apache server optimization

First of all, it is necessary to adjust additional parameters in the server settings:

/etc/httpd/conf/httpd.conf

<IfModule mpm_itk_module>

   StartServers                    1

   MinSpareServers            1

   MaxSpareServers           1

   MaxClients                      150

   MaxRequestsPerChild  100

</IfModule>

You should to change the MaxClients value, which means the maximum number of processes, given the number of processes that will not lead to a server crash due to a shortage of RAM.Keep in mind that each Apache process takes 4-8 MB of memory, so the following command can find out how much one apache / httpd process takes up memory on your server and determine MaxClients from this value:

top -d 1 | grep -E 'http|apache' | awk '{a+=$7}END{print a/(1024*NR) " Mb"}'

You should also adjust and set the following parameters so that outdated apache processes can stop their work faster:

Timeout                            60

MaxKeepAliveRequests 50
  • Configuring nginx as front-end for apache
server {

       listen       80;

       server_name  examplesite.com www.examplesite.com;

 deny all;

WWW domain must be disabled by configuring nginx in the required virtual host. This will force nginx to issue 403 Forbidden rather than redirecting requests to the apache web server.

Nginx

     1.First of all, it is necessary to limit the speed of requests so that Nginx accepts incoming requests at the speed necessary for real users:

limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

server {

# ... 

     location /index.html {

         limit_req zone=one;

     }

}

limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;

server {

# ... 

     location /example.html {

         limit_req zone=one;

     }

}

This configuration example uses the following settings:

  • limit_req_zone – the directive configures the called shared memory zone to store the status of requests for the specified key, in this case the client IP address ($ binary_remote_addr).
  • limit_req – The directive in the location block for /index.html refers to the shared memory zone.

     2.Limit the number of connections that can be opened by one client IP

limit_conn_zone $binary_remote_addr zone=addr:10m;

server {     

# ...     

    location /products/ {         

        limit_conn addr 10;        

    } 

}

This configuration example uses the following settings:

  • limit_conn_zone— The directive sets up a shared memory zone named addr to /products requests for the specified key, in this case (as in the previous example) the client IP address, $ binary_remote_addr.
  • limit_conn— The directive in the location block for / products refers to the shared memory zone and establishes a maximum of 10 connections from each client IP address.

     3.Close slow connections

You can close connections that write data too infrequently, which may be an attempt to keep connections open and thus reduce the server’s ability to accept new connections.

client_header_timeout           30s;

client_body_timeout             30s;

By default, this parameter is 60 seconds.

 

These are currently all common measures to prevent attacks on web servers. If you encounter an attack on your web server, please save the logs for further investigation of the causes of vulnerabilities in your service.