mod_qos cannot only be used to implement QoS by controlling your Apache
web server's traffic but may also help you to protect
your web site against denial of service (DoS) attacks. The two features
of mod_qos which are particularly suitable to help you in doing this,
are the possibility to measure the bandwidth used for a TCP connection
(and the possibility to enforce that the requirements concerning the
minimum bandwidth is fulfilled) and the existence of event counters
per client's IP addresses (allowing you to limit the number of events
a client is allowed cause on your web site).
Note: Multiple users may share an IP addresses (IP address is not
unique per user) when using an intermediate proxy server or source NAT.
This is especially true for B2B applications.
This documentation shall give you an idea on how you could use mod_qos
within your Apache web server to defense against the following DoS attacks:
- Low-bandwidth DoS attacks
The attacker tries to keep many TCP connections to your web server open,
only sending partiality request data periodically (just enough not triggering
any inactivity timeouts). The target is to occupy all available connections
(running threads of your Apache server) so that nobody else can connect.
- HTTP GET/POST flood DoS attacks
The attacker sends a huge amount of HTTP requests to your web server without
awaiting the server's response. This requires only little traffic for the
attacker but may occupy your server's threads and consumes computing resources
(CPU, memory). Some attackers scan your web site prior an attack measuring
the duration it takes to answer the request in order to find out which one are
the "most expensive" HTTP requests (consuming most time while being processed
by your web server).
The following is a step-by-step checklist about potential configuration
options you want to apply to improve your Apache server's DoS resistance.
It shall give you an idea about which parameter you might want to set, to
build an additional protective layer against DoS attacks.
Note: If you are under an attack, it's no a question whether someone
is blocked or not, but who. mod_qos helps your web server to make
the right decision. Your job is to set the thresholds matching your
infrastructure. You might either decide to have these rules active
all the time or just as part ot your incident response plan.
Hardware is inexpensive. Today's CPUs offers many cores allowing you to run
many threads in parallel and prices for memory are as low as never before.
So please allow your Apache server to serve many requests / TCP connections in
parallel by setting a "high" value for its
parameter (and the corresponding
values). I'm going to use 896 in the following examples. This is not
an absolute value. Its probably not even a particular "high" value if you
are fighting against a low-bandwidth DoS attack. Maybe it is fine
for a quad-core Intel CPU serving several thousand concurrent users
(assuming you are running the Apache server as your web tier only and
not using more than half of the possible connections in the normal
case - the upper half is only a reserve for exceptional situations, better
if you have even more reserves as over-provisioning may be really helpful)
but you might choose a different value suitable for your environment
(note that each tread requires about 1 to 2 MB of memory). Just adapt
all other values accordingly.
Other important Apache base settings concern timeouts.
One is the
directive defining the idle timeout while waiting for data on the network
socket, the other directive is
KeepAliveTimeout , telling the Apache
server for how long to wait for a subsequent request before closing an idle
connection. Keep-Alive is an important feature to accelerate your web server
but you should disable it if the server runs out of free connections.
Disabling Keep-Alive will give more users a chance to connect to your
server and send a HTTP request if your server becomes too busy and don't
has any free slots anymore. mod_qos's
QS_SrvMaxConnClose directive allows you to disable Keep-Alive
in such a situation automatically.
# maximum number of active TCP connections is limited to 896 (limited
# by the available memory, adjust the settings according to the used
# idle timeout (while the server is waiting for TCP packets):
# keep alive (enabled, but only until 80% of all connections are busy):
Connections per IP
There is no reason to allow a single IP address to open an unlimited number of
TCP connections. The
directive can be used to limit the connections a single IP is allowed to open.
# don't allow more than 30 TCP connections per client source address
# if the server has 500 or more open connections:
QS_SrvMaxConnPerIP 30 500
Minimum Data Rate
The definition of a minimum upload/download throughput a client must generate
(the bytes sent/received by the client per seconds) is a very important protection
mechanism against low-bandwidth DoS attacks.
can be used to implement this rule.
QS_SrvMinDataRate <bytes per second> <max bytes per second> <connections>
It offers three parameters. The first defines the
minimum data rate a client must achieve when this limitation becomes active
and the second parameter defines the throughput a client must achive when
the server reaches its
MaxClients setting. The third parameter
defines the number of busy connections to enable this restriction.
# minimum request/response data reate if the server has 500 or more
# open connections:
QS_SrvMinDataRate 120 1500 500
You might also want to have a look at the Apache module
(available since Apache 2.2.15) which may be used to set various timeouts for
receiving the request headers and the request body from the client.
A very effective means of protection is the possibility to block client
IP addresses automatically for a certain period if they violate a rule
multiple times respectively if they cause errors many times.
directive can be used to do this. It defines how often a "block event" (the Apache
process environment variable
may occur during a defined period of time. This enhances the effect of the above limitations.
Incoming TCP connections are rejected if a client IP address reaches this threshold until
the limitation expires.
QS_SetEnvIfStatus is one of mod_qos's
directive which may be used to define an event which must not occur too frequently.
These limitations do not only increase the DoS defense efficiency.
- 400 405 406 408 413 414 500
Status codes which may be caused by clients sending invalid or incomplete requests.
Slow clients violating the
QS_SrvMinDataRate rule (see above).
Clients opening too many TCP connections, see
Clients closing/aborting the TCP connection before reading the the HTTP response (
BrokenConnection in particular can be used to detect clients performing a HTTP GET/POST flood DoS attack.
The following example blocks clients if they cause more than 20 events within 5 minutes.
This is just an example of events you might want to limit. Feel free to add
more or to ignore some events.
If you want to prevent from SSL DoS attacks as well (many SSL handshakes
initiated by the client), you might also want to block clients opening TCP
connections not sending any HTTP data. These clients may be marked using the
Requests per IP
Rules, limiting a clients number of requests to a resource, may be configured
directive. This provides an event counter per IP address and you may specify
how often a client is allowed to
trigger this event within a defined period of
time. Such a limitation might defense HTTP GET/POST flood DoS attacks,
especially if you know which requests are the most expensive ones / which
URLs provide the greatest risk of being attacked.
You may use any request attributes to distinguish between "expensive"
(resources your server takes long to process) and "inexpensive" (like static
resource files which can be send to the client immediately). You can also
define different attribues and configure more than one counter per IP
(each counter is idenitfied by the specified name).
One attribute could be the request's URL and you may use the
directive to detect them and to increment the counter.
You can use the
-pu) to analyze log data (or just use any other log data
management tool). You should not only search your Apache server's log about
"slow requests" but also check how many requests are issued by a single
IP address to decide what limitations you want to configure (which URLs
and how often).
For the following example, lets assume that requests to static resources
(jpg,gif,css,...) are cheap (quickly processed by your server) and other
requests expensive (takes long to be processed) while the most expensive
URL path is
/generateReport.php. Therefore, you won't need
to set any penalty when accessing a static resource. Other resources
are marked by "1" (allowing a client to access them 20 times within two minutes)
while requests to the "most expensive" resource
/generateReport.php are burden by a
penalty of "2" (may be accessed only 10 times within two minutes).
It is also possible that you enable this limitation only if the server
reaches a predefined number of busy connections (no limitation if it is not
You can achieve this by deleting the event variable (
in this example) if the server has less connections.
variable tells you the number of busy TCP connections and the
allows you to set or unset variables. The following example unset the
SlowRequest variable as long as the server has less than 499
Clients which violates this request violation may be blocked for an even
longer period of time. This is implemented by a second counter
Your site might hosts multiple web applications of different importance. An
unimportant application can be prone to a HTTP GET/POST flood DoS attack.
To minimize the influence of such an application on others, you can limit the
allocable resources using the
directive. This directive allows you to limit the number of concurrent
requests to certain URLs and thus limit with how many simultaneous request
one or multiple attacker can try to slowdown your server.
Country Specific Rules
Some web sites may have content that is only of regional interest, e.g., a
site whose content is written in German has probably most visitors from
countries where German is an officially spoken language. This allows you
to prefer clients connecting from one of those country only in the case
your server runs out of free TCP connections.
# loads the GEO IP database and allows only client connections from
# Germany, Austria or Switzerland if the number of busy connections
# server reaches 700:
QS_ClientGeoCountryPriv DE,AT,CH 700
The geolocation database file is a CSV file containing the following
fields: the double quoted integer number
defining the first IPv4 address in a netblock, the double quoted integer number
defining the last IPv4 address in a netblock, and the double quoted ISO 3166
Example (extract) of a database file:
Prefer Known Clients
mod_qos may prefer "known" client IP addresses in the case that too
many clients access the server. "Known" clients are those
which have once been identified by the application by setting
the corresponding HTTP response header. Such identification
may happen at successful user login. Connections from clients
which are not known to mod_qos (never marked by the corresponding
response header) are denied if the server runs on low TCP connection
Unknown clients may get blocked. mod_qos prefers clients
which communicate with the server instantaneously and fast,
and denies access to slow clients sending data irregularly,
violating other rules or loading different content types than
the majority of the other clients do.
The directive to enable this is called
using this feature, you should define how to detect the "good" clients
directive (e.g., let your application add a special response header if a user
successfully authenticates). Alternatively, you can use the
QS_VipIPUser directive if you are using
an Apache authentication module such as mod_auth_basic to mark IP addresses
from which someone has successfully been authenticated.
It is also recommended to configure a static value for the
directive in order to avoid distortions of the reference values during an attack.
# mark an IP address from which someone has authenticated
# specify the threshold (busy connections) when mod_qos starts to prefer some clients:
# define what content type "normal" clients do access (this is just an example!):
# html css/js images other 304
QS_ClientContentTypes 40 15 150 10 40
Note: Clients marked as VIP
can pass the restrictions defined by the
default. You can use
if you want to change this.
There are two reasons why you would like to limit some request attributes
when fighting against DoS attacks. Having request line or header limitations
may lay open clients exceeding these limits exposing attackers trying
to hide themslef. The other one is that you don't want allow a client to
send too many data.
Three Apache core
and one mod_qos directives may be used to set limitations.
# limits request line, header and body:
Note: These parameters needs to be adapted to fit your web server's usage.
Especially the request body size limitation.
You might want to configure this limitation depending
on the request's content type or increase the values for some URLs.
Kernel and iptables
You should also ensure to have the kernel parameters of your server adjusted
to meet the requirements of a web server (many ports, short close timeouts).
# example settings
net.core.somaxconn = 32000
net.core.netdev_max_backlog = 32000
net.ipv4.ip_local_port_range = 9999 61000
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_slow_start_after_idle = 0
Your firewall in front or your Apache web server also performs important
tasks related to DoS prevention - but the configuration of your FW is out of
the scope of this article. However, iptables can also be fun...
# limits the number of new connections (active after reaching the burst limit only):
iptables -A INPUT -p tcp --dport 80,443 -m limit \
--state NEW --limit 60/minute --limit-burst 250 -j ACCEPT
# limits the number of established/concurrent connections:
iptables -A INPUT -m state --state RELATED,ESTABLISHED \
-m limit --limit 50/second --limit-burst 50 -j ACCEPT
# limits the connections from a single source IP to 100:
iptables -A INPUT -p tcp --syn --dport 80,443 -m connlimit \
--connlimit-above 100 -j REJECT
You may want to inform other systems about client IP addresses which shall
be blocked, e.g., to synchronize multiple Apache instances (using the
web console), to configure
iptables rules, or to inform your ISP about clients which shall no
longer be routed to your site. Watch your server's
logs! The directives mentioned on this
page may write event messages using the
following identifiers when blocking clients.