Pencatatan semua perintah ssh lokal dan cap waktu?

12

Bagaimana saya bisa menyimpan catatan lokal, timestamped dari semua perintah jarak jauh yang saya gunakan ssh(klien openssh baris perintah dimulai melalui bash)?

Persyaratan:

  • Penting:

    • 100% sisi klien tanpa mengandalkan server logging
    • Dikonfigurasi atau diinstal per pengguna dengan log yang disimpan di direktori home pengguna.
    • Dukungan untuk membedakan antara beberapa sesi simultan dengan berbagai pengguna dan host.
    • Non-intrusif (tidak perlu mengaktifkannya setiap kali dan tidak mengganggu penggunaan ssh)
  • Prioritas utama:

    • Entah output tidak dicatat atau disaring sebanyak mungkin
    • Entri kata sandi tidak dicatat atau file dienkripsi
    • Mengindikasikan perintah aktual yang digunakan (setelah tab / riwayat selesai, backspaces, CTRL+ C, dll ... telah diproses)
  • Senang bisa memiliki:

    • Juga mencatat perintah dalam sesi berantai (perintah yang dimasukkan saat remote sshatau su <user>sesi)
    • Awal dan akhir sesi harus dicatat
    • Sebuah bashsolusi sederhana , non-root akan menjadi yang terbaik (mungkin skrip aliasatau bashpembungkus untuk sshperintah?)

Tingkat keahlian saya:

  • Saya bukan orang baru dalam pemrograman, tetapi saya masih belajar bashdan "Linux cara", jadi contoh kode dengan penjelasan singkat akan sangat dihargai.

Kemungkinan strategi

  • keylogger - Masalah: kata sandi log, tidak mencatat tab / penyelesaian sejarah (lihat jawaban glenn )
  • screendengan scrollback dumping sekali per detik dan di diffantara mereka untuk menemukan jalur scrollback baru - Masalah: bagaimana ini dapat diterapkan dengan cara otomatis yang bermanfaat?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile) - Masalah: tidak dapat menangani perintah atau riwayat multiline dalam sesi berantai, pembersihan yang cermat diperlukan (lihat jawaban saya)
  • Kombinasi beberapa hal di atas

Sebuah contoh

Sesi SSH berikut:

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

Mungkin menghasilkan log di ~/logs/ssh.logseperti:

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]

Atau, mungkin log terpisah akan dibuat untuk setiap sesi dengan baris perintah yang digunakan untuk memulai sesi di bagian atas file.

Oleg
sumber
Seharusnya juga menangani editor seperti nano atau vim
daisy

Jawaban:

4

Saya tertarik dengan pertanyaan Anda. Awalnya saya tidak akan memberikan jawaban tetapi saya ketagihan.

Ini menggunakan expectdan itu benar-benar kunci logger.

#!/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}"

Catatan:

  • itu ditambahkan ke file dengan tujuan ssh dalam nama
  • itu adalah logger kunci: jika Anda belum mengatur kunci ssh, Anda mendapatkan kata sandi pengguna dalam file log
  • itu digagalkan oleh penyelesaian tab: jika pengguna mengetik uptTab(untuk uptimeperintah), Anda akan mendapatkan "upt \ t" dalam file log, bukan "uptime"
  • itu mengambil karakter dalam mode "mentah": jika pengguna adalah pengetik yang buruk, Anda akan mendapatkan banyak ^?(karakter backspace) dalam file log.
glenn jackman
sumber
Terimakasih banyak atas jawaban Anda. Sangat menarik bahwa sepertinya tidak ada jawaban yang mudah untuk ini, mungkin asli untuk klien ssh. Terima kasih telah menjelaskan batasannya; Saya pikir penyelesaian tab / karakter backspace logging / kata sandi cukup untuk mencegah saya sering menggunakan ini. Itu juga membuat saya lebih memikirkan prioritas saya, dan saya akan mengklarifikasi mereka dalam pertanyaan.
Oleg
Output dari proses spawned dapat diurai untuk mengekstrak perintah yang Anda inginkan. Anda harus mengetahui permintaan pengguna untuk membuatnya lebih mudah.
glenn jackman
Saya banyak menggunakan tab completion. Bukankah ini berarti bahwa perintah-perintah itu tidak akan dicatat?
Oleg
Ah, aku mengerti apa yang kamu katakan. Bagaimana output diurai? Prompt dapat dimasukkan di suatu tempat sebagai opsi konfigurasi.
Oleg
Saya menambahkan daftar kemungkinan solusi di bagian bawah pertanyaan. ssh ... | tee -ai <logfile> berfungsi dengan baik untuk mencatat input dan output dengan aman, tapi saya tidak tahu bagaimana menambahkan cap waktu dan / atau memfilter output di latar belakang.
Oleg
2

Saat ini saya menggunakan skrip bash di bawah ini. Ini memiliki banyak masalah, tetapi itu adalah satu-satunya solusi yang saya temukan yang membahas semua persyaratan, prioritas, dan "baik untuk dimiliki" (setidaknya sebagian besar waktu).

Jawaban ini membahas mengapa mencatat sesi ssh secara lokal sangat sulit.

