すべてのSSHコマンドのローカルタイムスタンプロギング?

すべてのSSHコマンドのローカルタイムスタンプロギング?

で使用されているすべてのリモートコマンドssh(を通じて起動されたコマンドラインopensshクライアント)のローカルタイムスタンプ履歴をどのように維持しますか?bash

必要:

  • 基本的な:

    • 100%クライアント側、サーバーのログ記録に依存しない
    • ユーザーが設定またはインストールすると、ログはユーザーのホームディレクトリに保存されます。
    • 異なるユーザーとホストとの複数の同時セッションの区別をサポートします。
    • 非侵害的(毎回有効にする必要はなく、SSHの使用を大幅に妨げない)
  • 高い優先順位:

    • 出力を記録しないか、可能であれば出力をフィルタリングします。
    • パスワードエントリが記録されていないか、ファイルが暗号化されています。
    • 実際に使用されたコマンドを示します(タブ/書き込み完了、バックスペース、CTRL+Cなど...が処理されました)。
  • 持ってもいい:

    • また、接続されたセッションのコマンドを記録します(リモートでsshまたはセッション中にsu <user>入力されたコマンド)。
    • セッションの開始と終了を記録する必要があります。
    • ルートではなく単純なbashベースソリューションが最適です(コマンドベースaliasまたはbashラッパースクリプトかもしれませんssh)。

私の技術レベル:

  • 私はプログラミングは初めてではありませんが、まだbash「Linux方式」を学んでいるので、簡単な説明を含むコード例をお寄せいただきありがとうございます。

考えられる戦略

  • キーロガー- 問題:タブ/記録が完了していないパスワードロギング(参照)グレンの答え)
  • screen毎秒ロールバックし、diffその間に新しいロールバック行を探します。- 質問:便利で自動化された方法でこれを達成するにはどうすればよいですか?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile)- 問題:リンクされたセッションで複数行のコマンドや履歴を処理できず、慎重にクリーンアップする必要があります(私の答えを参照)。
  • 上記の内容の一部を組み合わせたもの

一例

次のSSHセッション:

user@local:~$ ssh user@remote
Last login: Tue Jun 17 16:34:23 2014 from local
user@remote:~$ cd test
user@remote:~/test$ ls
a  b
user@remote:~/test$ exit

~/logs/ssh.log次のログが生成されることがあります。

2014-06-17 16:34:50   [user@remote - start]
2014-06-17 16:34:51   [user@remote] cd test
2014-06-17 16:34:52   [user@remote] ls
2014-06-17 16:34:53   [user@remote] exit
2014-06-17 16:34:53   [user@remote - end]

または、ファイルの上部からセッションを開始するために使用されるコマンドラインを使用して、各セッションに対して別々のログを生成することもできます。

答え1

私はあなたの質問に非常に興味があります。答えをしようとしませんでしたが、抜けました。

これはexpect実際にキーロガーです。

#!/usr/bin/expect -f

proc log {msg} {
    puts $::fh "[timestamp -format {%Y-%m-%d %H:%M:%S}]: $msg"
}

set ssh_host [lindex $argv 0]
set ::fh [open "sshlog.$ssh_host" a]

log "{session starts}"

spawn ssh $ssh_host

interact {
    -re "(.)" {
        set char $interact_out(1,string)
        if {$char eq "\r"} {
            log $keystrokes
            set keystrokes ""
        } else {
            append keystrokes $char
        }
        send -- $char
    }
    eof
}

log "{session ends}"

メモ:

  • 名前にsshターゲットが含まれているファイルに追加されます。
  • キーロガーです。 SSHキーをまだ設定していない場合は、ログファイルからユーザーパスワードを取得できます。
  • タブの完成により失敗します。ユーザーがコマンドを入力すると、uptTabログuptimeファイルに「uptime」ではなく「upt \ t」と表示されます。
  • 「生」モードで文字を取得します。ユーザーが入力に失敗した場合、^?ログファイルに多くのバックスペース文字が表示されます。

答え2

私は現在以下のbashスクリプトを使用しています。多くの問題がありますが、すべての要件、優先順位、および「良い点と悪い点」の側面(少なくともほとんどの場合)を満たす唯一のソリューションです。

この回答SSHセッションをローカルに記録するのがなぜそんなに難しいのかを話し合ってください。

