Tüm ssh komutlarının yerel, zaman damgalı günlüğü?


13

sshİçinde kullandığım tüm uzak komutların yerel, zaman damgalı kaydını nasıl tutabilirim (komut satırı openssh istemcisi başladı bash)?

Gereksinimler:

  • esansiyel:

    • Sunucu günlüğüne güvenmeden% 100 istemci tarafı
    • Kullanıcının ana dizininde depolanan günlüklerle kullanıcı başına yapılandırılmış veya yüklenmiş.
    • Çeşitli kullanıcılar ve ana bilgisayarlarla aynı anda birden çok oturum arasında ayrım yapma desteği.
    • Müdahaleci olmayan (her seferinde etkinleştirmeye gerek yoktur ve ssh kullanımına önemli ölçüde müdahale etmez)
  • Yüksek öncelik:

    • Çıktılar mümkün olduğunca günlüğe kaydedilmez veya filtrelenmez
    • Parola girişleri günlüğe kaydedilmez veya dosya şifrelenir
    • Kullanılan gerçek komutları gösterir (sekme / geçmiş tamamlama, geri boşluklar, CTRL+ C, vb. İşlendikten sonra )
  • Olması güzel:

    • Ayrıca zincirleme oturumlardaki komutları günlüğe kaydeder (uzak sshveya su <user>oturumlar sırasında girilen komutlar )
    • Oturum başlangıcı ve bitişi günlüğe yazılmalıdır
    • Basit bashtabanlı, kök olmayan bir çözüm en iyisidir (belki de komut için bir aliasveya bashsarıcı komut dosyası ssh?)

Beceri seviyem:

  • Programlamaya yeni değilim, ama hala öğreniyorum bashve "Linux yolu", bu yüzden kısa açıklamalar ile kod örnekleri çok takdir edilecektir.

Olası stratejiler

  • keylogger - Sorun: şifreleri günlüğe kaydeder, sekmeyi / geçmiş tamamlamayı günlüğe kaydetmez ( glenn'in cevabına bakın )
  • screensaniyede bir kez ve diffyeni kaydırma çizgileri bulmak için aralarında boşaltma boşaltma ile - Sorun: Bu yararlı bir otomatik şekilde nasıl uygulanabilir?
  • ssh "$@" | tee >(some_cleaner_function >> $logfile) - Sorun: Zincirli oturumlarda çok satırlı komutları veya geçmişi işleyemiyor, dikkatli bir şekilde temizlenmesi gerekiyor (cevabıma bakın)
  • Yukarıdakilerin bazılarının kombinasyonu

Bir örnek

Aşağıdaki SSH oturumu:

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

Aşağıdaki ~/logs/ssh.loggibi bir günlüğe neden olabilir :

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]

Veya, her oturum için dosyanın üst kısmında oturumu başlatmak için kullanılan komut satırı ile ayrı bir günlük oluşturulur.


Ayrıca nano veya vim gibi düzenleyicileri işlemesi gerektiğini
papatya

Yanıtlar:


5

Sorunuz ilgimi çekti. Aslında cevap vermeyecektim ama bağlandım.

Bu kullanır expectve gerçekten bir anahtar kaydedici.

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

Notlar:

  • adında ssh hedefi olan bir dosyaya eklenir
  • bu bir tuş kaydedicidir: ssh tuşlarını ayarlamadıysanız, günlük dosyasında kullanıcının şifresini alırsınız
  • sekme tamamlandığında başarısız olur: kullanıcı uptTab( uptimekomut için) yazarsa, günlük dosyasında "uptime" değil "upt \ t" alırsınız
  • karakterleri "raw" modunda tutar: kullanıcı kötü bir daktilo ^?ise, günlük dosyasında çok sayıda (geri karakteri) alırsınız .

Cevabınız için çok teşekkür ederim. Bunun için kolay bir cevap olmadığı, belki de ssh istemcisine özgü olduğu ilginç. Sınırlamaları açıkladığınız için teşekkür ederiz; Sekme tamamlama / geri alma karakter günlüğü / parola günlüğü bu sık sık kullanmamı önlemek için yeterli olduğunu düşünüyorum. Aynı zamanda önceliklerim hakkında daha fazla düşünmemi sağladı ve sorudakileri açıklığa kavuşturacağım.
Oleg

Ortaya çıkan işlemden çıktı istediğiniz komutu ayıklamak için ayrıştırılabilir. Bunu kolaylaştırmak için kullanıcının istemini bilmeniz gerekir.
glenn jackman

Sekme tamamlamayı çok kullanıyorum. Bu, bu komutların kaydedilmeyeceği anlamına gelmiyor mu?
Oleg

Ne dediğini anlıyorum. Çıktı nasıl ayrıştırılır? Bilgi istemi bir yere yapılandırma seçeneği olarak girilebilir.
Oleg

Sorunun sonuna olası çözümler listesini ekledim. ssh ... | tee -ai <logfile> giriş ve çıkışı güvenli bir şekilde günlüğe kaydetmek için iyi çalışır, ancak arka planda zaman damgaları ve / veya çıkışı filtrelemeyi bilmiyorum.
Oleg

3

Şu anda aşağıdaki bash betiğini kullanıyorum. Birçok problemi var, ama tüm gereksinimleri, öncelikleri ve "güzellerimiz var" (en azından çoğu zaman) ile ilgili bulduğum tek çözüm.

Bu cevap ssh oturumlarını yerel olarak kaydetmenin neden bu kadar zor olduğunu tartışıyor.

