2026年11月14日

2026年11月14日

Limit Concurrent Connections per IP in Apache with mod_limitipconn

This article is a localized edition of the Japanese original. Read the Japanese original

mod_limitipconn is a module that caps the number of simultaneous connections a single IP address can open to Apache. It is well suited to download pages for large files, where download managers may open dozens of parallel connections and tie up bandwidth and worker slots.

It is not a standard module bundled with Apache but a third-party module distributed by David Jao. As of November 2026 the latest version is 0.25, and the download page says it has been tested on Apache 2.4 and 2.2. We could not find a package in the official Debian 13 repositories or in EPEL 9, so this article builds it from source. The steps were tested on Debian 13 (Apache 2.4).

As the author's own documentation states, this module is not designed to prevent DoS attacks. It does nothing against attacks coming from many IP addresses, so if your goal is attack mitigation, also read "Choosing between this and other approaches" later in the article.

How it works and prerequisites

mod_limitipconn looks at Apache's scoreboard (the list of which client each worker is currently serving) and counts the in-progress connections from the same IP address. Requests over the limit receive 503 Service Unavailable.

Because client information has to be recorded in the scoreboard, two things are required:

  • mod_status is loaded
  • ExtendedStatus On is in effect (in Apache 2.4, loading mod_status turns it On by default, but writing it in the configuration to make the intent explicit is the safer choice)

On Debian/Ubuntu, mod_status is enabled by default. Check that status_module appears in the output of sudo apache2ctl -M | grep status.

Building and installing

The build needs apxs, which comes with Apache's development package. On Debian/Ubuntu, install it like this:

sudo apt update
sudo apt install apache2-dev build-essential bzip2 curl

On RHEL-family systems, httpd-devel and gcc provide apxs and the compiler.

Download the source from the distribution page, extract it, and build and install it with apxs.

cd /usr/local/src
sudo curl -LO https://dominia.org/djao/limit/mod_limitipconn-0.25.tar.bz2
sudo tar xjf mod_limitipconn-0.25.tar.bz2
cd mod_limitipconn-0.25
sudo apxs -c -i -a -n limitipconn mod_limitipconn.c

-i copies the module into Apache's module directory, and -a adds the configuration that loads it. On Debian/Ubuntu this creates /etc/apache2/mods-available/limitipconn.load and enables it right away. Confirm that it is loaded with:

sudo apache2ctl -M | grep limitipconn

If you see limitipconn_module (shared), you are ready. After upgrading Apache, you may need to rebuild the module using the same steps.

Setting the concurrent connection limit

The module provides three directives:

Directive Meaning
MaxConnPerIP number Maximum simultaneous connections from one IP address. 0 means no limit
NoIPLimit MIME-type… Do not count the listed MIME types (e.g. image/*)
OnlyIPLimit MIME-type… Count only the listed MIME types

On Debian/Ubuntu, create the configuration file in conf-available. The following example limits each IP to 2 simultaneous connections under /downloads only, and does not count images.

sudo nano /etc/apache2/conf-available/limitipconn.conf
ExtendedStatus On

<IfModule mod_limitipconn.c>
    <Location /downloads>
        MaxConnPerIP 2
        NoIPLimit image/*
    </Location>
</IfModule>

To limit only video and audio, write something like OnlyIPLimit audio/mpeg video instead of NoIPLimit.

Enable the configuration, check the syntax, then restart.

sudo a2enconf limitipconn
sudo apache2ctl configtest
sudo systemctl restart apache2

Server-wide limits and per-location limits

Writing something like MaxConnPerIP 10 outside <Location> sets a server-wide limit. Note that the server-wide limit and each <Location> limit are calculated separately. For example, if the server-wide limit is 10 and /downloads is 3 with NoIPLimit image/* set for /downloads, the 11th simultaneous image request still hits the server-wide limit. If you want per-location settings to override, put the global limit inside <Location /> and nest the individual <Location> blocks inside it.

Pages that load many images, CSS and JavaScript files make browsers open several connections at once. A small site-wide limit turns normal browsing into 503 errors, so restrict the limit to download paths or exclude static files with NoIPLimit.

Testing that it works

Put a fairly large test file in place and run four bandwidth-limited curl requests at the same time. With a limit of 2, the third and later requests return 503.

sudo mkdir -p /var/www/html/downloads
sudo head -c 5000000 /dev/zero | sudo tee /var/www/html/downloads/big.bin > /dev/null

for i in 1 2 3 4; do
  curl -s -o /dev/null --limit-rate 200k -w "req$i %{http_code}\n" http://127.0.0.1/downloads/big.bin &
  sleep 0.3
done
wait

Sample output (requests 3 and 4 return 503 immediately; requests 1 and 2 print 200 after their downloads finish in about 25 seconds):

req3 503
req4 503
req1 200
req2 200

Delete the test file when you are done. In production, watch the number of 503s in the access log to make sure the limit isn't too strict.

sudo rm /var/www/html/downloads/big.bin
sudo awk '$9 == 503' /var/log/apache2/access.log | tail

Operational notes

  • Logging denied requests: Requests denied by the limit have the environment variable LIMITIP set to 1. Writing something like CustomLog ${APACHE_LOG_DIR}/access.log combined env=!LIMITIP keeps the denied requests out of the access log.
  • Behind a proxy or load balancer: By default, every client is counted as the proxy's IP address, so everyone shares the same limit. Use mod_remoteip, which ships with Apache 2.4, to restore the original IP from X-Forwarded-For. List only trusted proxy addresses in RemoteIPTrustedProxy.
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 10.0.0.10
  • Users sharing one IP: In offices, schools and on mobile networks, many users share a single IP address. Set the limit too low and legitimate users get 503s.
  • No per-IP limits: The same limit applies to every IP address.
  • Combining with mod_cache: When used with modules that respond from a quick handler, such as mod_cache, per-location settings such as <Location> have no effect; only server-wide settings work.

Choosing between this and other approaches

Goal Tool
Limit simultaneous connections (parallel downloads) from one IP mod_limitipconn
Limit transfer speed per connection The standard mod_ratelimit (How to limit bandwidth in Apache)
Temporarily block IPs that send a burst of requests mod_evasive (DDoS mitigation with mod_evasive)
Control connections and requests in finer detail mod_qos (How to configure mod_qos)

Apache modules alone can't absorb attacks coming from many IP addresses. Combine them with a CDN, a WAF or an upstream firewall.

Summary

  • mod_limitipconn is a third-party module; build and enable it with apxs -c -i -a -n limitipconn mod_limitipconn.c
  • It requires mod_status and ExtendedStatus On
  • Set the cap with MaxConnPerIP, and narrow what is counted by MIME type with NoIPLimit/OnlyIPLimit
  • Requests over the limit get 503. Behind a proxy, use mod_remoteip so the real client IP is used
  • For attack mitigation, combine it with mod_evasive, mod_qos, a CDN or a WAF

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