シェルがSSHから制御されているかどうかを検出するにはどうすればよいですか?


69

SSHで制御されているかどうかをシェルスクリプト(より具体的には.zshrc)から検出したいのですが。HOST変数を試しましたが、常にシェルを実行しているコンピューターの名前です。SSHセッションの発信元のホスト名にアクセスできますか?2つを比較すると、問題が解決します。

ログインするたびに、最終ログイン時刻とホストを示すメッセージが表示されます。

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)か()?
ジル14

1
@PraxeoliticまたSSH_*、SSHセッションの先頭にあるシェルのサブプロセスにも変数が設定されます。たとえば、SSHを介してスクリーンセッションを開始する場合(気にする場合は、セッションを開始する前に変数を設定解除する必要があります)。親プロセスをテストする理由は、sshdが環境変数を定義する前にそれを始めたからだと思います。
ジル

21

あなたは経由してチェックすることができるはずSSH_TTYSSH_CONNECTIONまたはSSH_CLIENT変数。


1
また、これらをコマンドに追加してenv_keep、コマンドsudoers間で機能するようにしsuます
。)

10

LinuxでもBashを使用して同じ問題が発生しました。最初に環境変数SSH_CONNECTIONを使用しましたが、次に設定した場合は設定されないことに気付きましたsu -

上記のlastlogソリューションは、suまたはの後でも機能しませんでしたsu -

最後に、who am iSSH接続の場合、最後にリモートIP(またはホスト名)を表示するを使用しています。suの後でも動作します。

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アドレスには、正規表現で許可されていないコロンが含まれている場合があります。これは私にとってはXセッション(xterm)にwho am i含ま(:0.0)れているため、扱いにくいかもしれません。
ベネ

@bene:追加したばかりの代替ソリューションはIPv6でも機能するはずです。tmuxについては知りませんが、でも動作しscreenます。
mivk

7

ジルとケーキモックスの答えは良いと思うが、完全を期すためだけに...

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

pam_lastlog1から来ます。

2コマンドpam_lastlogを使用して情報を印刷できます。例えばlastlog

$ 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用のLinux / FreeBSDドキュメントpam_lastlog
2 Linux / FreeBSD lastlog(8) manページ。


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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.