Nginxのログファイルをリアルタイムで暗号化する方法を記載します。
POSTされたログ(リクエストボディ)は欲しいけど、ローカルに記録されるタイミング(リアルタイム)では暗号化したい見たいなシチュエーションを想定しています。
ログファイル自体を都度暗号化する方法はググればすぐ出てきますが、リアルタイムで
暗号化する方法は意外となくて、OSの持つ機能で手軽にできないか模索していた際に思いついた内容です。
セキュリティ面の問題やパフォーマンス、およびその他十分な動作検証をしている
わけではないので利用する際は十分検証を行ってください。
1. 環境
- OS : CentOS7.9
- Kernel: 3.10.0-1160.49.1.el7.x86_64
- Nginx: 1.18.0
- rsyslog: 8.24.0-57
- openssl: 1.0.2k-22
2. Nginx設定
リクエストボディの内容がログに記録されるようにlogフォーマットを作成し、それをsyslogに転送できるように設定します。
※下記設定はすべてがnginx.confだけで構成されている例となります。conf.d配下にserverディレクティブを分けて記載している場合、access_log 部分は適切な場所に設定してください。
vim /etc/nginx.conf
log_format custom '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" "request_body": "$request_body"';
access_log syslog:server=127.0.0.1:514,facility=local6,severity=debug custom;
:wq
nginx -t
systemctl restart nginx
3. SYSLOG設定
Nginxから転送されたログを受け取れるようrsyslog.confの設定を変更します。
vim /etc/rsyslog.conf
$ModLoad imudp
$UDPServerRun 514
$AllowedSender UDP, 127.0.0.1
local6.debug |/var/log/plain.fifo
:wq
4. fifoファイル作成/暗号化用Shell作成
fifo/ログファイル作成します。
mkfifo /var/log/plain.fifo
touch /var/log/crypt.log
systemctl restart rsyslog
スクリプト配置用ディレクトリ作成します。
mkdir -p /usr/local/encrypt/bin
cd /usr/local/encrypt/bin
暗号化用スクリプト作成します。
vim encryption.sh
# !/bin/bash
LOGBASE=/var/log
MONITORING_LOG=${LOGBASE}/plain.fifo
TARGET_LOG=${LOGBASE}/crypt.log
action() {
while read plaintext
do
echo "${plaintext}" | openssl enc -pass pass:abc123 -e -aes128 | base64 -w 1000 >> ${TARGET_LOG}
done
}
cat ${MONITORING_LOG} | action
※pass:abc123は暗号化/復号化実施時に利用するパスワードです。
実運用では環境変数を利用するなど工夫して使ってください。
※base64 の「-w 1000」はログファイル1行の折り返し文字指定(デフォルト76文字)です。
実際のログに合わせて値は調整してください。
あとは作成したencryption.shに実行権限をつけてバックグランドで起動。
自動起動したい人はrc.localとか .serviceファイルを作成して利用してください。
復号化させる場合は、暗号化されたログファイル自体を読み込んで1行ずつ復号化させれば
平文のログを閲覧できます。
vim decode.sh
BASEDIR=/var/log
TARGET_LOG=crypt.log
while read decrypt
do
echo "${decrypt}" | base64 -d | openssl enc -pass pass:abc123 -d -aes128
done < ${BASEDIR}/${TARGET_LOG}