What is mod_vlimit. “limit the number of simultaneous connections”

Preface

This is the distribution page for the Apache module mod_vlimit.

mod_vlimit allows “Apache HTTP Server” administrators to limit the number of  simultaneous connections(exec cgi php)  from the same IP address or all to any files.

If client accessese are over the limit connections, mod_vlimit return 503 error message to the client.

[warning]
mod_vlimit is for Apache 2.x.
If you use “VirtuaHost”, This is OK.
mod_vlimit is approved Apache module by “Apache Module Registry“.
[/warning]

 

Downloads

mod_vlimit is approved Apaceh module by “Apache Module Registry“.

You can search or browse on “Apache Module Registry“, if you’d like to get the information for mod_vlimit.

[note]

[/note]

Install

On systems that support Apache dynamic shared objects (DSOs), the recommend installation procedure using apxs is:

apxs -i -c mod_vlimit.c

and configured httpd.conf:

LoadModule vlimit_module modules/mod_vlimit.so

 

How to use

limit the number of simultaneous connections per IP address

  • set limits to 5 simultaneous connections(cgi php exec) per IP address to the directory(/www/hoge/fuga/)
<Directory "/www/hoge/fuga/">
    VlimitIP 5
</Directory>
  • set limits to 3 simultaneous connections(cgi php exec) per IP address to files(test.cgi)
<Files "test.cgi">
    VlimitIP 3
</Files>
  • set limits to 4 simultaneous connections(cgi php exec) per IP address to some files(a.cgi b.cgi c.cgi d.cgi …)
<FilesMatch "^*¥.cgi$">
    VlimitIP 4
</FilesMatch>

is equal to:

<Files "a.cgi">
    VlimitIP 4
</Files>
<Files "b.cgi">
    VlimitIP 4
</Files>
<Files "c.cgi">
    VlimitIP 4
</Files>
<Files "d.cgi">
    VlimitIP 4
</Files>
.
.
.
.
  • set limits to 1 simultaneous connections(cgi php exec) per IP address to the symlink file(/usr/local/test-cgi/test.cgi -> /var/www/html/test.cgi)
<Files "test.cgi">
    VlimitIP 1 /var/www/html/test.cgi
</Files>

 

limit the number of simultaneous connections per File or Directory

  • set limits to 7 simultaneous connections(exec cgi php) to the directory(/www/hoge/fuga/)
<Directory "/www/hoge/fuga/">
    VlimitFile 7
</Directory>
  • set limits to 2 simultaneous connections(exec cgi php) to files(test.cgi)
<Files "test.cgi">
    VlimitFile 2
</Files>
  • set limits to 5 simultaneous connections(exec cgi php exec) to some files(a.cgi b.cgi c.cgi d.cgi …)
<FilesMatch "^*¥.cgi$">
    VlimitFile 4
</FilesMatch>

is equal to:

<Files "a.cgi">
    VlimitFile 4
</Files>
<Files "b.cgi">
    VlimitFile 4
</Files>
<Files "c.cgi">
    VlimitFile 4
</Files>
<Files "d.cgi">
    VlimitFile 4
</Files>
.
.
.
.
  • set limits to 1 simultaneous connections(exec cgi php) to the symlink file(/usr/local/test-cgi/test.cgi -> /var/www/html/test.cgi)
<Files "test.cgi">
    VlimitFile 1 /var/www/html/test.cgi
</Files>

 

logging

mod_vlimit can output some logs. Basically, mod_vlimit don’t output logs but if you “touch” the flag file associated with the log you want, mod_vlimit will output the log.

  • Check debug log
touch /tmp/VLIMIT_DEBUG
less /var/log/syslog
  • Stop debug log
rm /tmp/VLIMIT_DEBUG
  • Check m0dule access log
touch /tmp/VLIMIT_LOG
less /tmp/mod_vlimit.log
  • Stop module access log
rm /tmp/VLIMIT_LOG
  • module access log sample
