🌐

Apache(httpd)のリバースプロキシで大きなリクエストを制限する

2021/07/31に公開

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