スマートフォンからの画像を自分のPCに転用する形で用いているNextcloud。

アップロードが途中で失敗したり、特定の条件下で接続が切れたりすることがあります。Apacheビルトインのmod_reqtimeout設定を最適化し、サーバーの安定性と利便性を両立させるためのチューニングを行いました。

環境

  • Nextcloud 32
  • Apache 2.4
  • PHP-FPM8.3
  • Ubuntu 24.04

そもそもmod_reqtimeoutとは?

Slowloris(スローロリス)攻撃への対策

このモジュールがビルトインされたのは、Slowlorisという、非常に低コストで強力な攻撃手法への対抗があります。

通常のDoS攻撃は大量の通信を送りますが、Slowlorisは逆に「極めてゆっくり」通信します。

  1. サーバーに接続を開始する。
  2. リクエスト(ヘッダーやボディ)を、タイムアウトにならないギリギリの遅さで、1バイトずつ小出しに送る。
  3. サーバー側は「まだデータが来るはずだ」と判断し、その接続(スレッドやプロセス)を維持し続ける。

結果 サーバーの同時接続数の上限が攻撃者の「待ち」状態で埋まってしまい、正規のユーザーがアクセスできなくなります。

mod_reqtimeout は、この「嫌がらせ」を許さないための防衛線です。

サーバーリソースの適正管理

Apacheサーバーが1つの接続を維持するには、メモリやCPUリソースを消費します。
もしタイムアウト設定がない、あるいは極端に長い場合、以下のような問題が発生します。

  • ゾンビ接続の蓄積: ネットワークが切れたのにクローズ処理が終わっていない接続が残り続ける。
  • リソースの浪費: 応答の遅いクライアント(意図的か否かに関わらず)のために、サーバーの貴重な作業枠をいつまでも空けておくことになります。

なぜこれがNextcloudで徒になるのか

Nextcloudのデータの性質と通信の仕組みにあります。

巨大なファイルを細切れにする

Nextcloudは、数MBから数GBあるような大きなファイルを送る際、一気に送らずにファイルを分割して、「チャンク(塊)」に分割して送信します。

  • 動作の流れ:
    • チャンクAを送信 → サーバーが処理 → チャンクBを送信……
  • 問題点:
    • チャンクとチャンクの間に、クライアント側でのファイル読み込みやハッシュ計算などで一瞬「無通信」の時間が流れます。
  • 結果:
    • Apacheのmod_reqtimeoutは、この無通信を先のSlowlorisと誤認して、接続をバッサリ切ってしまいます。

モバイル回線の不安定さ

Nextcloudは外出先のスマートフォンから使うことを想定しています。

  • 電波の瞬断:
    • 移動中にWi-Fiから4G/5G回線に切り替わったりする。
  • 上り速度の制限:
    • モバイル回線は「下り」は速くても「上り」が極端に遅いことが多い。

これも、先のSlowloris攻撃と見做されてしまいます。

チューニングの必要性

だからといって、このmod_reqtimeoutを無効にすると、それらの攻撃への備えがなくなります。

Nextcloudの利便性を高めつつ不審な攻撃を守るというのは

「任務」は遂行する「部下」も守る
お前ごときに「両方」やるというのはそう難しいことじゃあないな

ぐらいの精神でやっていきましょう。

さっくりとした手順

  • mod_reatimeoutの設定ファイルのバックアップを取る。
  • mod_reatimeoutの設定ファイルを修正する。
  • サービス再起動を行う。

mod_reatimeoutの設定ファイルのバックアップ

  • 念のためのモジュール確認
sudo apache2ctl -M |grep req

reqtimeout_module (shared)を確認します。(apacheをapt等で入れていれば、まず入っています)

  • ファイルバックアップ
sudo cp -pi /etc/apache2/mods-available/reqtimeout.conf /path/to/backup/directory/reqtimeout.conf.$(date +%Y%m%d)

/path/to/backup/directoryは自分の環境に合わせます。

  • ファイルバックアップ確認
diff -u /path/to/backup/directory/reqtimeout.conf.$(date +%Y%m%d) /etc/apache2/mods-available/reqtimeout.conf 

エラーがないことを確認します。

mod_reatimeoutの設定ファイルを修正

/etc/apache2/mods-available/reqtimeout.confを管理者権限で修正します。

筆者は以下のように行いました。

-RequestReadTimeout body=10,minrate=500
+RequestReadTimeout body=20,minrate=500

具体的には、リクエストボディ(データの送信本体)の読み取り開始を待機する時間を10秒から20秒へ延長しています。

  • body=20:
  • リクエストボディの最初の1バイトを待つ時間を20秒に設定。
  • minrate=500:
  • データが送り始められた後、最低でも秒間500バイトの転送速度を要求する。これより遅い状態が続くとタイムアウトします。
  • ファイルの差分確認
diff -u /path/to/backup/directory/reqtimeout.conf.$(date +%Y%m%d) /etc/apache2/mods-available/reqtimeout.conf 

以下のような差分を確認します。

-RequestReadTimeout body=10,minrate=500
+RequestReadTimeout body=20,minrate=500

設定反映

  • 構文チェック
sudo apache2ctl configtest

Syntax OKとなることを必ず確認してください。でないと、apacheサービスが停止したままとなってしまい、サービス断が発生します。

  • Apache サービス再起動
sudo systemctl reload apache2.service
  • Apacheサービス再起動確認
systemctl status apache2.service

active(running)を確認します。

まとめ

Nextcloudサーバーにおいて、RequestReadTimeout のbody待ち時間を延長することは、「モバイル環境や大容量ファイル送信時の安定性」を向上させるために非常に有効な手段です。

もし、ログ(Apacheのerror_log)に The timeout specified has expiredrequest body read timeout といった記録が残っている場合は、この値を調整してみることをお勧めします。

  • 参考コマンド
sudo grep "request body read timeout" /var/log/apache2/error.log