web-dev-qa-db-ja.com

パスワードプロンプトなしでssh-addを自動的に実行するにはどうすればよいですか?

SSHを介して、ネットワーク上の複数のコンピューター(静的イーサネット)間で通信したい。これを行うには、特定のマシンにログインするたびにssh-addを実行する必要があります。これを行うには、一度セットアップして、ログインまたは再起動するたびにパスフレーズを要求しないようにします。私のマシン?

bash_profileファイルにいくつかの行を追加する方法があることはわかっていますが、特定のマシンに再起動/ログインするたびにパスワードを入力する必要があります。

if [ -z "$SSH_AUTH_SOCK" ] ; then
    eval `ssh-agent -s`
    ssh-add
fi
267
zdun8

これは、セキュリティと利便性のトレードオフの典型的な例です。幸いにもいくつかのオプションがあります。最も適切なソリューションは、使用シナリオと必要なセキュリティレベルによって異なります。

ssh-key with passphrase、nossh-agent

認証にキーが使用されるたびに、パスフレーズを入力する必要があります。これはセキュリティの観点からは最良のオプションですが、最悪のユーザビリティを提供します。これは、繰り返し入力する負担を軽減するために、弱いパスフレーズが順番に選択されることにもつながります。

ssh-key with passphrase、withssh-agent

以下を~/.bash_profileに追加すると、自動的にssh-agentが開始され、ログイン時にsshキーがロードされます。

if [ -z "$SSH_AUTH_SOCK" ] ; then
  eval `ssh-agent -s`
  ssh-add
fi

ログインするたびにパスフレーズを入力する必要があります。使いやすさの観点からは少し優れていますが、ログインセッション中にキーを使用するかどうかに関係なく、ssh-agentがパスフレーズを要求するという欠点があります。新しいログインごとに個別のssh-agentインスタンスも生成され、明示的に強制終了しない限り、ログアウト後もメモリに追加されたキーで実行され続けます。

ログアウト時にssh_agentを強制終了するには、~/.bash_logoutに以下を追加します

if [ -n "$SSH_AUTH_SOCK" ] ; then
  eval `/usr/bin/ssh-agent -k`
fi

または以下を~/.bash_profile

trap 'test -n "$SSH_AUTH_SOCK" && eval `/usr/bin/ssh-agent -k`' 0

Collin Andersonの回答 のように、ファイルシステム内の固定された場所にエージェントへの永続的な通信ソケットを作成することで、複数のssh-agentインスタンスの作成を回避できます。これは、複数のエージェントインスタンスを生成する場合よりも改善されていますが、明示的に強制終了しない限り、ログアウト後も復号化されたキーがメモリに残ります。

デスクトップでは、デスクトップ環境に含まれる Gnome Keyring SSH Agent などのssh-agentを使用すると、通常、最初にssh-keyでパスフレーズの入力を要求できるため、より優れたアプローチになります。ログインセッション中に使用され、セッションが終了するまで、復号化された秘密鍵をメモリに保存します。

ssh-key with passphrase、withssh-ident

ssh-ident は、ユーザーに代わってssh-agentを管理し、必要に応じてIDをロードできるユーティリティです。 ssh-agentへのアクセスを必要とする端末、ssh、またはログインセッションの数に関係なく、必要なときに一度だけキーを追加します。また、接続されているホスト、またはディレクトリsshの呼び出し元に応じて、異なるエージェントと異なるキーのセットを追加して使用することもできます。これにより、異なるホストでエージェント転送を使用するときにキーを分離できます。また、GitHubなどのサイトで複数のアカウントを使用することもできます。

ssh-identを有効にするには、それをインストールし、次のエイリアスを~/bash_profileに追加します。

alias ssh='/path/to/ssh-ident'

ssh-key with passphrase、withkeychain

keychain は、ユーザーに代わってssh-agentを管理し、ログインセッションの終了時にssh-agentを実行したままにすることができる小さなユーティリティです。以降のログインでは、keychainは既存のssh-agentインスタンスに接続します。実際には、これは、再起動後の最初のログイン時にのみパスフレーズを入力する必要があることを意味します。以降のログインでは、既存のssh-agentインスタンスの暗号化されていないキーが使用されます。これは、パスワードなしのsshキーなしでcronジョブでパスワードなしのRSA/DSA認証を許可する場合にも役立ちます。

