Bagaimana saya bisa mendeteksi jika shell dikontrol dari SSH?

69

Saya ingin mendeteksi dari skrip shell (lebih khusus. Zshrc) jika dikontrol melalui SSH. Saya mencoba variabel HOST tetapi selalu nama komputer yang menjalankan shell. Bisakah saya mengakses nama host tempat sesi SSH berasal? Membandingkan keduanya akan menyelesaikan masalah saya.

Setiap kali saya masuk ada pesan yang menyatakan waktu masuk dan host terakhir:

Last login: Fri Mar 18 23:07:28 CET 2011 from max on pts/1
Last login: Fri Mar 18 23:11:56 2011 from max

Ini berarti server memiliki informasi ini.

stribika
sumber

Jawaban:

90

Berikut adalah kriteria yang saya gunakan di ~/.profile:

  • Jika salah satu variabel SSH_CLIENTatau SSH_TTYdidefinisikan, ini adalah sesi ssh.
  • Jika nama proses induk shell login adalah sshd, ini adalah sesi ssh.
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
  SESSION_TYPE=remote/ssh
# many other tests omitted
else
  case $(ps -o comm= -p $PPID) in
    sshd|*/sshd) SESSION_TYPE=remote/ssh;;
  esac
fi

(Mengapa Anda ingin menguji ini dalam konfigurasi shell Anda daripada memulai sesi Anda?)

Gilles 'SANGAT berhenti menjadi jahat'
sumber
3
Terima kasih banyak! github.com/balupton/dotfiles/commit/…
balupton
1
Anda mungkin ingin melakukan ini dalam konfigurasi shell Anda jika Anda ingin mengaktifkan ssh agent forwarding dari remote shell Anda (karena vars lingkungan perlu diatur di setiap shell yang ingin Anda teruskan) kecuali saya kehilangan sesuatu?
underrun
@underrun Saya tidak mengerti maksud Anda. Jika Anda menjalankan shell lain di sesi yang sama, itu mewarisi variabel lingkungan yang ditetapkan oleh .profile. Dan apa hubungannya dengan penerusan agen?
Gilles 'SO- berhenti menjadi jahat'
1
@underrun Jika Anda ingin menguji keberadaan penerusan agen SSH, uji untuk SSH_AUTH_SOCKvariabel. Tetapi mengapa Anda menjalankan agen SSH dalam kasus itu? Apakah maksud Anda memulai agen jika Anda masuk tanpa penerusan agen? Mengapa tidak memulai agen jika belum ada satu ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Gilles 'SANGAT berhenti menjadi jahat'
1
@Praxeolitic SSH_*Variabel juga diatur dalam subproses dari shell yang ada di kepala sesi SSH, misalnya jika Anda memulai sesi layar melalui SSH (Anda harus menghapus variabel sebelum memulai sesi jika Anda peduli). Saya pikir alasan untuk menguji proses induk adalah bahwa saya mulai melakukan itu sebelum sshd mendefinisikan variabel lingkungan apa pun.
Gilles 'SO- berhenti bersikap jahat'
21

Anda harus dapat memeriksa melalui SSH_TTY, SSH_CONNECTIONatau SSH_CLIENTvariabel.

Cakemox
sumber
1
Juga tambahkan ini ke env_keepdalam sudoersuntuk membuatnya bekerja melintasi superintah :)
Thomas G.
10

Saya baru saja mengalami masalah yang sama di Linux, menggunakan Bash. Saya pertama kali menggunakan variabel lingkungan SSH_CONNECTION, tetapi kemudian menyadari bahwa itu tidak disetel jika Anda su -.

Solusi lastlog di atas tidak berfungsi baik setelah suatau su -.

Akhirnya, saya menggunakan who am i, yang menunjukkan IP jarak jauh (atau nama host) pada akhirnya jika itu koneksi SSH. Ini juga berfungsi setelah su.

Menggunakan ekspresi reguler Bash, ini berfungsi:

if [[ $(who am i) =~ \([-a-zA-Z0-9\.]+\)$ ]] ; then echo SSH; else echo no; fi

Jika zsh tidak mendukung ekspresi reguler, hal yang sama dapat dicapai dengan berbagai cara dengan grep, cut, sed, atau apa pun.