[Fri Mar 11 11:54:48 2011] pid=[28734] name=[172.16.71.46] client=[172.16.71.46] RESULT:  OK INC ip_count: 1/5 file_count: 0/0 file=[/var/www/html/32.php]
[Fri Mar 11 11:54:48 2011] pid=[28734] name=[172.16.71.46] client=[172.16.71.46] RESULT: END DEC ip_count: 0/5 file_count: 0/0 file=[/var/www/html/32.php]
[Fri Mar 11 11:54:48 2011] pid=[28648] name=[172.16.71.46] client=[172.16.71.46] RESULT:  OK INC ip_count: 1/5 file_count: 0/0 file=[/var/www/html/33.php]
[Fri Mar 11 11:54:48 2011] pid=[28580] name=[172.16.71.46] client=[172.16.71.46] RESULT:  OK INC ip_count: 2/5 file_count: 0/0 file=[/var/www/html/33.php]
[Fri Mar 11 11:54:48 2011] pid=[28402] name=[172.16.71.46] client=[172.16.71.46] RESULT:  OK INC ip_count: 3/5 file_count: 0/0 file=[/var/www/html/33.php]
[Fri Mar 11 11:54:48 2011] pid=[28532] name=[172.16.71.46] client=[172.16.71.46] RESULT:  OK INC ip_count: 4/5 file_count: 0/0 file=[/var/www/html/33.php]
[Fri Mar 11 11:54:48 2011] pid=[28648] name=[172.16.71.46] client=[172.16.71.46] RESULT: END DEC ip_count: 3/5 file_count: 0/0 file=[/var/www/html/33.php]
[Fri Mar 11 11:54:48 2011] pid=[28776] name=[172.16.71.46] client=[172.16.71.46] RESULT:  OK INC ip_count: 4/5 file_count: 0/0 file=[/var/www/html/33.php]
[Fri Mar 11 11:54:48 2011] pid=[28653] name=[172.16.71.46] client=[172.16.71.46] RESULT:  OK INC ip_count: 5/5 file_count: 0/0 file=[/var/www/html/34.php]
[Fri Mar 11 11:54:48 2011] pid=[28764] name=[172.16.71.46] client=[172.16.71.46] RESULT: 503 INC ip_count: 6/5 file_count: 0/0 file=[/var/www/html/34.php]
[Fri Mar 11 11:54:48 2011] pid=[28544] name=[172.16.71.46] client=[172.16.71.46] RESULT: 503 INC ip_count: 7/5 file_count: 0/0 file=[/var/www/html/34.php]
[Fri Mar 11 11:54:48 2011] pid=[28557] name=[172.16.71.46] client=[172.16.71.46] RESULT: 503 INC ip_count: 8/5 file_count: 0/0 file=[/var/www/html/34.php]
[Fri Mar 11 11:54:48 2011] pid=[28778] name=[172.16.71.46] client=[172.16.71.46] RESULT: 503 INC ip_count: 9/5 file_count: 0/0 file=[/var/www/html/34.php]
[Fri Mar 11 11:54:48 2011] pid=[28580] name=[172.16.71.46] client=[172.16.71.46] RESULT: END DEC ip_count: 8/5 file_count: 0/0 file=[/var/www/html/33.php]
  • Check current counter list per files
touch /tmp/VLIMIT_FILE_STAT
cat /tmp/vlimit_file_stat.list
    • vlimit_file_stat.list sample
[Fri Mar 11 11:51:15 2011] slot=[2] filename=[20.php] counter=[10]
[Fri Mar 11 11:51:15 2011] slot=[3] filename=[12.php] counter=[7]
[Fri Mar 11 11:51:15 2011] slot=[4] filename=[23.php] counter=[10]
[Fri Mar 11 11:51:15 2011] slot=[5] filename=[24.php] counter=[10]
[Fri Mar 11 11:51:15 2011] slot=[6] filename=[4.php] counter=[2]
[Fri Mar 11 11:51:15 2011] slot=[7] filename=[25.php] counter=[10]
[Fri Mar 11 11:51:15 2011] slot=[8] filename=[2.php] counter=[7]
[Fri Mar 11 11:51:15 2011] slot=[9] filename=[1.php] counter=[5]
[Fri Mar 11 11:51:15 2011] slot=[10] filename=[3.php] counter=[2]
[Fri Mar 11 11:51:15 2011] slot=[11] filename=[5.php] counter=[2]
  • Re-create FILE counter lists
