Як я можу виявити, чи оболонка управляється з SSH?


69

Я хочу виявити скрипт оболонки (точніше. Zshrc), якщо він керується через SSH. Я спробував змінну HOST, але це завжди ім'я комп'ютера, на якому працює оболонка. Чи можу я отримати доступ до імені хоста, звідки надходить сеанс SSH? Порівнювання обох вирішило б мою проблему.

Кожен раз, коли я входжу в систему, з'являється повідомлення із зазначенням останнього часу входу та хоста:

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

Це означає, що сервер має цю інформацію.

Відповіді:


90

Ось критерії, які я використовую в своїх ~/.profile:

  • Якщо одна із змінних SSH_CLIENTабо SSH_TTYвизначена, це ssh сеанс.
  • Якщо назва батьківського процесу оболонки для входу - sshdце 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

(Чому ви хочете перевірити це в конфігурації оболонки, а не при запуску сеансу?)


3
Працювали велике спасибі! github.com/balupton/dotfiles/commit/…
balupton

1
ви можете зробити це в конфігурації оболонки, якщо ви хочете ввімкнути пересилання ssh-агента зі своєї віддаленої оболонки (оскільки для кожної оболонки, яку ви хочете переслати, необхідно встановити варс середовища), якщо я щось не пропускаю?
недоїдання

@underrun Я не розумію вашої точки зору. Якщо ви запустили іншу оболонку в тому ж сеансі, вона успадковує змінні середовища, встановлені .profile. І що це стосується переадресації агентів?
Жиль

1
@underrun Якщо ви хочете протестувати на наявність переадресації агента SSH, перевірте SSH_AUTH_SOCKзміну. Але навіщо в такому випадку запускати агента SSH? Ви мали на увазі запустити агента, якщо ви ввійшли без переадресації агента? Чому б не запустити агент, якщо його ще немає ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Жиль

1
@Praxeolitic SSH_*Змінні також встановлюються в підпроцесах оболонки, яка знаходиться на чолі сеансу SSH, наприклад, якщо ви запускаєте сеанс на екрані через SSH (вам слід скасувати змінні перед початком сеансу, якщо вам це важливо). Я думаю, що причина тестування батьківського процесу полягає в тому, що я почав це робити, перш ніж sshd визначив будь-які змінні середовища.
Жиль

21

Ви повинні бути в змозі перевірити з допомогою SSH_TTY, SSH_CONNECTIONабо SSH_CLIENTзмінних.


1
Крім того, додати їх до env_keepв , sudoersщоб змусити його працювати по suкомандам :)
Thomas G.

10

У мене просто була така ж проблема в Linux, використовуючи Bash. Я спершу використав змінну середовища SSH_CONNECTION, але потім зрозумів, що вона не встановлена, якщо ви su -.

Наведене вище рішення останнього журналу не працювало ні після, suні su -.

Нарешті, я використовую who am i, який показує віддалений IP (або ім'я хоста) наприкінці, якщо це з'єднання SSH. Він також працює після су.

Використовуючи регулярні вирази Bash, це працює:

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

Якщо zsh не підтримує регулярні вирази, те саме можна досягти різними способами за допомогою клавіш grep, cut, sed чи будь-чого іншого.

Для допитливих, нижче, для чого я це використовую, в корені .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

Альтернативою, яка також працює su, буде рекурсивний пошук sshdчерез батьківські процеси:

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

Якщо функція додана до .bashrc, її можна використовувати як if is_ssh; then ...


1
не працює у віддалених tmuxсеансах, а також має проблеми, якщо увійти через IPv6 і немає зворотного імені DNS.
бенефіс

@bene: що не працює? Звичайний вираз, чи who am iне відображається ваша IPv6 адреса?
mivk

1) who am iнічого не повертає у віддаленому tmuxсеансі. 2) IPv6-адреса може містити кольори, які не дозволяє ваш регулярний вираз. Це може бути складним, оскільки who am iміститься (:0.0)в X сесіях для мене (xterm).
бенефіс

@bene: Альтернативне рішення, яке я щойно додав, також має працювати з IPv6. Я не знаю про tmux, але він також працює screen.
mivk

7

Я думаю, що відповіді Гілла та Кекемокса хороші, але лише для повноти ...

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

походить від pam_lastlog1 .

Ви можете друкувати pam_lastlogінформацію за допомогою команди lastlog2 , наприклад

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

для локального входу, порівняно з

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

для входу в SSH.

У моїй системі це працює для його вилучення

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

lastі wможе бути корисним, наприклад

$ 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 документація на Linux / FreeBSD для Windowspam_lastlog .
2 основні сторінки Linux / FreeBSD lastlog(8) .


1

Почніть з огляду свого оточення та пошуку правильного варіанту

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

Ви можете підключитись до багатьох цих змінних середовища, щоб запустити конкретні дії на основі їх присутності.


-1

Це потрібно для перевірки встановленого з'єднання від іншого користувача за допомогою SSH

netstat | grep ssh

Це зовсім не надійно.
DannyNiu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.