keychainを有効にするには、それをインストールし、次のようなものを~/.bash_profileに追加します。

eval `keychain --agents ssh --eval id_rsa`

セキュリティの観点からは、ssh-identおよびkeychainは、特定のセッションの存続期間に制限されているssh-agentインスタンスよりも劣りますが、高度な利便性を提供します。 keychainのセキュリティを向上させるために、--clearキーチェーンの呼び出しに~/.bash_profileオプションを追加する人もいます。このようにすることで、上記のようにログイン時にパスフレーズを再入力する必要がありますが、cronジョブは、ユーザーがログアウトした後も暗号化されていないキーにアクセスできます。 keychainwiki page には、より多くの情報と例があります。

ssh-key with passphrase

セキュリティの観点からは、秘密鍵が公開された場合に備えて完全に保護されていないため、これは最悪のオプションです。ただし、これは再起動後にパスフレーズを再入力する必要がないことを確認する唯一の方法です。

ssh-key with passphrase、withssh-agentpassphrase tossh-addスクリプトから

スクリプトからパスフレーズをssh-addに渡すことは簡単なように思えるかもしれませんが、 echo "passphrase\n" | ssh-add、これはssh-addのように単純ではありません stdinからパスフレーズを読み取りませんが、/dev/ttyを直接開いて読み取ります

これは、インタラクティブアプリケーションを自動化するためのツールである expect を使用して 回避策 にすることができます。以下は、スクリプトに保存されているパスフレーズを使用してsshキーを追加するスクリプトの例です。

#!/usr/bin/expect -f
spawn ssh-add /home/user/.ssh/id_rsa
expect "Enter passphrase for /home/user/.ssh/id_rsa:"
send "passphrase\n";
expect "Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)"
interact

パスフレーズはスクリプトでプレーンテキストで保存されるため、セキュリティの観点から、これはパスワードなしのsshキーを使用するよりもはるかに優れていることに注意してください。このアプローチを使用する場合は、パスフレーズを含むexpectスクリプトに適切な権限を設定し、鍵の所有者のみが読み取り、書き込み、実行できるようにすることが重要です。

363
Thomas Nyman

これを~/.bashrcに追加し、ログアウトして再度ログインすると、有効になります。

if [ ! -S ~/.ssh/ssh_auth_sock ]; then
  eval `ssh-agent`
  ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
ssh-add -l > /dev/null || ssh-add

これにより、再起動するたびに初めてログインするときにのみパスワードの入力を求められます。実行中であれば、同じssh-agentを再利用し続けます。

101
Collin Anderson

OPの質問とはあまり関係ありませんが、他の人には役立つかもしれません。7.2.0以降、ssh(1)には、最初の認証時にssh-agentにキーを追加できるオプションがあります。オプションはAddKeysToAgentで、yesnoask、またはconfirmに設定でき、システム全体または個人用.ssh/configファイル。

参照: https://www.openssh.com/txt/release-7.2

16

ssh-agentは、ロック解除されたさまざまなsshキーをキャッシュするため、sshキーをパスワードで保護できますが、毎回入力する必要はありません。

ロック解除されたキーをキャッシュするには、それらのキーのロックを解除する必要があります。パスフレーズでロックされている鍵のロックを解除するには、これらのパスフレーズを知っている必要があります。

人間からの承認を必要としない方法(「パスワードの入力」など)は、システムを安全な状態にするだけではありません。また、ssh-agentの目的全体が無意味になります。

これをすべて言っても、パスワードで保護されていないsshキーを使用するだけで済みます(ヒット Enter キー生成中にパスワードを要求された場合)。パスワードがないため、ssh-agentキャッシュする(しない)ために要求する必要はありません。

7
umläute

SSHパスフレーズを自動化するための回避策を次に示します。

  1. パスフレーズを標準出力に出力する1行のスクリプトを作成します。例:

     echo 'echo MY_SSH_PASSWORD' > ~/.print_ssh_password && chmod 700 ~/.print_ssh_password
    

    重要:必ず先頭のスペースを にコピーして、パスワードを履歴に保存しないようにしてください

