意地でもBASIC認証を使いたいあなたへ@SSL化&多要素認証&Fail2Banでお手軽要塞


前提
・Azure仮想マシンを利用する
・firewalld/SELinuxは無効にしている
・OSはRHEL9.5/Gen2
・Apache/2.4.62
・今回はGoogleAuthenticatorを使う
・自己証明書を使う
・コマンド実行はすべてroot権限で行っています



用語のおさらい

BASIC認証とは?

ウェブサーバーが提供する最もシンプルな認証方式の一つです。ユーザー名とパスワードを入力することで、特定のページやディレクトリへのアクセスを制限できます。

Fail2Banとは?

不正なログイン試行を検出し、自動的にIPアドレスをブロックするセキュリティツールです。主にSSHやApache、nginxなどのサービスを保護するために使用されます。

TOTP(Time-based One-time Password)とは

一定時間ごとに変わるワンタイムパスワードを生成する、多要素認証の一つです。
今回はGoogle Authenticatorを使います。※Microsoftのでもいい。

※多要素認証は2つ以上の要素を組み合わせて認証を行う仕組みです。
単純なパスワード認証よりも高いセキュリティを提供します。
今回で言うとサーバー上に格納してあるユーザという要素(知識要素)とアプリとかで発行されるトークンという要素(所持要素)のこと。


実装方法(手順を進めるごとに要塞になります)


①前準備 (ノーガード)


 firewalld無効     (任意)

systemctl stop firewalld
systemctl disable firewalld
systemctl mask firewalld

 SELINUX無効     (任意)

sed -i 's/^SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
reboot

補足
vi で /etc/selinux/config を直接編集してもOK。
setenforce 0 は即座に Permissive になるが、Disabled にはならない。
Permissive の状態では、SELinuxのアクセス制御は行われないが、ログには記録される。完全に Disabled にするにはrebootが必要。
rebootしなくても Permissive の状態ならブロックされないので、動作的には問題ない。

 必要なパッケージ系のインストールと起動設定

 ブラウザから見えるように設定

#現在設定がしてあるドキュメントルートにhtmlファイルを置く
grep -i "DocumentRoot" /etc/httpd/conf/httpd.conf |grep -v "#"
 DocumentRoot "/var/www/html"

#ファイルの新規作成    ※「>」は上書き「>>」は追記。。。苦い思い出があるので一応追記にしてます
echo "Apache Test" >> /var/www/html/index.html

#権限設定
chown apache:apache /var/www/html/index.html

#必要な場合
chmod 644 /var/www/html/index.html

これでブラウザでサーバーIPをたたいたらテストページが見えるハズ!


②自己証明書を使ったSSL化 (一般的なセキュア)


下準備

#opensslが使えるかどうか確認する
openssl version
OpenSSL 3.2.2 4 Jun 2024 (Library: OpenSSL 3.2.2 4 Jun 2024)

#なければインストール
dnf install -y openssl

#sslに必要なモジュールをインストール
dnf install -y mod_ssl

※mod_sslをインストールすると以下のディレクトリができる
/etc/httpd/conf.d/ssl.conf

自己証明書(鍵)の作成

#鍵を作る場所の移動(後から移動する)
cd ~

# 以下コマンドは 証明書の対(server.key server.crt)作成と有効期限365日の指定です。
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes

