0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SSHで叩かれたコマンドを記録する

Posted at

モチベーション

デプロイメントツールなどで、SSHで対象のサーバに入ってよしなに色々してくれるものがあります。
中で何やってるのか見てみたいなーという時がちょこちょこあるのですが、あまりピンとくる方法がなく、いつも時間切れで諦めてしまってました。

今回またそういう要件が出てきたので、再挑戦してみようと思います。

SSHのコマンドログを取る方法 基本方針

できるもの、できないものあるのですが、頭の整理のために並べてみます。

A. SSHDのロギングの機能を使うーNG

ログインの成否までは出せますが、中で叩いたコマンドはログに出ません。

B. ログイン時に呼び出されるShellに細工する

なんだかんだで現実的なのは、これですね。

C. 通信を横抜きーNG

したところで暗号化してるんですから。。。

D. プロキシを通す

Paramikoとか、、、?
現状Bのほうが筋が良さそうなので、まずはBで頑張って見ることにします。

Shellの細工方針

ググって調べた方針を整理します。

a. ログイン時に呼び出すシェルを、細工したスクリプトに置き換える

うまく行きそうだったのですが、後述のtrapの仕込みがうまく行きませんでした。
最後にbash -iを呼び出す際にtrapがそちらに引き継がれず。
exec側の方はうまく行ったのですが。。

トライしたのは以下。

$ echo $SHELL
/usr/local/bin/mtsh

$ cat /usr/local/bin/mtsh
#!/bin/bash

MT_LOGDIR=/var/log/sshlogs/

function log_history {
  echo $(date) $$ $BASH_COMMAND >> ${MT_LOGDIR}/history_${USER}
}
readonly -f log_history
trap log_history DEBUG EXIT ERR RETURN

exec &> >(tee -a >(awk '{print strftime("[%Y/%m/%d %H:%M:%S] "),$0} {fflush()}' >> ${MT_LOGDIR}/log_${USER}))

bash -i

exit

b. プロファイルに仕込みを入れる

対話型でSSHに入るときと、コマンド実行だけさせるときで、読み出されるプロファイルが変わります。
.bashrcであればどちらのケースでも読まれるらしいので、そこに仕込みを入れます。
入れる内容は以下の2つ。

b-1. exec &> を仕込んでおく

以下を実行することで、標準出力と標準エラー出力をteeに食わせます。
実装は以下を参考にさせていただきました。
https://zenn.dev/lovegorira/articles/62849db9f25012

$ cat ~/.bashrc
...
MT_LOGDIR=/var/log/sshlogs/
exec &> >(tee -a >(awk '{print strftime("[%Y/%m/%d %H:%M:%S] "),$0} {fflush()}' >> ${MT_LOGDIR}/log_${USER}))
...

teeの後がちょっとひねってあり、ログに書き出す前にawkで時刻を頭につけるようにしています。
また、&>にすることで、標準出力と標準エラーを両方拾っています。
エラーも拾っておきたいというよりは、、ターミナルの頭の「[user01@localhost ~]$」の部分が標準エラー出力になるようでして、それを拾いたかった、という方が強いです。

b-2. trapでコマンドが叩かれる度にログを出す関数を呼び出します。

以下を参考にさせていただきました。
https://www.beex-inc.com/blog/linuxbashhistory

コマンドの結果の表示は拾えないのですが、叩いたコマンドは拾えます。
b-1で情報は包含しきれているのですが、別の用途で拡張するときに使えそうなので、仕込んでおくことにします。

b-1,2を実装した.bashrc配下の通り。

$ cat ~/.bashrc
...

# User specific aliases and functions
MT_LOGDIR=/var/log/sshlogs/
function log_history {
  echo $(date) $$ $BASH_COMMAND >> ${MT_LOGDIR}/history_${USER}
}
readonly -f log_history
trap log_history DEBUG

exec &> >(tee -a >(awk '{print strftime("[%Y/%m/%d %H:%M:%S] "),$0} {fflush()}' >> ${MT_LOGDIR}/log_${USER}))

まとめ

とりあえずSSHで叩いたログが拾える状態になりましたが、ツールが叩く処理の中でリダイレクトをいじっている場合にb-1と干渉しないか?という感もあり。
軽く使ってみて様子を見てみようと思います。

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?