これまでに見つけたスクリプトの問題:

  1. 複数行コマンドで問題が発生する可能性があります。

    • リモート履歴から複数行の項目をページに移動すると(上下のキーを使用)、最新のコマンドではなく履歴項目が記録されます。あなたはこれを避けることができますBash レコードから削除複数行コマンドは使用後すぐに実行されます。
    • 複数行コマンドの最初の行のみが記録されます。
  2. セッションを接続すると(リモート側sshまたはsuコマンドを使用)、実際に使用されたコマンドではなく、スクロールによって渡されたコマンドを記録するために履歴がスクロールされます。

  3. 正規表現は改善される可能性があり、特定の環境では修正する必要があるかもしれません。

    • cat -vクリーニング前に印刷されていない文字を変換してトリックを書きました。したがって、^[[コマンドに文字列を使用すると、ペイロードが削除される可能性があります。
    • たとえば、履歴をすばやく転送する場合は、コマンドの前に追加のレコード入力を受け取ることがあります。通常、実際のコマンドの前に「^ M」が表示されるため、必要に応じて削除できます。
    • 時々、異なる制御文字が表示されます。どんなものが取り除いても安全か分かるまで、今はすべてそのままにします。上記の^ Mは誤ったレコード入力を検出するのに役立ちます。^ Cはコマンドが中断されたかどうかを示します。
    • 特定のプロンプトに対してプロンプト正規表現を変更する必要があり、リモート環境によって制御文字パターンが異なる可能性があると想像できます。
  4. ホスト名などの SSH コマンドの bash 完了はありません。 sshこのスクリプトのエイリアスを with と指定すると、bash 完了を取得できます。alias ssh="sshlog"

スクリプトのソースとインストール:

インストールするには、次を ~/bin/sshlog に貼り付けて実行可能にします。を呼び出しますsshlog <ssh command options>。オプションで、ユーザーの .bashrc ファイルで「ssh」でエイリアスを指定します。

#!/bin/bash
# A wrapper for the ssh command that produces a timestamped log of all ssh commands
declare -r logfile=~/logs/ssh.log
declare -r description="sshlog-${$} ${@}"
declare -r TAB=$'\t'

logdir=`dirname ${logfile}`
[ -d ${logdir} ] || mkdir "${logdir}";

clean_control_chars() {
    while IFS= read -r line; do
        # remove KNOWN control characters. Leave the rest for now.
        # line=$(echo "${line}" | sed 's/\^\[\[K//g')  # unkown control character: ^[[K
        # line=$(echo "${line}" | sed 's/\^\[\[[0-9]\+[P]//g')  # these are generated by up/down completion - e.g. ^[[2P
        line=$(echo "${line}" | sed 's/\^\[\[[0-9]*[A-Z]//g')  # all other ^[[..
        # replay character deletions (backspaces)
        while [[ $(echo "${line}" | grep -E --color=never '.\^H') != "" ]]; do
            line=$(echo "${line}" | sed 's/.\^H//')
        done
        # remove common control characters
        line=$(echo "${line}" | sed 's/\^M$//')  # remove end of line marker from end
        line=$(echo "${line}" | sed 's/^\^G//g')  # remove start marker from start
        # remove ^G from other locations - possibly a good idea
        # line=$(echo "${line}" | sed 's/\^G//g')
        # remove all other control characters - not recommended (many like ^C and ^M indicate which section was processed/ ignored)
        # line=$(echo "${line}" | sed 's/\^[A-Z]//g')
        echo ${line};
    done
}

filter_output() {
    while IFS= read -r line; do
        # convert nonprinting characters and filter out non-prompt (in Ubuntu 14.04 tests, ^G indicates prompt start)
        line=$(echo "${line}" | cat -v | grep -Eo '[\^][G].*[\$#].*')
        [[ ${line} != "" ]] && echo "${line}"
    done
}

format_line() {
    while IFS= read -r line; do
        raw=${line};
        line=$(echo "${line}" | clean_control_chars);
        prompt=$(echo "${line}" | grep -Po '^.*?(\$|#)[\s]*')
        command=${line:${#prompt}}
        timestamp=`date +"%Y-%m-%d %H:%M:%S %z"`
        echo -e "${timestamp}${TAB}${description}${TAB}${prompt}${TAB}${command}"
    done
}

echo "Logging ssh session: ${description}"
echo "[START]" | format_line >> ${logfile}
/usr/bin/ssh "$@" | tee >(filter_output | format_line >> ${logfile})
echo "[END]" | format_line >> ${logfile}

ログコンテンツの例:

2014-06-29 23:04:06 -0700   sshlog-24176 remote [START]
2014-06-29 23:04:12 -0700   sshlog-24176 remote oleg@remote:~$  cd test
2014-06-29 23:04:13 -0700   sshlog-24176 remote oleg@remote:~/test$     ls
2014-06-29 23:04:14 -0700   sshlog-24176 remote oleg@remote:~/test$     exit
2014-06-29 23:04:14 -0700   sshlog-24176 remote [END]

答え3

どうですかstrace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)?これにより、すべてのSSHセッションが記録されます。ログを解析したり、grep等を使用するツールが必要な場合があります。awk

  • -f:ブランチされたサブアイテムの追跡
  • -ff:各子供を個別に記録します。ssh_log.PID
  • -s8192:文字列ロギングの制限を増やします(必要な場合)。
  • -T -ttt:エポック以降マイクロ秒表示(秒)
  • -p N: pidに追加N

答え4

あまり複雑ではない答えがあり、確かにキーロガーではありません。サーバーログとは無関係であることを理解していません(つまり、すべての操作はサーバー上で実行する必要があり、すべてのログはサーバー側のログです)。システム全体に渡すのが良いアイデアだと思いますbashrcプロンプトコマンド良い:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -t "$USER[$$] $SSH_CONNECTION")'

Debian では、/etc/bash.bashrc ファイルを編集する必要があります。 centos では、/etc/bashrc ファイルを編集する必要があります。

現在のセッション記録を開始するには、編集したファイルをインポートする必要があります。たとえば、次のようになります。


source /etc/bash.bashrc

Debian システムまたは


source /etc/bashrc
セントースシステムで。

これから、すべてのSSHセッションに対するすべてのコマンドがログインします。/var/log/システムログDebian システムでは/var/log/メッセージセントースシステムで。

別のファイルに書き込んで他のログファイルと混在させたくない場合は、次のようにします。


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
前の PROMPT_COMMAND 例ではなく、必要に応じて rsyslogd を設定します。

たとえば、Debianシステムで編集します。/etc/rsyslog.confファイル:変更行:


.;auth,authpriv.none           -/var/log/syslog
到着

.;auth,authpriv.none,local6           -/var/log/syslog
ファイルの末尾に次の行を追加します。

local6.info                     /var/log/history.log

次に、次を実行します。

touch /var/log/history.log && /etc/init.d/rsyslog restart

関連情報