SEワンタンの独学備忘録

IT関連の独学した内容や資格試験に対する取り組みの備忘録

【Linux】ssh-agentを用いた公開鍵認証によるSSH接続


LPICの勉強をしていて、今更ながらssh-agentがすぐにうまく利用できずにちょっとハマってしまったのでまとめます。

前提と全体像

ssh-agentコマンドについて

ssh-agentは、SSH接続における交換鍵認証において、メモリ上に鍵のパスフレーズを保存することで認証におけるパスフレーズに入力を自動化するものです。

なので、そもそもSSH接続時の認証が交換鍵認証になっていない場合は使用できません

■ユーザパスワード認証
f:id:wantanBlog:20210129001710p:plain

最も基本的な認証方法。
なにも設定を行っていなければ、この認証方法になっているはず。
パスフレーズはログイン先のユーザのパスワードが必要になる

■交換鍵認証

・パスフレーズあり
f:id:wantanBlog:20210129004753p:plain

・パスフレーズなし
f:id:wantanBlog:20210129004730p:plain

client側で生成した鍵ペアのうち、秘密鍵をclient側に、公開鍵をserver(接続先)側に配布して鍵ペアの検証によって認証を行います
また鍵を生成する際にパスフレーズを任意で入力することができ、そこでパスフレーズを入力した場合には秘密鍵を使用するためにパスフレーズの入力が必要になります。
逆にパスフレーズを入力しなかった場合には、接続先のサーバへと公開鍵を登録した段階でパスフレーズの入力なくログインし放題になります。

それで、結局ssh-agentコマンドが使用される機会はと言うと、交換鍵認証方式におけるパスフレーズありの場合に限られます

ユーザパスワード認証はserver側で検証を行う公開鍵の情報がないので、秘密鍵を使用した認証はできませんし、交換鍵認証方式におけるパスフレーズなしの場合には、秘密鍵をそのまま使用すればいいだけなので必要ありません。

ssh-agentと言う仕組みは、通常であればSSH接続の度に使用できる状態にしているところを、メモリ上に使用できる状態の秘密鍵を保持していつでもそのまま使用できるようにしているというイメージでしょうか。

比較参考

www.wantanblog.com

実は以前にも同じようなことをやっています。
大きな違いは認証にssh-agentを用いていて、交換鍵にパスフレーズがある場合にも自動でログインできるようになることです。

わざわざ記事化しようと思ったのは、LPICという資格試験のためにssh-agentコマンドを学習したかったのと、ssh-agentについての記事はネット上ですぐに見つかりましたが、その前提にある公開鍵認証に触れている記事は少なく、前提知識がないとうまく実行できないのではないかと思ったから。

まぁこのような仕組みを利用する人は、SSH接続時の公開鍵認証なんてのはパッと分かって当然なのかもしれませんが、勘違いもあり私が少しハマったので。。

特にセキュリティ的に問題がない場合は上記の記事の方法の方が簡単です。

ssh-agentによる公開鍵認証

既に公開鍵認証の準備が完了している場合には途中を飛ばして「ssh-agentの実行と秘密鍵登録」から実行すればよいです。

また、以降の記事では、接続する側のマシンを「client」、接続される側のマシンを「server」と呼称します。

f:id:wantanBlog:20210131020002p:plain

認証方式を公開鍵認証に設定する

■作業情報
作業サーバ: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
作業ユーザ:ログインユーザ

次には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  130 00:44 id_rsa
-rw-r--r--. 1 wantan group1  395  130 00:44 id_rsa.pub
-rw-r--r--. 1 wantan group1  691  128 00:36 known_hosts
公開鍵の配布

■作業情報
作業サーバ:client
作業ユーザ:ログインユーザ

先ほど生成した鍵ペアのうち、公開鍵を接続先である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の起動

■作業情報
作業サーバ:client
作業ユーザ:ログインユーザ

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]$

今回はここまで。