Làm cách nào tôi có thể phát hiện nếu shell được điều khiển từ SSH?


69

Tôi muốn phát hiện từ tập lệnh shell (cụ thể hơn .zshrc) nếu nó được điều khiển thông qua SSH. Tôi đã thử biến HOST nhưng nó luôn là tên của máy tính đang chạy shell. Tôi có thể truy cập tên máy chủ nơi phiên SSH đến không? So sánh hai sẽ giải quyết vấn đề của tôi.

Mỗi lần tôi đăng nhập, có một thông báo cho biết lần đăng nhập cuối cùng và máy chủ lưu trữ:

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

Điều này có nghĩa là máy chủ có thông tin này.

Câu trả lời:


90

Dưới đây là các tiêu chí tôi sử dụng trong ~/.profile:

  • Nếu một trong các biến SSH_CLIENThoặc SSH_TTYđược xác định, đó là phiên ssh.
  • Nếu tên tiến trình cha của shell đăng nhập là sshd, thì đó là phiên 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

(Tại sao bạn muốn kiểm tra điều này trong cấu hình shell thay vì khởi động phiên của bạn?)


3
Làm việc rất cảm ơn! github.com/balupton/dotfiles/commit/ từ
balupton

1
bạn có thể muốn thực hiện việc này trong cấu hình shell của mình nếu bạn muốn bật chuyển tiếp tác nhân ssh từ shell từ xa (vì các vars môi trường cần được đặt trong mỗi shell bạn muốn chuyển tiếp) trừ khi tôi thiếu thứ gì đó?
underrun

@underrun Tôi không hiểu quan điểm của bạn. Nếu bạn chạy shell khác trong cùng một phiên, nó sẽ kế thừa các biến môi trường được đặt bởi .profile. Và điều này có liên quan gì đến việc chuyển tiếp đại lý?
Gilles

1
@underrun Nếu bạn muốn kiểm tra sự hiện diện của chuyển tiếp tác nhân SSH, hãy kiểm tra SSH_AUTH_SOCKbiến. Nhưng tại sao bạn lại chạy một tác nhân SSH trong trường hợp đó? Ý bạn là bắt đầu một đại lý nếu bạn đăng nhập mà không chuyển tiếp đại lý? Tại sao không bắt đầu một tác nhân nếu chưa có một ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Gilles

1
@Praxeolitic Các SSH_*biến cũng được đặt trong các quy trình con của trình bao ở đầu phiên SSH, ví dụ: nếu bạn bắt đầu phiên màn hình qua SSH (bạn nên bỏ đặt các biến trước khi bắt đầu phiên nếu bạn quan tâm). Tôi nghĩ lý do để kiểm tra tiến trình cha là vì tôi đã bắt đầu làm điều đó trước khi sshd xác định bất kỳ biến môi trường nào.
Gilles

21

Bạn sẽ có thể kiểm tra thông qua SSH_TTY, SSH_CONNECTIONhoặc SSH_CLIENTbiến.


1
Đồng thời thêm chúng env_keepvào sudoersđể làm cho nó hoạt động trên sucác lệnh :)
Thomas G.

10

Tôi chỉ gặp vấn đề tương tự trong Linux, sử dụng Bash. Lần đầu tiên tôi sử dụng biến môi trường SSH_CONNECTION, nhưng sau đó nhận ra rằng nó không được đặt nếu bạn su -.

Giải pháp Lastlog ở trên không hoạt động sau suhoặc su -.

Cuối cùng, tôi đang sử dụng who am i, hiển thị IP từ xa (hoặc tên máy chủ) ở cuối nếu đó là kết nối SSH. Nó cũng hoạt động sau khi su.

Sử dụng biểu thức chính quy Bash, công việc này:

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

Nếu zsh không hỗ trợ các biểu thức chính quy, điều tương tự có thể đạt được theo nhiều cách khác nhau với grep, cut, sed hoặc bất cứ điều gì.

Đối với người tò mò, bên dưới là những gì tôi sử dụng này cho, trong .bashrc của root:

    # 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

Một thay thế cũng hoạt động với susẽ là tìm kiếm đệ quy sshdthông qua các quy trình cha:

#!/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 $?

Nếu hàm được thêm vào .bashrc, nó có thể được sử dụng như if is_ssh; then ...


1
không hoạt động trong các tmuxphiên từ xa và cũng có vấn đề nếu đăng nhập qua IPv6 và không tồn tại tên đảo ngược DNS.
lợi ích

@bene: cái gì không hoạt động? Biểu thức chính quy hoặc who am ikhông hiển thị địa chỉ IPv6 của bạn?
mivk

1) who am ikhông trả lại bất cứ điều gì trong một tmuxphiên từ xa . 2) Địa chỉ IPv6 có thể chứa dấu hai chấm mà regex của bạn không cho phép. Điều này có thể khó khăn vì who am ichứa (:0.0)trong các phiên X cho tôi (xterm).
lợi ích

@bene: Giải pháp thay thế mà tôi vừa thêm cũng sẽ hoạt động với IPv6. Tôi không biết về tmux, nhưng nó cũng hoạt động screen.
mivk

7

Tôi nghĩ câu trả lời của Gilles và Cakemox là tốt, nhưng chỉ để hoàn thiện ...

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

đến từ pam_lastlog1 .

Bạn có thể in pam_lastlogthông tin bằng lệnh lastlog2 , vd

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

để đăng nhập cục bộ, so với

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

để đăng nhập SSH.

Trên hệ thống của tôi, điều này hoạt động để giải nén nó

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

lastwcũng có thể hữu ích

$ 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 tài liệu Linux / FreeBSD cho pam_lastlog.
2 trang người dùng Linux / FreeBSD lastlog(8) .


1

Bắt đầu bằng cách xem xét môi trường của bạn và tìm ra lựa chọn phù hợp

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

Bạn có thể nối vào nhiều biến môi trường này để kích hoạt các hành động cụ thể dựa trên sự hiện diện của chúng.


-1

Điều này là để kiểm tra tất cả các kết nối được thiết lập từ người dùng khác bằng SSH

netstat | grep ssh

Điều này không đáng tin cậy chút nào.
DanielNiu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.