この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので十分ご注意ください。
「Linuxにログインしたユーザーの操作ログが欲しい」
あなたならどうしますか?
わたしは「history」や「last」コマンドでなんとかなるだろうと考えていました。しかし、取得する操作ログには以下の要件を満たしている必要があったのです。
- 実行ユーザー名が記録されている
- 実行時刻がわかる
- コマンド結果
「history」や「last」コマンドでは上記の条件を満たしていません。どうすればいいのか・・・
そんなあなたに今回紹介するのが、ログインユーザーの操作ログを自動で取得する方法です。
ユーザーの操作ログを自動記録する方法
操作ログといえば、わたしは「history」コマンドを思い浮かべました。しかし、historyと叩けばわかるのですが、コマンド自体の記録しか残っておりません。実行結果や実行した時刻が記録されていないので、証跡としては不十分です。
今回わたしが考えた記録方法は、ssh接続したログインユーザーが実行したコマンド・実行結果をscriptコマンドで記録する方法です。
操作ログを漏れなく取得するために、/etc/prfileにスクリプトを追記し、ユーザーログイン時にscriptコマンドが実行されるように設定します。
■scriptコマンド
今回の自動記録で利用する"script"コマンドについて説明します。
script は、端末セッションで行われるすべてについて忠実な記録 (タイプスクリプト、typescript) を作成する。端末上のデータは、未加工のまま (in raw form) ログファイルに記録され、 タイミングに関する情報は、(作成する、しないが任意の) 構造化された別のログファイルに記録される。このタイミングのログファイルは、後で scriptreplay(1) を使用して、セッションを再生するためにも、 またセッションに関する補足情報を記録するためにも必要である。(linuxjm.osdn.jpより)
scriptコマンドを打つと、実行したコマンドや実行結果をすべて記録することができるんですよね。
しかし、ユーザーがログインする度にscriptコマンドを打つのは大変ですし、漏れが発生することでしょう。
■構築
ログインユーザーの操作ログを自動で記録するために、/etc/prfileにscriptコマンドが実行されるよう追記します。また、操作ログは指定のディレクトリに保存されるように設定しておきましょう。
それでは、構築していきます。
[ec2-user@ip-172-31-20-170 ~]$ sudo su -
[root@ip-172-31-20-170 ~]# mkdir -p /var/log/scripts/opelog/
[root@ip-172-31-20-170 ~]# chmod 733 -R /var/log/scripts/opelog/
[root@ip-172-31-20-170 ~]# cp /etc/profile /etc/profile.`date "+%Y%m%d"`
[root@ip-172-31-20-170 ~]# ls /etc/profile*
/etc/profile /etc/profile.20230211
/etc/profile.d:
256term.csh bash_completion.sh colorgrep.sh colorls.sh lang.csh less.csh sh.local which2.sh
256term.sh colorgrep.csh colorls.csh csh.local lang.sh less.sh which2.csh
/etc/profileに以下のスクリプト追記します。
# operationLog
nowProcess=`ps aux | grep $PPID | grep sshd | awk '{ print $11 }'`
if [ "$nowProcess" = sshd: ]; then
todayDate=`date '+%Y%m%d%H%M'`
loginUser=`whoami`
script -afq /var/log/scripts/opelog/${loginUser}_${todayDate}.log
fi
それでは追記します。
[root@ip-172-31-20-170 ~]# vi /etc/profile
# /etc/profile
# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc
# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.
pathmunge () {
case ":${PATH}:" in
*:"$1":*)
;;
*)
if [ "$2" = "after" ] ; then
PATH=$PATH:$1
else
PATH=$1:$PATH
fi
esac
}
if [ -x /usr/bin/id ]; then
if [ -z "$EUID" ]; then
# ksh workaround
EUID=`/usr/bin/id -u`
UID=`/usr/bin/id -ru`
fi
USER="`/usr/bin/id -un`"
LOGNAME=$USER
MAIL="/var/spool/mail/$USER"
fi
# Path manipulation
if [ "$EUID" = "0" ]; then
pathmunge /usr/sbin
pathmunge /usr/local/sbin
else
pathmunge /usr/local/sbin after
pathmunge /usr/sbin after
fi
HOSTNAME=`/usr/bin/hostname 2>/dev/null`
HISTSIZE=1000
if [ "$HISTCONTROL" = "ignorespace" ] ; then
export HISTCONTROL=ignoreboth
else
export HISTCONTROL=ignoredups
fi
export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL
# By default, we want umask to get set. This sets it for login shell
# Current threshold for system reserved uid/gids is 200
# You could check uidgid reservation validity in
# /usr/share/doc/setup-*/uidgid file
if [ $UID -gt 199 ] && [ "`/usr/bin/id -gn`" = "`/usr/bin/id -un`" ]; then
umask 002
else
umask 022
fi
for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
unset i
unset -f pathmunge
# operationLog
nowProcess=`ps aux | grep $PPID | grep sshd | awk '{ print $11 }'`
if [ "$nowProcess" = sshd: ]; then
todayDate=`date '+%Y%m%d%H%M'`
loginUser=`whoami`
script -afq /var/log/scripts/opelog/${loginUser}_${todayDate}.log
fi
追記が完了しましたら、保存し、ログアウトしましょう。
ESC
:wq
[root@ip-172-31-20-170 ~]# exit
logout
[ec2-user@ip-172-31-20-170 ~]$ exit
構築は以上です。
■動作確認
操作ログが記録されるか見ていきましょう。
ssh接続でログインします。
適当なコマンドを実行してみます。
[ec2-user@ip-172-31-20-170 ~]$ pwd
/home/ec2-user
[ec2-user@ip-172-31-20-170 ~]$ whoami
ec2-user
[ec2-user@ip-172-31-20-170 ~]$ uname -a
Linux ip-172-31-20-170.ap-southeast-1.compute.internal 5.10.162-141.675.amzn2.x86_64 #1 SMP Mon Jan 9 22:45:11 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
ログの中身を見てみます。
[ec2-user@ip-172-31-20-170 ~]$ exit
exit
[ec2-user@ip-172-31-20-170 ~]$ sudo su -
Last login: Sat Feb 11 02:23:29 UTC 2023 on pts/0
[root@ip-172-31-20-170 ~]# ls /var/log/scripts/opelog/
ec2-user_202302110229.log
[root@ip-172-31-20-170 ~]# less /var/log/scripts/opelog/ec2-user_202302110229.log
Script started on 2023-02-11 02:29:39+0000
ESC]0;ec2-user@ip-172-31-20-170:~^GESC[?1034h[ec2-user@ip-172-31-20-170 ~]$ pwd
/home/ec2-user
ESC]0;ec2-user@ip-172-31-20-170:~^G[ec2-user@ip-172-31-20-170 ~]$ whoami
ec2-user
ESC]0;ec2-user@ip-172-31-20-170:~^G[ec2-user@ip-172-31-20-170 ~]$ uname -ESC[Ka
Linux ip-172-31-20-170.ap-southeast-1.compute.internal 5.10.162-141.675.amzn2.x86_64 #1 SMP Mon Jan 9 22:45:11 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
ESC]0;ec2-user@ip-172-31-20-170:~^G[ec2-user@ip-172-31-20-170 ~]$ exit
exit
Script done on 2023-02-11 02:33:03+0000
/var/log/scripts/opelog/ec2-user_202302110229.log (END)
ログは以下の画像です。
正直きれいな見た目ではありません。Linuxの知識をさらにつけ、クールな出力になるように改善していきます。
■注意点
今回の「ログインユーザーの操作ログを自動で取得する方法」には、いくつか注意点があります。
- exitを打つとシェルが終了し記録が止まる
- ログの見た目が汚い
- 長時間操作した場合、ファイルサイズが大きくなる
- ログファイルがたまっていく
まとめ:LinuxOSにログインしたユーザーの操作ログを自動記録してみる
わたしは今の現場でログ収集の業務を行っています。ログの種類はさまざまですが、今回の操作ログのように、取得できる方法を自分で考えなければいけないことがあります。がんばっていきましょう!
また、今回紹介した方法は、まだまだ改善の余地がありますので、随時追記していくつもりです。
↓ほかの協栄情報メンバーもLinuxに関する記事を公開しています。ぜひ参考にしてみてください。
■Linuxコマンド紹介-「grep」(dapeng)
https://cloud5.jp/linux-grep/
■AWS EC2 (Redhat linux 8)にSSHログインユーザの追加手順(小林 剛)
https://cloud5.jp/aws-ec2-redhat-linux-8-ssh/
■EC2(RHEL)でSELinuxを無効化するハンズオン(INAMURA)
https://cloud5.jp/invalid-selinux-on-ec2/