Bagi yang penasaran, di bawah ini saya gunakan untuk apa, di root .bashrc:

    # We don't allow root login over ssh.
    # To enable root X forwarding if we are logged in over SSH, 
    # use the .Xauthority file of the user who did su

    w=$(who am i)
    if [[ $w =~ \([-a-zA-Z0-9\.]+\)$ ]] ; then
        olduser=${w/ .*/}
        oldhome=$(getent passwd $olduser | cut -d: -f 6)
        [ -f "$oldhome/.Xauthority" ] \
          && export XAUTHORITY=$oldhome/.Xauthority
    fi

Alternatif yang juga berfungsi suadalah mencari secara rekursif sshdmelalui proses induk:

#!/bin/bash

function is_ssh() {
  p=${1:-$PPID}
  read pid name x ppid y < <( cat /proc/$p/stat )
  # or: read pid name ppid < <(ps -o pid= -o comm= -o ppid= -p $p) 
  [[ "$name" =~ sshd ]] && { echo "Is SSH : $pid $name"; return 0; }
  [ "$ppid" -le 1 ]     && { echo "Adam is $pid $name";  return 1; }
  is_ssh $ppid
}

is_ssh $PPID
exit $?

Jika fungsi ditambahkan ke .bashrc, ini dapat digunakan sebagai if is_ssh; then ...

mivk
sumber
1
tidak berfungsi dalam tmuxsesi jarak jauh dan juga memiliki masalah jika masuk melalui IPv6 dan tidak ada nama terbalik DNS.
bene
@ Ben: apa yang tidak berhasil? Ekspresi reguler, atau who am itidak menunjukkan alamat IPv6 Anda?
mivk
1) who am itidak mengembalikan apa pun dalam tmuxsesi jarak jauh . 2) Alamat IPv6 mungkin berisi titik dua yang tidak diizinkan oleh regex Anda. Ini mungkin sulit karena who am imengandung (:0.0)sesi X untuk saya (xterm).
bene
@ Ben: Solusi alternatif yang baru saja saya tambahkan juga harus bekerja dengan IPv6. Saya tidak tahu tentang tmux, tetapi itu juga berfungsi screen.
mivk
7

Saya pikir jawaban Gilles dan Cakemox baik, tetapi hanya untuk kelengkapan ...

Last login: Fri Mar 18 23:07:28 CET 2011 from max on pts/1

berasal dari pam_lastlog1 .

Anda dapat mencetak pam_lastloginformasi menggunakan perintah lastlog2 , mis

$ lastlog -u mikel  
Username         Port     From             Latest
mikel            tty1                      Fri Jan 28 10:58:10 +1100 2011

untuk login lokal, dibandingkan dengan

Username         Port     From             Latest
mikel            pts/9    mikel-laptop     Sat Mar 19 11:11:58 +1100 2011

untuk login SSH.

Di sistem saya, ini berfungsi untuk mengekstraknya

$ lastlog -u mikel | sed -ne '2{p;q}' | cut -c 27-42
mikel-laptop 

lastdan wbisa membantu juga, misalnya

$ TTY=$(tty)
$ last -n 1 ${TTY#/dev/} | sed -ne '1{p;q}'
mikel    pts/12       :0.0             Sat Mar 19 11:29   still logged in 


1 dokumentasi Linux / FreeBSD untuk pam_lastlog.
2 halaman manual Linux / FreeBSD lastlog(8) .

Mikel
sumber
1

Mulailah dengan melihat lingkungan Anda dan menemukan opsi yang tepat

printenv|grep SSH
SSH_CLIENT=192.168.1.xxx
SSH_CONNECTION=192.168.1.xxx
SSH_TTY=/dev/ttys021

Anda bisa menghubungkan ke banyak variabel lingkungan ini untuk memicu tindakan spesifik berdasarkan keberadaannya.

lfender6445
sumber
-1

Ini untuk memeriksa semua koneksi yang dibuat dari pengguna lain menggunakan SSH

netstat | grep ssh
ARD
sumber
Ini sama sekali tidak bisa diandalkan.
DannyNiu