Apacheモジュール
- Ubuntu20.04サーバにApacheのDoS対策モジュール(mod_evasive)を導入。
- UbuntuサーバにMod_Securityを導入。
- Mod_Securityで特定のルールを無視する設定(Nextcloudでの偽陽性を排除)
Ubuntu20.04サーバにApacheのDoS対策モジュール(mod_evasive)を導入。
概要
DoS/DDoS対策ができるモジュールをApacheに導入したときのメモです。
環境
- Ubuntu 20.04
- Apache 2.4系
- FWにufwを利用
さっくりとした手順
- mod_evasiveモジュールをインストールします。
- apache2実行ユーザー(www-data)がufwを利用できるように設定します。
- mod_evasiveモジュールの設定をします。
- 設定の反映を行います。
まずはサーバにターミナルログインするところから始めます。
mod_evasiveのインストール
sudo aptitude install libapache2-mod-evasive
このとき、postfixが依存関係でインストールされる場合があります。メール機能が使えない(AWS等で送信が制限されているなど)は、途中の設定で「何もしない」を選択します。
apache2実行ユーザーの権限変更
これは、www-dataがufwを実行する場合の処理です。権限昇格の危険性を承知した上で、慎重に作業を行ってください。
- sudoersファイルのバックアップ
sudo cp -pi /etc/sudoers /path/to/backup/directory/sudoers.$(date +%Y%m%d)
任意のバックアップディレクトリを指定します。
- diffによるバックアップ確認
sudo diff -u /path/to/backup/directory/sudoers.$(date +%Y%m%d) /etc/sudoers
差分がないことを確認します。
- ファイル追記
echo 'www-data ALL=(ALL) NOPASSWD: /usr/sbin/ufw' | sudo tee -a /etc/sudoers
- ファイル追記確認
sudo diff -u /path/to/backup/directory/sudoers.$(date +%Y%m%d) /etc/sudoers
以下の差分を確認します。
+www-data ALL=(ALL) NOPASSWD: /usr/sbin/ufw
evasiveの設定変更
- ファイルバックアップ
sudo cp -pi /etc/apache2/mods-available/evasive.conf /path/to/backup/directory/evasive.conf.$(date +%Y%m%d)
- diffによるバックアップ確認
sudo diff -u /path/to/backup/directory/evasive.conf.$(date +%Y%m%d) /etc/apache2/mods-available/evasive.conf
差分がないことを確認します。
-
以下のファイルを教義・信仰に沿ったエディタで編集していきます。
-
/etc/apache2/mods-available/evasive.conf
-
-
編集例
DOSHashTableSize 3097
DOSPageCount 100
DOSSiteCount 100
#かなり緩く設定して、後で狭めていった方が偽陽性を防げます。
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 10
#DOSEmailNotify you@yourdomain.com
#メール通知を行わないため、ここを省いています
DOSSystemCommand "sudo ufw deny proto tcp from %s to any port 80,443"
# 検証時に自分のサイトがブロックされるのを防ぐため、ポートは80/443に絞っています
DOSLogDir "/var/log/mod_evasive"
DOSWhitelist 127.0.0.1
DOSWhitelist xx.xx.xx.xx
# 対象外としたいIPアドレス(自分の環境など)
参考:Apache の DoS攻撃対策モジュール mod_evasive
- 設定編集確認
sudo diff -u /path/to/backup/directory/evasive.conf.$(date +%Y%m%d) /etc/apache2/mods-available/evasive.conf
- 差分例
- #DOSHashTableSize 3097
- #DOSPageCount 2
- #DOSSiteCount 50
- #DOSPageInterval 1
- #DOSSiteInterval 1
- #DOSBlockingPeriod 10
+ DOSHashTableSize 3097
+ DOSPageCount 100
+ DOSSiteCount 100
+ DOSPageInterval 1
+ DOSSiteInterval 1
+ DOSBlockingPeriod 10
#DOSEmailNotify you@yourdomain.com
- #DOSSystemCommand "su - someuser -c '/sbin/... %s ...'"
- #DOSLogDir "/var/log/mod_evasive"
+ DOSSystemCommand "sudo ufw deny proto tcp from %s to any port 80,443"
+ DOSLogDir "/var/log/mod_evasive"
+ DOSWhitelist 127.0.0.1
+ DOSWhitelist xx.xx.xx.xx
</IfModule>
設定反映
- 構文確認
sudo apache2ctl configtest
Syntax OK
を確認します。
- apache再起動
sudo systemctl restart apache2.service
これで、不審なアクセスが大量にあったときにufwで弾く体制が整いました。
UbuntuサーバにMod_Securityを導入。
ApacheのWAFモジュールであるmod_securityを導入します。
- AWS Lightsailで早々とインストールしていた
- 各種不審なIPアドレスを弾くための盾
として機能しているにもかかわらず文書化していなかったので、Web Arenaでの検証を機に文章に残します。
環境
- Ubuntu 24.04 (20.04でも一応動くとは思います)
- Apache 2.4
※ パッケージ管理にaptitudeを用いています。必要に応じてaptに読み替えてください。
さっくりとした手順
- mod_securityのインストールを行います。
- mod_securityの設定を行います。
- Apacheのバーチャルサイトにmod_securityを組み込みます。
- 設定を反映して動作を確認します。
mod_securityのインストールを行います。
- パッケージ全体のアップデート
sudo aptitude update
- mod_securityインストール
sudo aptitude install libapache2-mod-security2
- インストール確認
sudo apache2ctl -M |grep security
security2_module (shared)
と表示されていることを確認します。
ModSecurityの設定
- 設定ファイル書き換え
sudo mv /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
推奨ファイルをそのまま設定ファイルとして書き換えます。
OWASP Core Rule Set (CRS)のインストールと設定
- ディレクトリ移動
cd /usr/share/modsecurity-crs && pwd
- ルールセットのダウンロード
sudo git clone https://github.com/coreruleset/coreruleset.git
- ルールセットの設定書き換え
sudo mv /usr/share/modsecurity-crs/coreruleset/crs-setup.conf.example /usr/share/modsecurity-crs/coreruleset/crs-setup.conf
mod_securityモジュールにCRSを読み込む設定を追記
- ディレクトリ移動
cd /etc/apache2/mods-available/ && pwd
- ファイルのバックアップ
sudo cp -pi security2.conf /path/to/backup/directory/security2.conf.$(date +%Y%m%d)
任意のバックアップディレクトリを指定します。
- バックアップ確認
diff -u /path/to/backup/directory/security2.conf.$(date +%Y%m%d) security2.conf
エラーがなければバックアップは成功です。
- ファイル追記
/etc/apache2/mods-available/security2.conf
を、以下の差分になるように教義・信仰に沿ったエディタで編集します。(要root権限)
- </IfModule>
+ # Include OWASP ModSecurity CRS rules if installed
+ IncludeOptional /usr/share/modsecurity-crs/*.load
+</IfModule>
- 設定追記の整合性を確認
sudo apache2ctl configtest
Syntax OK
を確認します。
- Apache再起動
sudo systemctl restart apache2.service
- Apache再起動確認
systemctl status apache2.service
active (running)
を確認します。
Apacheのバーチャルサイト編集
稼働済みのApacheバーチャルサイトの設定ファイルをいじります。バックアップ確認は入念に行ってください。
- ディレクトリ移動
cd /etc/apache2/sites-available && pwd
- バーチャルサイトの設定ファイルバックアップ
sudo cp -pi your_site.conf /path/to/backup/directory/your_site.conf.$(date +%Y%m%d)
.confファイルやバックアップディレクトリは自分の環境を指定します。
- バックアップ確認
diff -u /path/to/backup/directory/your_site.conf.$(date +%Y%m%d) your_site.conf
エラーがなければバックアップは成功です。
- ファイル追記
/etc/apache2/sites-available/your_site.conf
を、以下の差分になるように教義・信仰に沿ったエディタで編集します。(要root権限)
# Mod Security
## ModSecurity有効化
SecRuleEngine On
## ModSecurity検知モード
### 検知モードで動かす場合はSecRuleEngine Onをコメントアウトしてこちらを有効化します
#SecRuleEngine DetectionOnly
## ファイルのアップロードをできるようにします。
SecRequestBodyInMemoryLimit 524288000
SecRequestBodyLimit 524288000
## テスト用の検知パラメータを付け加えます。
SecRule ARGS:modsecparam "@contains test" "id:4321,deny,status:403,msg:'ModSecurity test rule has triggered'"
- ファイル差分
diff -u /path/to/backup/directory/your_site.conf.$(date +%Y%m%d) your_site.conf
+# Mod Security
+
+## ModSecurity有効化
+SecRuleEngine On
+## ModSecurity検知モード
+### 検知モードで動かす場合はSecRuleEngine Onをコメントアウトしてこちらを有効化します
+#SecRuleEngine DetectionOnly
+
+## ファイルのアップロードをできるようにします。
+SecRequestBodyInMemoryLimit 524288000
+SecRequestBodyLimit 524288000
+
+## テスト用の検知パラメータを付け加えます。
+ SecRule ARGS:modsecparam "@contains test" "id:4321,deny,status:403,msg:'ModSecurity test rule has triggered'"
+
- 設定追記の整合性を確認
sudo apache2ctl configtest
Syntax OK
を確認します。
- Apache再起動
sudo systemctl restart apache2.service
- Apache再起動確認
systemctl status apache2.service
active (running)
を確認します。
mod_security動作確認
- ブラウザで、上記の設定を行ったWebサイトにアクセスし、閲覧できることを確認します。
- アドレスバーの末尾に
?modsecparam=test
を追加してアクセスします。
のように、アクセスできないことを確認します。
また、サーバでも
sudo cat /path/to/sites_log/directory/sites_error.log
※ログの格納場所やログの名前は自分の環境に合わせます。
を開き、
ModSecurity: Access denied with code 403 (phase 2). String match "test" at ARGS:modsecparam. [file "/etc/apache2/sites-enabled/your_site.conf"] [line "53"] [id "4321"] [msg "ModSecurity test rule has triggered"] [hostname "host_address"] [uri "/"] [unique_id "xxxxxxx"]
のように、エラーが発生していることを確認します。
備考
Wordpress、Redmine等のWebアプリは自身の操作によって「不審なアクセス」として遮断することが極めてよくあります。(偽陽性)
そのため、テストを行った後は
## ModSecurity有効化
#SecRuleEngine On
## ModSecurity検知モード
### 検知モードで動かす場合はSecRuleEngine Onをコメントアウトしてこちらを有効化します
SecRuleEngine DetectionOnly
として検知モードとして動かした方が良いでしょう。
Mod_Securityで特定のルールを無視する設定(Nextcloudでの偽陽性を排除)
Nextcloudにmod_securityを導入するに当たり、気をつけなければならないのがファイルの閲覧や登録、入力処理中にMod_securityが不審な処理として判断してしまうこと(偽陽性)です。
そこで、
- 偽陽性と思われるログの調査
- 調査時の補助線引き
- 偽陽性になるルールを無視する設定
を行います。
ログ確認
/var/log/nextcloud_error.log
から、以下のようなログを見ました。
[Wed Sep 11 16:35:02.048442 2024] [security2:error] [pid 32762:tid 32762] [client aaa.bbb.ccc.ddd:56994] [client aaa.bbb.ccc.ddd] ModSecurity: Warning. Operator GE matched 5 at TX:inbound_anomaly_score. [file "/usr/share/modsecurity-crs/rules/RESPONSE-980-CORRELATION.conf"] [line "92"] [id "980130"] [msg "Inbound Anomaly Score Exceeded (Total Inbound Score: 5 - SQLI=0,XSS=0,RFI=0,LFI=0,RCE=0,PHPI=0,HTTP=0,SESS=0): individual paranoia level scores: 5, 0, 0, 0"] [ver "OWASP_CRS/3.3.5"] [tag "event-correlation"] [hostname "nextcloud.hoge.com"] [uri "/ocs/v2.php/apps/user_status/api/v1/heartbeat"] [unique_id "ZuFIJU_udFaqxqrJvRLaPQAAAAA"]
ここで見たいのは
- クライアントのIPアドレス
- どのようなルールIDを
- どのぐらい検知したか
です。
ログ確認のワンライナー
これらを確認するため、copilotの助けを借りてawkスクリプトを生成します。
awk '/ModSecurity/ {
ip = gensub(/.*\[client ([0-9.]+):.*/, "\\1", "g", $0);
rule_id = gensub(/.*\[id "([0-9]+)"\].*/, "\\1", "g", $0);
print rule_id, ip;
}' /var/log/nextcloud/nextcloud_error.log | sort | uniq -c
これを実行したところ、Mod_Securityがエラーとして検知したログの中から
36 911100 127.0.0.1
267 911100 aaa.bbb.ccc.ddd
65 920420 aaa.bbb.ccc.ddd
36 949110 127.0.0.1
267 949110 aaa.bbb.ccc.ddd
36 980130 127.0.0.1
267 980130 aaa.bbb.ccc.ddd
という結果を確認しました。127.0.0.1はローカルアドレス、aaa.bbb.ccc.dddも自分がアクセスしてきたIPアドレス。この間、自分がしていたのはNextcloudの設定変更やファイルの閲覧のみです。
Mod_securityが検知したルールIDを「偽陽性」と判断し、処置していきます。
Mod_Securityで特定のルールを検知させない処理
Apacheのバーチャルサイトで設定しているという形です。
設定ファイルの修正
- ファイルのバックアップ
sudo cp -ci /etc/apache2/sites-available/nextcloud.conf /path/to/backup/directory/nextcloud.conf.$(date +%Y%m%d)
設定ファイルやバックアップディレクトリは自分の環境に合わせます。
- バックアップ確認
diff -u /path/to/backup/directory/nextcloud.conf.$(date +%Y%m%d) /etc/apache2/sites-available/nextcloud.conf
エラー無く、差分も表示されていなければバックアップは成功です。
- ファイル修正
/etc/apache2/sites-available/nextcloud.conf
を以下のように修正していきます。(要root権限)
# Mod_security
## 最初は検知モード
SecRuleEngine DetectionOnly
## 偽陽性と判断したID
SecRuleRemoveById 911100
SecRuleRemoveById 920420
SecRuleRemoveById 949110
SecRuleRemoveById 980130
- ファイル修正確認
diff -u /path/to/backup/directory/nextcloud.conf.$(date +%Y%m%d) /etc/apache2/sites-available/nextcloud.conf
SecRuleRemoveById ID
で、これにマッチするパターンは無視します。
- 差分例
## 最初は検知モード
SecRuleEngine DetectionOnly
+
+## 偽陽性と判断したID
+SecRuleRemoveById 911100
+SecRuleRemoveById 920420
+SecRuleRemoveById 949110
+SecRuleRemoveById 980130
+
</VirtualHost>
設定ファイルの設定反映
- 構文確認
sudo apache2ctl configtest
Syntax OK
を確認します。
- 設定反映
sudo systemctl restart apache2.service
- Apache稼働確認
systemctl status apache2.service
active(running)
を確認します。
動作確認
ターミナルで
tail -f /var/log/nextcloud/nextcloud_error.log
としてエラーログを流します。(エラーログは自分の環境に合わせます)
- 上記処理を行ったNextcloudにアクセスして操作をしていきます。
- 処理を行ったIDが検知されないことを確認します。