Şu ana kadar bulduğum senaryo ile ilgili sorunlar:

  1. Çok satırlı komutlar sorunlara neden olur:

    • Uzak geçmişte (yukarı / aşağı tuşlarıyla) çok satırlı bir öğeyle sayfa açarsanız, en son komut yerine bir geçmiş öğesini günlüğe kaydeder. Herhangi bir çok satırlı komutu kullanıldıktan hemen sonra bash geçmişinden silerek bunu önleyebilirsiniz .
    • Çok satırlı komutların yalnızca ilk satırı günlüğe kaydedilir.
  2. Zincirleme oturumlar ( uzak uçta sshveya sukomutlarını kullanarak ), geçmiş kaydırmanın kullanılan gerçek komutlar yerine kaydırılan komutları kaydetmesine neden olur

  3. Normal ifadeler geliştirilebilir ve belirli ortamlar için değiştirilmesi gerekebilir:

    • cat -vTemizlemeden önce yazdırılmayan karakterleri dönüştürerek hile yapıyorum . Sonuç olarak, ^[[komutlarınızda olduğu gibi dizeleri kullanırsanız geçerli içerik kaldırılabilir .
    • Bazen, geçmişten çok hızlı sayfa geçtiğiniz gibi, komuttan önce ekstra günlüğe giriş alırsınız. Bunu genellikle gerçek komuttan önce bir "^ M" izler ve böylece istenirse sökülebilir.
    • Diğer kontrol karakterleri bazen ortaya çıkabilir. Hangisini kaldırmanın güvenli olduğunu öğreninceye kadar hepsini şimdilik bırakıyorum. ^ Dediğim gibi, geçersiz günlük girişini tespit etmek için kullanışlıdır ve ^ C komutun iptal edilip edilmediğini size söyleyecektir.
    • İstemi normal ifadesinin belirli istemler için değiştirilmesi gerekebilir ve farklı uzak ortamların farklı denetim karakteri düzenlerine sahip olabileceğini hayal edebilirim.
  4. Ana bilgisayar adı gibi ssh komutu bash tamamlama yok. Eğer bu senaryoyu diğer ad varsa bash tamamlanması alabilirsiniz sshilealias ssh="sshlog"

Komut dosyası kaynağı ve kurulumu:

Yüklemek için aşağıdakileri ~ / bin / sshlog dosyasına yapıştırın ve yürütülebilir yapın. İle arayın sshlog <ssh command options>. İsteğe bağlı olarak kullanıcının .bashrc dosyasındaki 'ssh' için diğer ad.

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

Örnek günlük içeriği:

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]

0

Daha az karmaşık bir cevabım var ve kesinlikle bir keylogger değil. Sunucu günlüğü bağımsız olma noktasını almıyorum (bu, tüm eylemlerin sunucuya alınması gerektiği ve tüm günlüklerin sunucu tarafı günlükleri olduğu anlamına gelir) ve bu nedenle iyi bir fikrin sistem geniş bashrc'ye geçmek olduğunu düşündüm gibi bir komut istemi:


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

Debian dilinde: /etc/bash.bashrc dosyasını ve centos'ta: / etc / bashrc dosyasını düzenlemelisiniz.

Bulunduğunuz oturum için günlüğe kaydetmeye başlamak istiyorsanız, düzenlediğiniz dosyayı kaynaklamanız gerekir, örneğin yürütün:


source /etc/bash.bashrc

debian sistemde veya


source /etc/bashrc
bir centos sisteminde.

Şu andan itibaren her ssh oturumunun her komutu, bir debian sistemdeki / var / log / syslog'a ve bir centos sistemindeki / var / log / messages dizinine kaydedilecektir.

Bunları ayrı bir dosyaya kaydetmek ve diğer günlük dosyalarıyla uğraşmak istemiyorsanız:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
önceki PROMPT_COMMAND örneği yerine rsyslogd dosyasını gerektiği gibi yapılandırın.

Örneğin bir Debian Sisteminde /etc/rsyslog.conf dosyasını düzenleyin : satırı değiştirin:


.;auth,authpriv.none           -/var/log/syslog
için

.;auth,authpriv.none,local6           -/var/log/syslog
ve dosyanın sonuna aşağıdaki satırı ekleyin:

local6.info                     /var/log/history.log

sonra yürütün:

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


Bu soru özellikle, her bir uzak sunucuyu yapılandırmaya (hatırla / izin ver) veya günlükleri bağladığınız tüm uzak sunuculardan manuel olarak indirmeye gerek kalmadan, başlatma / yerel / istemci bilgisayarın yanındaki ssh oturumlarının günlüğe kaydedilmesi sorunuyla ilgilidir. için. Cevabınız bu soruyu cevaplamasa da, sunucularının denetimini geliştirmekle ilgilenen biri için yararlı olacağını ve belki de daha alakalı bir soruya taşınması gerektiğini düşünüyorum.
Oleg

0

Nasıl strace -o /tmp/ssh_log -ff -s8192 -T -ttt -fp $(pidof sshd)? Bu tüm ssh oturumlarını günlüğe kaydeder. Bir sonradan günlüğü ayrıştırmak için aracı, ya da sadece kullanımını gerekebilir grep, awkvb

  • -f: çatallı çocukların izini sürmek
  • -ff: her çocuğu ayrı ayrı ssh_log.PID
  • -s8192: dize günlüğü sınırını artır (gerekirse)
  • -T -ttt: Dönemden bu yana saniyeler içinde mikrosaniye damgalama
  • -p N: pideye ekle N
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.