Apache(httpd)のリバースプロキシで大きなリクエストを制限する
Apache(httpd)のmod_proxyを使ったリバースプロキシで大きなリクエストを制限したかったのですが、LimitRequestBody
では制限できませんでした。
下記の情報などによると、プロキシの場合にはLimitRequestBody
が効かないようです。
上記でも言及されているmod_securityだと制限できるようなので、mod_securityを試してみます。
検証環境
CentOSの公式yumリポジトリを使って入れたApache(httpd)に対してmod_securityを設定します。
- CentOS 7.9
- Apache(httpd) 2.4.6
mod_security のインストール
CentOSの公式yumリポジトリにあるものをそのままインストールします。
sudo yum install -y mod_security
インストールされたバージョンは2.9.2でした。
$ rpm -aq | grep mod_security
mod_security-2.9.2-1.el7.x86_64
mod_security の設定
mod_securityをインストールすると、/etc/httpd/conf.d/mod_security.conf
に設定ファイルが作成されます。
mod_securityは、WAF(Web Application Firewall)で、デフォルトで様々な設定(SQLインジェクションや、XSSなどを使った攻撃を検知)が有効になっています。
今回は、リクエストサイズのチェックに絞った設定とするため、 /etc/httpd/conf.d/mod_security.conf
の内容を全部消して、下記に置き換えます。
(例として50MBを上限として設定)
sudo vi /etc/httpd/conf.d/mod_security.conf
# mod_securityを有効化
SecRuleEngine On
# リクエストボディのチェックを有効化
SecRequestBodyAccess On
# リクエストボディの上限を設定(バイト)
SecRequestBodyLimit 52428800
# 上限を超えた時の動作(Rejectは破棄)
SecRequestBodyLimitAction Reject
# リクエストボディの上限を設定(バイト)
# application/x-www-form-urlencoded の場合は、こちらが利用される
SecRequestBodyNoFilesLimit 52428800
Apacheを再起動して設定を反映します。
sudo systemctl restart httpd
動作確認
制限を超えるようなリクエストを送ってみて、制限にひっかかることを確認します。
fallocate
でアップロードするためのファイルを作成します。制限値に引っかかるサイズにします。
fallocate -l 52428800 50mb.dat
curl
コマンドでアップロードします。
curl -X POST -F upfile=@50mb.dat http://localhost/ --include
制限にひっかかり、 413 Request Entity Too Large が返却されました。
HTTP/1.1 413 Request Entity Too Large
Date: Sat, 31 Jul 2021 13:41:46 GMT
Server: Apache/2.4.6 (CentOS)
Content-Length: 329
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>413 Request Entity Too Large</title>
</head><body>
<h1>Request Entity Too Large</h1>
The requested resource<br />/<br />
does not allow request data with POST requests, or the amount of data provided in
the request exceeds the capacity limit.
</body></html>
/var/log/httpd/error_log
にも、nod_securityの制限にひっかかったことを表すログが出力されます。
[Sat Jul 31 13:45:22.866136 2021] [:error] [pid 13049] [client ::1:49630] [client ::1] ModSecurity: Request body (Content-Length) is larger than the configured limit (52428800). [hostname "localhost"] [uri "/"] [unique_id "YQVT8udR0RL5fZ3NmNjprAAAAAM"]
おわりに
mod_securityをインストールすることで、リバースプロキシでもリクエストサイズを制限することが出来ました。
ちなみに、Nginxだとリバースプロキシでもclient_max_body_size
で設定できるので、Apacheだとちょっと手間だな、、と感じました。
今回この方法を調査したのは、Rocket.ChatでリバースプロキシとしてApacheを利用している環境で、ファイルアップロードの制限をしたいためでした。
Rocket.Chat自体でもファイルアップロードのサイズ制限が出来るのですが、リクエスト自体は受け付けたうえでのチェックとなるので、Nodeでアップロードサイズに応じたメモリを一時的ではありますが利用することとなります。
そのため、間違って大きなファイルをアップロードされた場合の保険として、Rocket.Chatが受け付ける前にプロキシとなるApacheで弾くような仕組みを入れることにしました。
Discussion