การบันทึกโลคัลของคำสั่ง ssh ทั้งหมดแบบโลคัล?


12

ฉันจะเก็บบันทึกโลคัลที่บันทึกเวลาของคำสั่งรีโมตทั้งหมดที่ฉันใช้ในssh(ไคลเอ็นต์ openssh บรรทัดคำสั่งเริ่มต้นผ่านbash) ได้อย่างไร?

ที่ต้องการ:

  • ที่สำคัญ:

    • ฝั่งไคลเอ็นต์ 100% โดยไม่ต้องอาศัยการบันทึกเซิร์ฟเวอร์
    • กำหนดค่าหรือติดตั้งต่อผู้ใช้พร้อมบันทึกที่จัดเก็บในโฮมไดเรกทอรีของผู้ใช้
    • การสนับสนุนสำหรับการแยกความแตกต่างระหว่างหลายเซสชันพร้อมกันกับผู้ใช้และโฮสต์ที่หลากหลาย
    • ไม่รบกวน (ไม่จำเป็นต้องเปิดใช้งานในแต่ละครั้งและไม่รบกวนการใช้ ssh อย่างมีนัยสำคัญ)
  • ลำดับความสำคัญสูง:

    • เอาต์พุตไม่ถูกล็อกหรือกรองออกให้มากที่สุด
    • รายการรหัสผ่านอย่างใดอย่างหนึ่งจะไม่ถูกบันทึกหรือไฟล์ถูกเข้ารหัส
    • บ่งชี้ถึงคำสั่งจริงที่ใช้ (หลังจากแท็บ / ประวัติเสร็จสมบูรณ์, backspaces, CTRL+ C, ฯลฯ ... ถูกประมวลผลแล้ว)
  • ยินดีที่ได้:

    • ยังบันทึกคำสั่งในเซสชันที่ถูกล่ามโซ่ (คำสั่งที่ป้อนระหว่างระยะไกลsshหรือsu <user>เซสชัน)
    • ควรเริ่มต้นเซสชันและสิ้นสุดเซสชัน
    • ง่ายbash-based, การแก้ปัญหาที่ไม่ใช่รากจะดีที่สุด (บางทีอาจจะเป็นaliasหรือbashสคริปต์เสื้อคลุมสำหรับsshคำสั่ง?)

ระดับความสามารถของฉัน:

  • ฉันไม่ได้ใหม่กับการเขียนโปรแกรม แต่ยังคงเรียนรู้bashและ "วิธี Linux" ดังนั้นตัวอย่างโค้ดที่มีคำอธิบายสั้น ๆ จะได้รับการชื่นชมมากที่สุด

กลยุทธ์ที่เป็นไปได้

  • keylogger - ปัญหา: บันทึกรหัสผ่านไม่บันทึกแท็บ / เสร็จสิ้นประวัติ (ดูคำตอบของ glenn )
  • 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]

หรืออาจมีการสร้างบันทึกแยกต่างหากสำหรับแต่ละเซสชันด้วยบรรทัดคำสั่งที่ใช้ในการเริ่มเซสชันที่ด้านบนของไฟล์


นอกจากนี้ยังควรจัดการกับบรรณาธิการเช่น nano หรือ vim
daisy

คำตอบ:


4

ฉันรู้สึกทึ่งกับคำถามของคุณ เดิมทีฉันไม่ได้ให้คำตอบ แต่ฉันถูกตะขอ

สิ่งนี้ใช้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คำสั่ง) คุณจะได้รับ "upt \ t" ในไฟล์บันทึกไม่ใช่ "สถานะการทำงาน"
  • มันคว้าตัวละครในโหมด "raw": หากผู้ใช้พิมพ์ดีดไม่ดีคุณจะได้รับจำนวนมาก^?(อักขระถอยกลับ) ในล็อกไฟล์

