LPICの勉強をしていて、今更ながらssh-agent
がすぐにうまく利用できずにちょっとハマってしまったのでまとめます。
前提と全体像
ssh-agentコマンドについて
ssh-agent
は、SSH接続における交換鍵認証において、メモリ上に鍵のパスフレーズを保存することで認証におけるパスフレーズに入力を自動化するものです。
なので、そもそもSSH接続時の認証が交換鍵認証になっていない場合は使用できません。
■ユーザパスワード認証
最も基本的な認証方法。
なにも設定を行っていなければ、この認証方法になっているはず。
パスフレーズはログイン先のユーザのパスワードが必要になる。
■交換鍵認証
・パスフレーズあり
・パスフレーズなし
client側で生成した鍵ペアのうち、秘密鍵をclient側に、公開鍵をserver(接続先)側に配布して鍵ペアの検証によって認証を行います。
また鍵を生成する際にパスフレーズを任意で入力することができ、そこでパスフレーズを入力した場合には秘密鍵を使用するためにパスフレーズの入力が必要になります。
逆にパスフレーズを入力しなかった場合には、接続先のサーバへと公開鍵を登録した段階でパスフレーズの入力なくログインし放題になります。
それで、結局ssh-agent
コマンドが使用される機会はと言うと、交換鍵認証方式におけるパスフレーズありの場合に限られます。
ユーザパスワード認証はserver側で検証を行う公開鍵の情報がないので、秘密鍵を使用した認証はできませんし、交換鍵認証方式におけるパスフレーズなしの場合には、秘密鍵をそのまま使用すればいいだけなので必要ありません。
ssh-agent
と言う仕組みは、通常であればSSH接続の度に使用できる状態にしているところを、メモリ上に使用できる状態の秘密鍵を保持していつでもそのまま使用できるようにしているというイメージでしょうか。
比較参考
実は以前にも同じようなことをやっています。
大きな違いは認証にssh-agent
を用いていて、交換鍵にパスフレーズがある場合にも自動でログインできるようになることです。
わざわざ記事化しようと思ったのは、LPICという資格試験のためにssh-agent
コマンドを学習したかったのと、ssh-agent
についての記事はネット上ですぐに見つかりましたが、その前提にある公開鍵認証に触れている記事は少なく、前提知識がないとうまく実行できないのではないかと思ったから。
まぁこのような仕組みを利用する人は、SSH接続時の公開鍵認証なんてのはパッと分かって当然なのかもしれませんが、勘違いもあり私が少しハマったので。。
特にセキュリティ的に問題がない場合は上記の記事の方法の方が簡単です。
ssh-agentによる公開鍵認証
既に公開鍵認証の準備が完了している場合には途中を飛ばして「ssh-agentの実行と秘密鍵登録」から実行すればよいです。
また、以降の記事では、接続する側のマシンを「client」、接続される側のマシンを「server」と呼称します。
認証方式を公開鍵認証に設定する
作業ユーザ:root
まずはserver側の設定で、sshdの認証方式を公開鍵認証に明示するように設定ファイルの修正を行っておきます。
修正対象のファイルは/etc/ssh/sshd_config
となります。
なお、本設定がなくても公開鍵の登録を行えば公開鍵認証として動作してくれるっぽいですが、ディストリビューションやその他設定によって違いがでる可能性もあるのでやっておくのが無難ではあると思います。
[root@server ssh]# vim /etc/ssh/sshd_config
エディタで対象ファイルを開いたらPubkeyAuthentication
と書かれた行を探して、コメントアウトされていたらコメントを解除、設定値がnoになっていたらyesに書き換えます。
PubkeyAuthentication yes
修正を行った場合は、sshd
を再起動しておきます。
[root@server ssh]# systemctl restart sshd
鍵ペアの生成
作業ユーザ:ログインユーザ
次にはclient側で鍵ペアの生成を行います。
鍵ペアの生成にはssh-key
コマンドを使用します。
ここでは必ず実際にSSH接続を行いたいユーザで実行します。特に拘りがなければ、オプションなしで実行して大丈夫です。
コマンドを実行すると、まず鍵の生成場所が聞かれますので基本的にはデフォルトで問題ないのでそのままエンターを押す。
次に鍵のパスフレーズが聞かれるので、ssh-agent
を使用してみたい場合には必ず任意のパスフレーズを入力します。
[wantan@client .ssh]$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/wantan/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/wantan/.ssh/id_rsa. Your public key has been saved in /home/wantan/.ssh/id_rsa.pub. The key fingerprint is: SHA256:5ytOx1z1s6V7qyrBg6fCyrDFx/87u4y1CK/uk5Wosok wantan@client The key's randomart image is: +---[RSA 2048]----+ | | | | | . | | . . | | . S . . .o| | . .. + X . .+| | . oo+o +.B .. | |..*..=+o*+.. ..| |E+oo+++*oOB...oo.| +----[SHA256]-----+ [wantan@client .ssh]$
ホームディレクトリの.ssh/
配下を確認して、以下のように秘密鍵と公開鍵が生成されていればOKです。
[wantan@client .ssh]$ ll ~/.ssh/ 合計 12 -rw-------. 1 wantan group1 1766 1月 30 00:44 id_rsa -rw-r--r--. 1 wantan group1 395 1月 30 00:44 id_rsa.pub -rw-r--r--. 1 wantan group1 691 1月 28 00:36 known_hosts
公開鍵の配布
作業ユーザ:ログインユーザ
先ほど生成した鍵ペアのうち、公開鍵を接続先であるserver側に配布します。
鍵の配布自体はいくつか方法がありますが、client側からssh-copy-id
コマンドを使用するのが失敗なく楽に実行できるのでお勧めです。
鍵をデフォルト設定で生成している場合は公開鍵のパスを指定する必要はありません、接続先のサーバ情報のみを[(接続先の)ログインユーザ]@[接続先のIP(またはホスト名)]
で指定します。
[wantan@client .ssh]$ ssh-copy-id wantan@server /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/wantan/.ssh/id_rsa.pub" The authenticity of host 'server (192.168.142.134)' can't be established. ECDSA key fingerprint is SHA256:LMNSDhFnnZrOtloxj3dsTIeg8HfrP4zlgXjKs8vkYPI. ECDSA key fingerprint is MD5:56:74:d8:8f:b7:ee:2c:81:a5:f3:52:fd:2e:7b:9a:e8. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys wantan@server's password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh 'wantan@server'" and check to make sure that only the key(s) you wanted were added. [wantan@client .ssh]$
なお本コマンドでやっていることとしては、client側の公開鍵(id_rsa.pub)の内容をserver側の「~/.ssh/authorized_keys」に書き込んでいます(内容のコピー)。
公開鍵認証が適用されていることの確認として以下のコマンドでついでに確認を行っておきます。
以下ではserverにssh接続を行い~/.ssh/authorized_keys
の内容を表示しています。
またこの段階ではid_rsa
(秘密鍵)のパスフレーズ入力が求められることも確認しておきます。
[wantan@client .ssh]$ ssh wantan@server cat ~/.ssh/authorized_keys Enter passphrase for key '/home/wantan/.ssh/id_rsa': ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSqHVulBRA3ZQZI8ier4LJE7hRSkLvx4Beq9TLIf3uL1l2PCWW9w8z9CDGGakTti8JqIuqoxjr/iVlyJRTZNx5Otxl2rs+oLuVPkOjfX0r7/Gq1099mYp/v4OgrhdvpVO5Ie5Z+9ZNYK5t7W2uh60X09wWxhUUZsLqEk4SajCGbe/IsA03gqPpO0Vkils/u2lY45GuZXQERu7W2Fhii0jO9ddsJ0GAJTKVM4Cmstu2iaWBwkzmff9A4agJm+rq0IhCsyOeSjPm93Ql0WMoHCneg7wxUuLdpkKBy8mqCZDf1bHFvZbHvOX+Z/d8mL71R+uX4t33LRhkKBLNvBmBLqdX wantan@client
ssh-agentの実行と秘密鍵登録
やっと本題です。ssh-agent
コマンドを使用してパスフレーズの入力を自動化します。
・ssh-agentの起動
作業ユーザ:ログインユーザ
ssh-agent
はそのまま実行しても必要な環境変数を示すだけなので、引数にbash(シェル)を指定することで、環境変数が設定された状態でシェルを子プロセスとして起動します。
しかし、そのまま実行すると仮にssh-agent
を停止させずにログアウトするとssh-agent
プロセスが残り続けてしまうので、exec
コマンドで実行することでログアウト時に自動でプロセスが停止させることができるので以下のような実行方法がおすすめです。
・ssh-agentの起動
[wantan@client .ssh]$ exec ssh-agent bash
以下のようにプロセスが表示されれば大丈夫です。
SSH_AGENT_PIDやSSH_AUTH_SOCKが設定されていればOKです。
[wantan@client .ssh]$ env | grep SSH SSH_AGENT_PID=2021 SSH_CLIENT=192.168.142.1 60490 22 SSH_TTY=/dev/pts/0 SSH_AUTH_SOCK=/tmp/ssh-NiCklZ8PrqNC/agent.2020 SSH_CONNECTION=192.168.142.1 60490 192.168.142.11 22
・秘密鍵の登録
現状ではまだssh-agent
を起動しただけなので、そこにパスフレーズを解除した秘密鍵を登録します。
登録の方法はssh-agent
を起動した状態で、ssh-add
コマンドを実行します。
鍵ペアをデフォルトパスで生成している場合にはオプションなしで実行すればいいだけです。登録時に秘密鍵のパスフレーズ入力を求められます。
[wantan@client .ssh]$ ssh-add Enter passphrase for /home/wantan/.ssh/id_rsa: Identity added: /home/wantan/.ssh/id_rsa (/home/wantan/.ssh/id_rsa)
また「-l」オプションをつけて実行することで、登録した秘密鍵を確認することができます。
[wantan@client .ssh]$ ssh-add -l 2048 SHA256:5ytOx1z1s6V7qyrBg6fCyrDFx/87u4y1CK/uk5Wosok /home/wantan/.ssh/id_rsa (RSA)
・ssh接続してみる
準備が整ったので、clientからserverに対して改めてSSH接続を行ってみます。
ログインしてもいいですが、先ほどと同様のコマンドを実行してみるとパスフレーズの入力が求められずに実行できることが確認できると思います。
[wantan@client .ssh]$ ssh wantan@server cat ~/.ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSqHVulBRA3ZQZI8ier4LJE7hRSkLvx4Beq9TLIf3uL1l2PCWW9w8z9CDGGakTti8JqIuqoxjr/iVlyJRTZNx5Otxl2rs+oLuVPkOjfX0r7/Gq1099mYp/v4OgrhdvpVO5Ie5Z+9ZNYK5t7W2uh60X09wWxhUUZsLqEk4SajCGbe/IsA03gqPpO0Vkils/u2lY45GuZXQERu7W2Fhii0jO9ddsJ0GAJTKVM4Cmstu2iaWBwkzmff9A4agJm+rq0IhCsyOeSjPm93Ql0WMoHCneg7wxUuLdpkKBy8mqCZDf1bHFvZbHvOX+Z/d8mL71R+uX4t33LRhkKBLNvBmBLqdX wantan@client
・ssh-agentを停止するには
exec
コマンドで実行した場合には、ログアウトをおこなうことで自動でプロセスが停止されます。
または明示的に停止させる場合には「-k」オプションで停止することができます。
[wantan@client ~]$ ssh-agent -k unset SSH_AUTH_SOCK; unset SSH_AGENT_PID; echo Agent pid 2288 killed;
おまけ
シェルスクリプトでも適用する
最後にシャルスクリプトにも適用を行ってみます。
対象のスクリプトはテストで実施するならなんでもいいですが、以下のように複数回のssh接続が行われるスクリプトが分かりやすいでしょう。
・サンプルスクリプト(test1.sh)
#!/bin/bash echo "start" ssh wantan@server touch test.log ssh wantan@server cat ~/.ssh/authorized_keys >> test.log ssh wantan@server ls >> test.log echo "end"
ひとまずそのまま実行してみます。
sshによる接続が3回あるので、その回数分だけパスフレーズを入力する必要があります。
[wantan@client work]$ ./test1.sh start Enter passphrase for key '/home/wantan/.ssh/id_rsa': Enter passphrase for key '/home/wantan/.ssh/id_rsa': Enter passphrase for key '/home/wantan/.ssh/id_rsa': end [wantan@client work]$
もちろん、ssh-agent
を事前に起動してからスクリプトを実行するという手もありますが、ここではシェルスクリプトに記述を行います。
ここではeval
というコマンドを用いることによって、ssh-agent
コマンドで出力される環境変数をエクスポートします。
・サンプルスクリプト(test2.sh)
#!/bin/bash echo "start" eval `ssh-agent` ssh-add ssh wantan@server touch test.log ssh wantan@server cat ~/.ssh/authorized_keys >> test.log ssh wantan@server ls >> test.log echo "end"
スクリプトを実行すると、ssh-add
コマンドで秘密鍵を登録する際に一度だけパスフレーズの入力が必要になっているはずです。
[wantan@client work]$ ./test2.sh start Agent pid 1592 Enter passphrase for /home/wantan/.ssh/id_rsa: Identity added: /home/wantan/.ssh/id_rsa (/home/wantan/.ssh/id_rsa) end [wantan@client work]$
今回はここまで。