rm /tmp/vlimit_file_stat.list
cat /tmp/vlimit_file_stat.list
  • Check current counter list per ip
touch /tmp/VLIMIT_IP_STAT
cat /tmp/vlimit_ip_stat.list
    • vlimit_ip_stat.list sample
[Fri Mar 11 11:54:29 2011] slot=[0] ipaddress=[172.16.71.46] counter=[6]
[Fri Mar 11 11:54:29 2011] slot=[1] ipaddress=[172.16.71.47] counter=[5]
[Fri Mar 11 11:54:29 2011] slot=[2] ipaddress=[172.16.71.48] counter=[7]
[Fri Mar 11 11:54:29 2011] slot=[3] ipaddress=[172.16.71.40] counter=[3]
[Fri Mar 11 11:54:29 2011] slot=[4] ipaddress=[172.16.71.49] counter=[1]
  • Re-create  IP counter lists
rm /tmp/vlimit_ip_stat.list
cat /tmp/vlimit_ip_stat.list

「What is mod_vlimit. “limit the number of simultaneous connections”」への22件のフィードバック

  1. はじめまして。
    有用なモジュールの開発&公開に感謝します。

    さっそくモジュールを導入させていただきました。
    特定ディレクトリ以下で制限を設けようと思い、以下の設定にしました。

    DirectoryIndex index.html

    VlimitFile 3

    上記設定で起動した場合、http://example.com/hoge/でアクセスすると4回目以降はすべて503になってしまいます。

    mod_vlimit.log(※抜粋)
    RESULT: OK INC ip_count: 0/0 file_count: 1/3 file=[/usr/***/hoge/]
    RESULT: END DEC ip_count: 0/0 file_count: 0/3 file=[/usr/***/hoge/index.html]
    RESULT: OK INC ip_count: 0/0 file_count: 2/3 file=[/usr/***/hoge/]
    RESULT: END DEC ip_count: 0/0 file_count: 0/3 file=[/usr/***/hoge/index.html]
    RESULT: OK INC ip_count: 0/0 file_count: 3/3 file=[/usr/***/hoge/]
    RESULT: END DEC ip_count: 0/0 file_count: 0/3 file=[/usr/***/hoge/index.html]
    RESULT: OK INC ip_count: 0/0 file_count: 4/3 file=[/usr/***/hoge/]

    カウンターのインクリメントとデクリメントの際のr->filenameの不一致が原因かと思われるのですが、なにかよい回避方法はないでしょうか?

  2. >> tamaさん
    モジュールを試して頂きありがとうございます。今、現象を確認しました。
    作っていた段階では、全てのファイルに制限をかけるというのを想定していなくて、Directiveで基本的に囲む、例えば、FilesやFilesMatch等の使用を想定していました。一旦それで試していただけますか。

    この事象の対応も近いうちにやってみます。

  3. 早速のお返事ありがとうございます。

    前回のコメントでは消えてしまっていますが、VlimitFile 3はDirectoryで囲んでいます。
    WPにタグとして解釈されて削除されてしまったのでしょうか?
    <Directory “/hoge/”>
    VlimitFile 3
    </Directory>

    上記設定だと以下のようになってしまいます
    http://example.com/hoge/だと4回目以降すべて503
    http://example.com/hoge/index.htmlだと正常

    <Filesmatch \.html>
    VlimitFile 3
    </Filesmatch>

    http://example.com/hoge/だと無制限
    http://example.com/hoge/index.htmlだと正常動作

    アクセスされるURLが[/]で終わっている場合で、DirectoryIndexが適用される場合に制限をかける方法を模索してみます。

    ちなみに以下のような使用方法では完璧に動作しています。
    <Filesmatch fuga.cgi>
    VlimitFile 3
    </Filesmatch>

  4. >>tamaさん
    僕も試してみたところ、Apacheの内部で/にアクセスあった場合のrewrite処理のところで、/にアクセスがあって、さらに実際にDirectoryIndexでアクセスされたファイルは何なのかを処理するルーチンが必要ですね・・・インクリメント時の実装不足のようです。確か、1.3系ではそこまで見てやらなくてもよかったと思うんですが、2系の特有の内部の処理のようです。

    すみません。ちょっと改修してみます。

  5. >>tamaさん
    DirectoryIndexのバグをFixしてみました。
    やった内容としては、今まではInitialRequests以外はRedirect対策でスキップするようにしていましたが、それをやめてDirectoryIndexのように、/にアクセスしたときに探索されるファイルをきちんとチェックして、ファイルやディレクトリが存在するか、また、それはファイルであるか、を見るようにしました。ログにも探索時のインクリメントデクリメントは出力しないようにしています。

    https://github.com/matsumoto-r/release-code/blob/master/APACHE-MODULE/mod_vlimit/mod_vlimit.c

    詳細はコミットログを見て頂くとわかると思います。

    なお、デバッグログにはそのあたりのログも出力するようにしていますので、ご確認ください。

  6. 迅速な対応ありがとうございます。
    早速導入してみました。

    <Directory “hoge”>
    VlimitFile 1
    </Directory>

    ▼http://example.com/hoge/の場合

    mod_vlmit.log
    RESULT: OK INC ip_count: 0/0 file_count: 1/1 file=[/usr/***/hoge/index.html]
    RESULT: 503 INC ip_count: 0/0 file_count: 2/1 file=[/usr/***/hoge/index.html]
    RESULT: END DEC ip_count: 0/0 file_count: 1/1 file=[/usr/***/hoge/index.html]
    RESULT: END DEC ip_count: 0/0 file_count: 0/1 file=[/usr/***/hoge/index.html]
    ※同時2接続した際のログ

    ただし、apacheのログではステータスコードが2アクセスとも200となり制限が効いていないようです。

    ▼http://example.com/hoge/index.htmlの場合

    mod_vlmit.log
    RESULT: OK INC ip_count: 0/0 file_count: 1/1 file=[/usr/***/hoge/index.html]
    RESULT: 503 INC ip_count: 0/0 file_count: 2/1 file=[/usr/***/hoge/index.html]
    RESULT: END DEC ip_count: 0/0 file_count: 1/1 file=[/usr/***/hoge/index.html]–ここまで1PV目のログ
    RESULT: 503 INC ip_count: 0/0 file_count: 2/1 file=[/usr/***/hoge/index.html]
    RESULT: END DEC ip_count: 0/0 file_count: 1/1 file=[/usr/***/hoge/index.html]

    2PV目以降はすべて503となります。
    1PV目でインクリメントが2回行われている模様です。

    なお、上記検証はコンパイルエラー回避のため、#include を追加して試しております。

    とりあえず、ご報告まで。

  7. 素晴らしいモジュールをありがとうございます。

    早速ですが、モジュールを使わせて頂きましたところ、
    mod_rewriteなどで、ファイルが存在しないパスへアクセスがあると
    ファイルのカウントが下がらないようです。

    例えば「nVlimitFile 5」とした場合で、
    .htaccess などで以下のような設定をしたとします。

    RewriteEngine on
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ view.php?file=$1 [L,QSA]

    この場合、
    例えば[ /test.html ]へアクセスすると[ /view.php?file=test.html ]と解釈されるのですが、
    実際には[ /test.html ]が存在しないとファイルのカウントが上がり続け、5回目以降は全て503エラーが返ってしまうようです。

    OS : Scientific Linux 6
    Apache 2.2.15

  8. >>tamaさん
    上記と同様の設定を行ったところ、hoge/index.htmlに対するアクセスにおいて、http://…./hoge/index.html  でアクセスすると正常にインクリメント・デクリメント、及び503エラーは機能していました。
    しかし、hoge/に対して、http://…../hoge/ でアクセスすると、同時接続数のカウンター上限までインクリメントされたのち、再度http://…../hoge/ にアクセスすると、503は返るのですが、Aache内部でのDirectoryIndexの処理上、index.htmlで503になった後は、残りのファイルの探索を継続する(index.rbとかindex.php5等)ので、最終的にそれらのファイルが見つからなかった場合はindex.htmlとしてではなくhoge/としてデクリメントしてしまいます。
    503ではなかった場合、index.htmlで探索を停止するので、正常にインクリメントとデクリメントがされる状況です。
    これは、少し工夫が必要そうなので、考えてみます。少し時間を下さい。
    現状の使い方としては、ファイル単位(FilesやFilesMacth等)の設定を使っていただければと思います。正規表現等で十分にチューニングができると思います。

    >>taniさん
    事象に関しては解決したようで良かったです。ただし、上記のようなバグがありますので、hoge/に対する設定等にはご注意下さい。

  9. >>tamaさん >>taniさん
    おまたせしました。

    Directory設定とmod_rewriteのバグを修正しました。
    これまでは、実際のカウントチェックをap_hook_access_checkerで呼び出していましたが、hookのタイミングとして適切ではなく、DirectoryIndexのファイル探索やredirectの処理が異なるタイミングで生じていたため、カウンターに齟齬が出ていたようです。

    ですので、色々Apacheのソースを見なおした結果、ap_hook_fixupsのhookのタイミング(リクエストの最終調整のタイミング)でカウンターチェックを行うようにしました。

    これによって、DirectoryIndexやredirect後の情報が構造体に入力された後の処理になるので、カウンターに齟齬が派生しないようになったと思われます。

    ご迷惑をお掛けしました。この修正によって、新たなバグが生じている可能性もありますので、また何かあったら教えていただきたいと思っています。

  10. 早速のご対応ありがとうございます。

    DirectoryIndex index.html

    <Directory “/hoge/”>
    VlimitFile 3
    </Directory>

    上記設定で
    /hoge/ /hoge/index.htmlどちらも正しく制限がかかることを確認しました。

    また

    <FilesMatch \.html>
    VlimitFile 3
    </FilesMatch>

    こちらも正しく動作しました。

    ただ、そのままコンパイルしようとするとエラーになってしまったので、とりあえず#include <sys/stat.h>を追加しました。
    現ソースを見る限りstat構造体は未使用のようなので、変数宣言部分を注釈にした方がよかったかも。。。
    環境はFreeBSD+Apache2.2.22です。

    これからいろいろなケースでチェックしたいと思います。
    とりあえずご報告まで。

    迅速なご対応に感謝します。

  11. >>tamaさん
    すみません。最新版のソースはいらない変数とかコメントを気づく限り消して、更新しておきました。
    FreeBSDでの動作情報はあまり無いですので、またフィードバック頂けたらとてもうれしいです。

  12. はじめまして。
    こんないいものを見つけたので、使ってみようと思っています。
    ご質問があるのですが、
    同じIP、または同じファイルで制限出来る事は確認できたのですが、
    「すべてのIPを対象」に接続数を制限する事はできないのでしょうか。

    VlimitIPは、同じIPからの接続数を設定するとの事で、
    Filesmatch を使って、「(cgi|htm?l|php)」と指定し、「VlimitFile 1」を設定したのですが、
    同じファイルへのアクセス時は、503が発生したのですが、他のファイルへアクセスすると200が帰ってきました。

    恐れ入りますが、よろしくお願いいたします。

  13. 何度もすみません。
    <Directory /home/…../>
    VlimitFile 1
    </Directory>
    でも、同じファイルへのアクセスは制限されたのですが、他のファイルと制限されませんでした。
    よろしくお願いいたします。

  14. >> けんたさん
    はじめまして、返事が遅くなってすみません!

    正規表現で指定したときは、それぞれのファイル名がカウンター値を持つ仕様になっています。
    全てのマッチするファイルに一つのカウンターを持つチューニングは、なんかあったときに全くアクセスできない状況になるのが怖いのであえてやっていません(だったと思います)。

    もし、具体的な設定例と実現したいチューニングがあって、それがmod_vlimitでできないのであれば、実装を検討しますので、よろしければgithubにissueを挙げて頂くことは可能でしょうか?

    https://github.com/matsumoto-r/mod_vlimit

コメントは受け付けていません。