ขอบคุณมากสำหรับคำตอบของคุณ. เป็นที่น่าสนใจที่ดูเหมือนจะไม่มีคำตอบที่ง่ายสำหรับสิ่งนี้บางทีอาจเป็นลูกค้าของ ssh ขอบคุณสำหรับการอธิบายข้อ จำกัด ฉันคิดว่าการบันทึกอักขระในแท็บเสร็จ / ถอยกลับ / การบันทึกรหัสผ่านนั้นเพียงพอที่จะป้องกันไม่ให้ฉันใช้สิ่งนี้บ่อยครั้ง มันทำให้ฉันคิดเกี่ยวกับการจัดลำดับความสำคัญของฉันมากขึ้นและฉันจะอธิบายให้ชัดเจนในคำถาม
Oleg

เอาต์พุตจากกระบวนการ spawned สามารถแยกวิเคราะห์เพื่อแยกคำสั่งที่คุณต้องการ คุณจะต้องรู้คำแนะนำของผู้ใช้เพื่อให้ง่ายขึ้น
เกล็นแจ็คแมน

ฉันใช้ความสมบูรณ์ของแท็บมาก นี่ไม่ได้หมายความว่าคำสั่งเหล่านั้นจะไม่ถูกบันทึก?
Oleg

อาฉันเห็นสิ่งที่คุณพูด จะแยกวิเคราะห์ผลลัพธ์ได้อย่างไร สามารถป้อนพรอมต์บางแห่งเป็นตัวเลือกการกำหนดค่า
Oleg

ฉันเพิ่มรายการโซลูชันที่เป็นไปได้ที่ด้านล่างของคำถาม ssh ... | tee -ai <logfile> ทำงานได้ดีในการบันทึกอินพุตและเอาต์พุตอย่างปลอดภัย แต่ฉันไม่ทราบวิธีเพิ่มการประทับเวลาและ / หรือกรองเอาต์พุตในพื้นหลัง
Oleg

2

ฉันกำลังใช้สคริปต์ทุบตีด้านล่าง มันมีปัญหามากมาย แต่มันเป็นทางออกเดียวที่ฉันได้พบว่าตอบสนองความต้องการลำดับความสำคัญและ "ยินดีที่ได้พบ" (อย่างน้อยเกือบตลอดเวลา)

คำตอบนี้กล่าวถึงสาเหตุที่เซสชันการบันทึก ssh ภายในเครื่องนั้นยากมาก