#以下は
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:TOKYO
Locality Name (eg, city) [Default City]:hoge
Organization Name (eg, company) [Default Company Ltd]:huga
Organizational Unit Name (eg, section) []:piyo
Common Name (eg, your name or your server's hostname) []:hogehugapiyo.jp
Email Address []:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#確認(抜粋) 2つ作成されていること
ls -lsa 
 4 -rw-r--r--   1 root root  2025 Feb 26 08:04 server.crt
 4 -rw-------   1 root root  3272 Feb 26 08:03 server.key

作った自己証明書をApacheに読み込ませる設定

#sslの設定ファイルの存在確認(mod_sslインストール時に配置されるハズ。。)新規作成でも可
ls -lsa /etc/httpd/conf.d/ssl.conf

#ssl設定ファイルがincludeされていることを確認(IncludeOptional conf.d/*.conf)
cat /etc/httpd/conf/httpd.conf |grep "Include" |grep -v "#"
 Include conf.modules.d/*.conf
 IncludeOptional conf.d/*.conf         ←これ

#鍵の配置場所を確認
grep "SSLCertificate" /etc/httpd/conf.d/ssl.conf | grep -v "#"
 SSLCertificateFile /etc/pki/tls/certs/localhost.crt
 SSLCertificateKeyFile /etc/pki/tls/private/localhost.key

#名前がlocalhostなので変更しつつ移動する
mv /root/server.crt /etc/pki/tls/certs/localhost.crt
mv /root/server.key /etc/pki/tls/private/localhost.key

httpの通信をhttpsにリダイレクトさせる設定

今回は自己証明書の為、見た目や信頼性の部分は良くないが、暗号化はされるのでテスト環境にはいいと思う。

自己証明書

③多要素認証の導入 (もうだいぶ要塞)


 多要素認証のユーザを作るスクリプトを作成&実行

#スクリプトを作る場所(どこでもいい) 
cd ~

#スクリプト作成「.shがついてれば名前は何でもいい」
vim makeauth-users.sh
#=====================
#!/bin/bash
user=${1:?Usage: $0 username}
file="/etc/httpd/conf/otp-users"
secret=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 15 | head -n 1)
secret_16=$(python3 -c "import base64; print(base64.b16encode(b'$secret').decode())")
secret_32=$(python3 -c "import base64; print(base64.b32encode(b'$secret').decode().rstrip('='))")
otpauth_uri="otpauth://totp/${issuer}:${user}?secret=${secret_base32}&issuer=${issuer}"

# ファイルがなければ作成
[ -f "$file" ] || touch "$file"

# 既存ユーザー確認して追加
if grep -q "^HOTP/T30 $user" "$file"; then
  echo " '$user' は既に存在します."
else
  echo "HOTP/T30 $(printf '%-12s' $user) - $secret_16" >> "$file"
  echo "'$user' を追加しました。 アプリに設定する鍵は: $secret_32  です"
fi
#=====================

#権限を追加
chmod +x makeauth-users.sh

#多要素認証のユーザ(makino)を作成(secretの値はアプリで設定します)
./makeauth-users.sh makino
 'makino' を追加しました。 アプリに設定する鍵は: XXXXXXXXXXXXXXXXXXXXXXX  です

#ユーザ確認   
cat /etc/httpd/conf/otp-users
#HOTP/T30 makino       - YYYYYYYYYYYYYYYYYYYYYYYYY


アプリ側設定
GoogleAuthenticatorアプリを開く。  
「+」を押し、セットアップキーを入力をクリック
以下の情報を入力
  「アカウント名」分かり易ければなんでもいい
   (例  makino@webServer)
  「鍵」
   ユーザを作った時のsecretの値(XXXXXXXXXXXXXXXXXXXXXXX) 
  「鍵の種類」
   時間ベース

 

BASIC認証の設定

#設定ファイル修正 注意:Directory内は修正し、モジュールは新規追加
vim /etc/httpd/conf/httpd.conf
==============================================================================
LoadModule authn_otp_module /usr/lib64/httpd/modules/mod_authn_otp.so
<Directory "/var/www/html">
    AuthType Basic
    AuthName "ワンタイムパスワード認証が必要です"
    AuthBasicProvider OTP
    Require valid-user
    OTPAuthUsersFile /etc/httpd/conf/otp-users
    OTPAuthMaxLinger 3600
    OTPAuthMaxOTPFailure 20
    OTPAuthPINAuthProvider file
    OTPAuthLogoutOnIPChange On
</Directory>
==============================================================================
※モジュールの追加は忘れないこと。
※今回はドキュメントルートに設定しています。
※設定ファイルを更新したら反映させること

※反映(再起動またはリロード)
systemctl restart httpd
systemctl reload httpd

これでブラウザでサーバーIPをたたいたらBASIC認証が聞かれるハズ!

BASIC認証

ユーザ名はmakeauth-users.shで作ったもの
パスワードはGoogleAuthenticatorで表示される6桁の数字

Apacheに多要素認証を導入する方法については以上です。


④Fail2Banの導入 (要塞)


 設定ファイルの作成と編集

Fail2Ban の設定は基本的に /etc/fail2ban/jail.local に行います。jail.conf はデフォルト設定なので直接編集せず、jail.local に必要な設定を上書きする形で。

# 設定ファイルをコピーして作成 
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

 Apache 向け設定の追加

以下の設定を jail.local に追加します。

#設定ファイル修正
vim /etc/fail2ban/jail.local

[apache-otp] 
enabled = true 
port = http,https 
filter = apache-auth 
logpath = /var/log/httpd/error_log 
maxretry = 5 
bantime = 24h 
findtime = 600

 補足
enabled: このルールを有効化
port: 監視するポート(HTTP と HTTPS)
filter: 初期フィルタ(apache-authはfail2ban/filter.d/内にinstallされる)
logpath: ログファイルのパス(Apache のエラーログ)
maxretry: 指定時間内に許容する最大失敗回数
bantime: ブロックする秒数
findtime: 試行失敗回数をカウントする時間(秒)

 Fail2Ban の再起動と確認

#Fail2Ban再起動(反映)
systemctl restart fail2ban
fail2ban-client reload


#確認   ※Jailリストにapache-otpがある事
fail2ban-client status

Status
|- Number of jail:      1
`- Jail list:   apache-otp


#現在ブロックされているIP達
fail2ban-client status apache-otp

Status for the jail: apache-otp
|- Filter
|  |- Currently failed: 0
|  |- Total failed:     20
|  `- File list:        /var/log/httpd/error_log
`- Actions
   |- Currently banned: 1
   |- Total banned:     1
   `- Banned IP list:   xxx.xxx.xxx.xxx


#特定の IP をブロック解除(1が出たら解除完了) 
fail2ban-client set apache-otp unbanip xxx.xxx.xxx.xxx
1

設定は以上!!
お疲れ様でした。

まとめ


今回の要件としてはBASIC認証を絶対使わないといけない。
だけどセキュリティはカチカチにしたい。という方向けの記事になります。

BASIC認証の攻撃リスクについてよくあげられるのが以下3点です。

1.通信の盗聴(平文送信) ※中間者攻撃
2.総当たり攻撃に弱い   ※ブルートフォース攻撃
3.パスワード漏洩     ※リスト型攻撃

今回はそれぞれの攻撃に対応する設定方法を記載しました。
1.証明書を使いSSL化することで通信が平文で送信されることの防止。
自己証明書ではなくValuessl等で正式な証明書であれば見た目・信頼性共に良い。ただし料金はかかるので自己証明書でも可。

2.File2Banを使い、同じIPからの総当たり攻撃を防止する。
 カスタマイズもでき、要件にあった設定が可能。

3.TOTP認証を使うので万が一パスワードを盗まれても数秒で新しく発行がされるので安心。(SSL化すればさらに安心)ユーザーごとにシークレットキーを作成することができる。

少しでもみなさまのお役に立てれば幸いです。以上。


いいなと思ったら応援しよう!