以下のいずれかの方法を使用します。

  • 標準入力アプローチを使用する:

    cat ~/.ssh/id_rsa | SSH_ASKPASS=~/.print_ssh_password ssh-add -
    
  • または 名前付きパイプ アプローチ:

    1. 名前付きパイプを作成するプロセス置換 を試すこともできます):

      mkfifo --mode 0600 ~/.ssh_fifo
      
    2. 認証に使用するプログラムを指定して、ssh-addを実行します。

      cat ~/.ssh/id_rsa >~/.ssh_fifo | SSH_ASKPASS=~/.print_ssh_password ssh-add ~/.ssh_fifo
      

    man ssh-addの詳細については、 SSH_ASKPASS を参照してください。

5
kenorb

ログイン時にssh-add(ssh-agentを開く必要がある)はお勧めしません。これは、ssh-agentセクションがいつ終了するかを制御できず、1つのログインセクションでキーファイルを使用する必要がない場合にセキュリティリスクを引き起こす可能性があるためです。

むしろ、すべてのキーファイルが自動的に追加されたssh-agentのセクションサブシェルを開き、sshを使用する必要があるときに呼び出されるスクリプトを書くことをお勧めします。採用できるのであれば、読み続けてください。

次の2つの選択肢があります。

  1. キーファイルが盗まれた場合、弱いセキュリティが設定されているキーのすべてのパスフレーズを削除します。 (したがって非推奨

  2. 鍵には同じパスフレーズを使用してください。その後、ssh-add keyfile1 keyfile2 ...、セクションごとに1回だけパスフレーズを入力する必要があります。

どちらの場合も、次のようなスクリプトファイル "ssh_keys_section.sh"を記述できます。

#!/bin/bash
# This script run a ssh-agent on a sub-Shell and automatically ssh-add all keyfiles at once.
# This agent ends when you type `exit` to close the sub-Shell.
exec ssh-agent bash -c "ssh-add /path/to/keyfile1 /path/to/keyfile2 ...; exec bash"

備考:

  • パスフレーズを変更または削除するコマンド:ssh-keygen -p -f keyfile
  • サブシェル内では、おそらく/path/to/yourterminal &(OSに依存)
4
Johnny Wong

以前はSteampoweredによって言及されたスクリプトを使用していましたが、ファイルを横に置いたままにしないため、以下のスクリプトを作成しました。

zshシェルのみで作業します。

#!/bin/sh

AGENT_BIN=`which ssh-agent`
AGENT_ADD_BIN=`which ssh-add`
AGENT_PID=`ps -fe | grep ${AGENT_BIN} | awk -vuser=$USER -vcmd="$AGENT_BIN" '$1==user && $8==cmd{print $2;exit;}'`
if [ -z "$AGENT_BIN" ]; then
    echo "no ssh agent found!";
    return
fi
if [ "" -eq "$AGENT_PID" ]; then
    if read -sq "YN?Do you want to unlock your ssh keys?"; then
        echo ""
        output=`$AGENT_BIN | sed 's/echo/#echo/g'`
        eval $output
        $AGENT_ADD_BIN
    fi
else
    for f in "/proc/"*
    do
        cmdline=`cat "$f/cmdline"`
        if [ "${AGENT_BIN}" -ef "${cmdline}" ]; then
            export SSH_AUTH_SOCK=`cat $f/net/unix | grep --binary-file=text -oP '((/[^/]*?)+/ssh-[^/]+/agent\.\d+$)'`
            export SSH_AGENT_PID=${f##*/}
            break;
        fi
    done
fi
2
rmc
if [ ! -S ${HOME}/.ssh/ssh_auth_sock ]; then
  eval $(ssh-agent)
  ln -sf "${SSH_AUTH_SOCK}" ${HOME}/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=${HOME}/.ssh/ssh_auth_sock

ssh_keys=$(find -E ~/.ssh -type f -regex '.*(rsa$|pem)')
ssh_agent_keys=$(ssh-add -l | awk '{key=NF-1; print $key}')

for k in "${ssh_keys}"; do
    for l in "${ssh_agent_keys}"; do
        if [[ ! "${k}" = "${l}" ]]; then
            ssh-add "${k}" > /dev/null 2>&1
        fi
    done
done

SSHのシングルサインオンソリューションは pam_ssh

この記事 によると、コンセプトは次のとおりです。

Sshを介して複数の* nixベースのマシンで作業している場合、別のボックスにアクセスするたびにパスワードを入力しなければならないことにうんざりしているでしょう。 sshでアクセスできるすべてのマシンに、別のパスワード(最初にサインオンしたもの以外)を入力せずにアクセスできる安全な方法があります。


これは実際には非常に簡単です。基本的には、公開鍵と秘密鍵のペアを作成して他のマシンに対して自分自身を認証し、PAMにログオン後にキーをロードするエージェントを生成させ、すべてのリモートにアクセスするためのシングルサインオンソリューションを提供しますマシン。このガイドでは、この設定について説明します。

これが実際に機能するかどうかは確認していません。

1
Michael
SSH_ENV="$HOME/.ssh/environment"

function start_agent {
     echo "Initialising new SSH agent..."
     /usr/bin/ssh-agent | sed 's/^echo/#echo/' > "${SSH_ENV}"
     echo succeeded
     chmod 600 "${SSH_ENV}"
     . "${SSH_ENV}" > /dev/null
     /usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
     . "${SSH_ENV}" > /dev/null
     #ps ${SSH_AGENT_PID} doesn't work under cywgin
     ps -ef | grep ${SSH_AGENT_PID} | grep ssh-agent$ > /dev/null || {
         start_agent;
     }
else
     start_agent;
fi

ここでクレジットを付与: https://www.cygwin.com/ml/cygwin/2001-06/msg00537.html

このソリューションもここで承認されています: http://mah.everybody.org/docs/ssh

1
steampowered

これを~/.bashrcファイルに追加します。

ssh-add -L|grep identities > /dev/null && ssh-add /path/to/ssh/private/key
0
Abukamel

これが決定的なスクリプトです。

$ PASSWを更新してから、ターミナルにコピーして貼り付けます

# <sshpass> via typinator
# Updated: 2017-01-18_21h36
#
# apt-get update -y; apt-get install expect -qy

# Pass this value to ssh-add
PASSW="myfancypass123"

# Define a name for this script
THIS_SCRIPT="$(date +%Y-%m-%d_%H-%M-%S-%N)".sh

# Create a fresh directory to work from / Clean up
rm -rf ~/temp; mkdir -p ~/temp; cd ~/temp; ls -la


# Output our bash script file - BEGIN
cat <<< '
#!/bin/bash

set -u     # Stop if an unbound variable is referenced
set -e     # Stop on first error
export HISTIGNORE="expect*";

# Normal CMDs
echo && echo "The process should take about 10 seconds:" && echo
eval "$(ssh-agent -s)"; sleep 0.5;

# Define VAR passed when this bash-script was launched
password="$@"

# Launch the expect magic
expect -c "
    spawn ssh-add /root/.ssh/id_rsa
    expect "?assword:"
    send \"$password\r\"
    expect "?password:"
    send \"$password\r\"
    expect eof"

export HISTIGNORE="";
export password="";
' > $THIS_SCRIPT
# Output our bash script file - END


# Ensure we are in the right path
cd ~/temp; ls -la; sleep 1;

# Run the bash script
chmod +x ./$THIS_SCRIPT; ./$THIS_SCRIPT "$PASSW"; unset password;

# Clean up
rm -rf ~/temp; mkdir -p ~/temp; cd ~/temp; ls -la
0
Pascal Andy

(おそらくパスワードなしの)キーを追加し、ssh-add[〜#〜] x [〜#〜]

DISPLAY= ssh-add -k /path/to/key </dev/null &>/dev/null

終了ステータスは、成功または失敗を示します。

0
Keith Cascio

私が認識している最良の方法は、この質問で満足のいく答えを見つけることができなかったため、前の作業から変更したPAMログインスクリプトを使用することです。

パスフレーズは、システムパスワードと強力な派生関数で暗号化されて保存されます。ログイン時に、システムパスワードを使用してパスフレーズを復号化し、エージェントに追加します。

https://github.com/capocasa/systemd-user-pam-ssh

提示されている他のすべてのソリューションに対する利点は、ブート時に手動でssh-addを実行するのと同等のセキュリティをゼロの労力で組み合わせていることです。追加のツールを必要とせず、ほとんどのシステム(OpenSSL)にデフォルトですでにインストールされている追加の依存関係があります。

0
cmc

パスワードマネージャーとしてタツノオトシゴを実行している場合 ...これはおそらく; D

あなたが探している目標を達成する別のソリューションは、ログイン時に自動ロック解除のためにタツノオトシゴにsshキーを単に追加することです。これの主な利点は、gdmを介してログインした後、またはキーにパスワードが設定されていても、ログインに使用した後は、キーのパスワードを入力する必要がないことです。これには、秘密鍵と公開鍵の両方が必要です。また、タツノオトシゴの命名規則に従う必要があります。デフォルトは受け入れ可能です(秘密鍵のid_rsaおよび公開鍵のid_rsa.pub ...privatekeynameおよびprivatekeyname.pub

ログイン時に自動ロック解除するタツノオトシゴにsshキーを追加するには、 (Fedora25では、パスが他のディストリビューションのどこにあるかはわかりませんが、非常によく似ています)

/lib64/seahorse/seahorse-ssh-askpass /path/to/keys/here

私にとっては

/lib64/seahorse/seahorse-ssh-askpass ~/.ssh/id_rsa

(タツノオトシゴは、私の場合の公開鍵がid_rsa.pubであると自動的に想定します)

コマンドを実行した後、seahorseはかわいい小さなgtkパスワードフィールドをポップオープンして、秘密鍵のパスワードを入力します。または、パスワードなしでキーを生成した場合は、空白のままにします。

すべてがうまくいった場合、タツノオトシゴはプロンプトを出しません。ターゲットマシンにSSHで接続する必要があります。その後、タツノオトシゴはパスワードでグラフィカルにキーのロックを解除するように促します(これは1回のみ発生します)が、今回は少し違って見えるはずです; P(これはタツノオトシゴがタツノオトシゴをssh-addするためにいくつかの魔法をかける部分でもあると思います) )、および[〜#〜]オプション[〜#〜]を提供して、ログイン時にキーのロックを解除します。このオプションをチェックして、目標を達成します。

すべての回答を読んだわけではないので、この回答を試す前に、ssh-addを使って誰もがあなたに言ったことを元に戻すことをお勧めします。そうしないと、キーに問題が発生する可能性があります、idk。

0
enconn

MacOSでの私のセットアップは次のとおりです(.zshrc、またはbashの場合は.bash_profileで)。

# Kill then Load the ssh-agent and set the necessary env variables it outputs
sshRestart() {
    # if all else fails
    # pkill -u $(whoami) ssh-agent;

    if [ -n "$SSH_AUTH_SOCK" ] ; then
        eval `/usr/bin/ssh-agent -k`
    fi
    eval `ssh-agent -s`
    ssh-add ~/.ssh/YOUR_KEY_FILE
    echo "Restarted SSH agent"
}

if [ -z "$SSH_AUTH_SOCK" ] || [[ $SSH_AUTH_SOCK == *"/private/tmp/"* ]] ; then
    eval `ssh-agent -s` > /dev/null 2>&1
    ssh-add ~/.ssh/YOUR_KEY_FILE > /dev/null 2>&1
fi

デフォルト値は|| [[ $SSH_AUTH_SOCK == *"/private/tmp/"* ]]であるため、macOSでは/private/tmp/com.Apple.launchd.SOMETHINGHERE/Listeners部分が必要です。そうでない場合、$SSH_AUTH_SOCKは常に何かに設定されているため、@ Thomas Nymanの包括的な回答は失敗します。

次に.zlogout(bashの場合は.bash_logout)で:

if [ -n "$SSH_AUTH_SOCK" ] ; then
    eval `/usr/bin/ssh-agent -k`
fi

MacOS Mojave 10.14.5でテスト済み

0
Samuel Prevost