ปัญหาเกี่ยวกับสคริปต์ที่ฉันพบ:

  1. คำสั่งหลายบรรทัดทำให้เกิดปัญหา:

    • หากคุณเลื่อนดูรายการหลายบรรทัดในประวัติระยะไกล (ด้วยปุ่มขึ้น / ลง) รายการนั้นจะบันทึกรายการประวัติแทนคำสั่งล่าสุด คุณสามารถหลีกเลี่ยงสิ่งนี้ได้โดยการลบจากประวัติทุบตีคำสั่งหลายบรรทัดทันทีหลังจากใช้
    • บันทึกบรรทัดแรกของคำสั่งหลายบรรทัดเท่านั้น
  2. เซสชันที่ถูกล่ามโซ่ (การใช้sshหรือsuคำสั่งที่ปลายทางระยะไกล) ทำให้เกิดการเลื่อนประวัติเพื่อบันทึกคำสั่งการเลื่อนผ่านแทนที่จะใช้คำสั่งจริง

  3. นิพจน์ทั่วไปสามารถปรับปรุงได้และอาจต้องแก้ไขสำหรับสภาพแวดล้อมบางอย่าง:

    • ฉันโกงโดยแปลงอักขระที่ไม่พิมพ์ออกcat -vมาก่อนทำความสะอาด ดังนั้นเนื้อหาที่ถูกต้องอาจถูกลบหากคุณเคยใช้สตริงเหมือน^[[ในคำสั่งของคุณ
    • บางครั้งคุณได้รับอินพุตที่เพิ่มเข้ามาก่อนคำสั่งเช่นถ้าคุณเลื่อนดูประวัติอย่างรวดเร็ว โดยทั่วไปแล้วตามด้วย "^ M" ก่อนคำสั่งจริงและอาจถูกถอดออกได้หากต้องการ
    • อักขระควบคุมอื่น ๆ เกิดขึ้นในบางครั้ง ฉันจะปล่อยพวกเขาทั้งหมดในตอนนี้จนกว่าฉันจะรู้ว่าปลอดภัยที่จะลบ ^ M ตามที่ฉันเพิ่งกล่าวถึงมีประโยชน์ในการตรวจสอบอินพุตที่ไม่ถูกต้องและ ^ C จะบอกคุณว่าคำสั่งถูกยกเลิก
    • พรอมต์ regex อาจต้องได้รับการแก้ไขสำหรับพรอมต์เฉพาะและฉันคิดว่าสภาพแวดล้อมระยะไกลที่แตกต่างกันอาจมีรูปแบบอักขระควบคุมที่แตกต่างกัน
  4. ไม่มีคำสั่ง bsh ที่ทำให้เสร็จสมบูรณ์เช่นชื่อโฮสต์ คุณจะได้รับการเสร็จสิ้นทุบตีถ้าคุณนามแฝงสคริปต์นี้sshด้วยalias ssh="sshlog"

แหล่งสคริปต์และการติดตั้ง:

หากต้องการติดตั้งให้วางสิ่งต่อไปนี้ลงใน ~ / bin / sshlog และทำให้สามารถเรียกใช้งานได้ sshlog <ssh command options>โทรหา เลือกที่จะใช้นามแฝงเป็น 'ssh' ในไฟล์. bashrc ของผู้ใช้

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

0

ฉันมีคำตอบที่ซับซ้อนน้อยกว่าและไม่ใช่ keylogger ฉันไม่ได้รับจุดของการบันทึกเซิร์ฟเวอร์ที่เป็นอิสระ (ซึ่งหมายความว่าการกระทำทั้งหมดจะต้องดำเนินการไปยังเซิร์ฟเวอร์และบันทึกทั้งหมดเป็นบันทึกด้านเซิร์ฟเวอร์) และดังนั้นฉันคิดว่าเป็นความคิดที่ดีคือการส่งผ่านไปยังระบบกว้าง bashrc คำสั่งให้เช่น:


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

ในเดเบียนคุณควรแก้ไขไฟล์: /etc/bash.bashrc และใน centos ไฟล์: / etc / bashrc

หากคุณต้องการเริ่มการบันทึกสำหรับเซสชันที่คุณอยู่คุณต้องระบุไฟล์ที่คุณแก้ไขตัวอย่างเช่นเรียกใช้งาน:


source /etc/bash.bashrc

ในระบบเดเบียนหรือ


source /etc/bashrc
ในระบบ centos

จากนี้ไปทุกคำสั่งของทุกเซสชัน ssh จะถูกบันทึกไว้ที่/ var / log / syslogบนระบบเดเบียนและที่/ var / log / ข้อความบนระบบ centos

ในกรณีที่คุณต้องการบันทึกไว้ในไฟล์แยกต่างหากและไม่ยุ่งกับไฟล์บันทึกอื่น ๆ ที่คุณสามารถใช้:


PROMPT_COMMAND='history -a >(tee -a ~/.bash_history | logger -p local6.info -t "$USER[$$] $SSH_CONNECTION")'
แทนที่จะเป็นตัวอย่าง PROMPT_COMMAND ก่อนหน้าจากนั้นกำหนดค่า rsyslogd ตามต้องการ

ตัวอย่างเช่นที่ Debian System ให้แก้ไขไฟล์/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


คำถามนี้เกี่ยวกับปัญหาของการบันทึกเซสชัน ssh ที่ด้านข้างของคอมพิวเตอร์เริ่มต้น / โลคัล / ไคลเอนต์โดยไม่จำเป็นต้อง (จำ / อนุญาต) เพื่อกำหนดค่าเซิร์ฟเวอร์ระยะไกลแต่ละเครื่องหรือต้องดาวน์โหลดบันทึกจากเซิร์ฟเวอร์ระยะไกลทั้งหมดที่คุณเชื่อมต่อด้วยตนเอง ถึง. ฉันคิดว่าคำตอบของคุณในขณะที่มันไม่ตอบคำถามนี้จะเป็นประโยชน์กับคนที่สนใจในการปรับปรุงการตรวจสอบเซิร์ฟเวอร์ของพวกเขาและอาจถูกย้ายไปคำถามที่เกี่ยวข้องมากขึ้น
Oleg

0

แล้วไง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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.