Masalah dengan skrip yang saya temukan sejauh ini:

  1. Perintah multiline menyebabkan masalah:

    • Jika Anda halaman melalui item multiline dalam sejarah jarak jauh (dengan tombol naik / turun), itu akan mencatat item sejarah bukannya perintah terbaru. Anda dapat menghindari ini dengan menghapus dari bash history perintah multiline segera setelah digunakan.
    • Hanya baris pertama dari perintah multiline yang dicatat.
  2. Sesi berantai (menggunakan sshatau superintah pada ujung jarak jauh) menyebabkan riwayat bergulir untuk merekam perintah yang berlalu digulir bukannya perintah yang sebenarnya digunakan

  3. Ekspresi reguler dapat ditingkatkan dan mungkin perlu dimodifikasi untuk lingkungan tertentu:

    • Saya menipu dengan mengubah karakter yang tidak tercetak dengan cat -vsebelum membersihkan. Akibatnya, konten yang valid dapat dihapus jika Anda pernah menggunakan string seperti ^[[dalam perintah Anda.
    • Kadang-kadang Anda mendapatkan input login ekstra sebelum perintah, seperti jika Anda menelusuri histori dengan sangat cepat. Ini biasanya diikuti oleh "^ M" sebelum perintah yang sebenarnya dan dengan demikian bisa dilucuti jika diinginkan.
    • Kadang-kadang karakter kontrol lain muncul. Saya meninggalkan mereka semua untuk saat ini sampai saya tahu mana yang aman untuk dihapus. ^ M seperti yang saya sebutkan berguna untuk mendeteksi input yang masuk tidak sah, dan ^ C akan memberi tahu Anda jika perintah dibatalkan.
    • Regex yang cepat mungkin perlu dimodifikasi untuk permintaan tertentu, dan saya bisa membayangkan bahwa lingkungan yang jauh berbeda mungkin memiliki pola karakter kontrol yang berbeda.
  4. Tidak ada penyelesaian perintah ssh bash, seperti untuk nama host. Anda bisa mendapatkan pesta selesai jika Anda alias script ini ke sshdenganalias ssh="sshlog"

Sumber dan instalasi skrip:

Untuk menginstal, rekatkan yang berikut ke ~ / bin / sshlog dan buat executable. Panggil dengan sshlog <ssh command options>. Secara opsional alias ke 'ssh' di file .bashrc pengguna.

#!/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}

Contoh konten log:

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]
Oleg
sumber
0

Saya memiliki jawaban yang tidak terlalu rumit, dan tentunya bukan keylogger. Saya tidak mengerti maksud Anda untuk menjadi server log independen (ini berarti bahwa semua tindakan harus diambil ke server dan semua log adalah log sisi server), dan dengan demikian saya pikir ide yang baik adalah meneruskan ke sistem bashrc lebar perintah prompt seperti:


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

Dalam debian Anda harus mengedit file: /etc/bash.bashrc dan dalam centos file: / etc / bashrc

Jika Anda ingin mulai masuk untuk sesi yang Anda ikuti, Anda harus sumber file yang telah Anda edit, misalnya jalankan:


source /etc/bash.bashrc

dalam sistem debian atau


source /etc/bashrc
dalam sistem centos.

Mulai sekarang, setiap perintah, dari setiap sesi ssh akan dicatat di / var / log / syslog pada sistem debian, dan di / var / log / messages di sistem centos.

Jika Anda ingin mencatatnya pada file terpisah dan tidak mengacaukan dengan file log lain yang dapat Anda gunakan:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
bukannya contoh PROMPT_COMMAND sebelumnya dan kemudian konfigurasikan rsyslogd sesuai kebutuhan.

Misalnya di Sistem Debian, edit file /etc/rsyslog.conf : ubah baris:


.;auth,authpriv.none           -/var/log/syslog
untuk

.;auth,authpriv.none,local6           -/var/log/syslog
dan tambahkan baris berikut ke akhir file:

local6.info                     /var/log/history.log

kemudian jalankan:

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

strimpak
sumber
Pertanyaan ini secara khusus mengenai masalah pendataan sesi ssh di sisi komputer inisiasi / lokal / klien, tanpa harus (ingat / diizinkan) untuk mengonfigurasi setiap server jarak jauh atau harus mengunduh log secara manual dari semua server jarak jauh yang Anda sambungkan. untuk. Saya pikir jawaban Anda, walaupun tidak menjawab pertanyaan ini, akan bermanfaat bagi seseorang yang tertarik untuk meningkatkan audit server mereka dan mungkin harus dipindahkan ke pertanyaan yang lebih relevan.
Oleg
0

Bagaimana dengan strace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)? Ini mencatat semua sesi ssh. Anda mungkin memerlukan alat untuk menguraikan log selanjutnya, atau hanya menggunakan grep, awkdll.

  • -f: melacak anak-anak bercabang dua
  • -ff: log setiap anak secara terpisah ke ssh_log.PID
  • -s8192: menambah batas logging string (jika perlu)
  • -T -ttt: stamping mikrodetik dalam hitungan detik sejak Zaman
  • -p N: lampirkan ke pid N
Anul
sumber