LinuxOSにログインしたユーザーの操作ログを自動記録してみる


この記事は公開されてから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-automatic-logging実行結果

 

 

正直きれいな見た目ではありません。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/

 

Last modified: 2023-02-11

Author