「SSH 鍵」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(校正(でき・出来))
 
1行目: 1行目:
[[Category:Secure Shell]]
+
[[Category:セキュアシェル]]
 
[[en:SSH keys]]
 
[[en:SSH keys]]
 
[[es:SSH keys]]
 
[[es:SSH keys]]

2024年8月16日 (金) 18:38時点における最新版

SSH 鍵は公開鍵暗号チャレンジ/レスポンス認証を使って SSH サーバーに自身を確認させる手段として用います。伝統的なパスワード認証と比べてこの方法を使用する利点として、ネットワークを介してパスワードを送信しなくてもサーバーから認証を受けられるということが挙げられます。パスワードを転送しているわけではないので、たとえ接続を盗聴されてもパスワードを盗まれたりクラックされる恐れがありません。さらに、SSH 鍵を使って認証をすることによって、ブルートフォース攻撃を受けるリスクを事実上なくすことができます。攻撃者が正しい証明書を得られる確率は劇的に減るからです。

セキュリティの向上につながるという他に、SSH 鍵認証は伝統的なパスワード認証よりも便利だという点もあります。SSH エージェントというプログラムを使うことで、システムごとのパスワードを記録して入力する必要はなくなり、SSH 鍵でサーバーに接続することが可能になります。

SSH 鍵に全く欠点がないというわけではなく、環境によっては相応しくないという場合もありますが、大抵の場合は SSH 鍵を使用することには強力なメリットが望めます。SSH 鍵の動作方法を理解することは、いつ、どのように鍵を使えば要求を満たせるのか考える手がかりになるでしょう。この記事では Secure Shell プロトコルについての基本的な知識を持っていて、公式リポジトリopenssh パッケージを既にインストールしていることを前提としています。

予備知識

SSH 鍵は常に、一方を秘密鍵、もう一方を公開鍵としてペアで生成されます。秘密鍵はあなたしか知らない鍵で、安全に保管する必要があります。一方、公開鍵は接続したい SSH サーバーと自由に共有できます。

SSH サーバがあなたの公開鍵を持っていて、あなたが接続をリクエストしたことを確認したら、SSH サーバーは公開鍵を使ってチャレンジを作成し、あなたに送ります。このチャレンジは暗号化されたメッセージで、サーバがあなたのアクセスを許可するために、適切な応答が必要です。この暗号化されたメッセージを安全に解読できるのは秘密鍵を持っている人だけということが、暗号文を特に安全なものにしています。公開鍵を使ってメッセージを暗号化することはできる一方で、公開鍵を使ってメッセージを復号化することはできません。秘密鍵を持っている、あなただけが、チャレンジを解読して適切なレスポンスを作成することができるわけです。

この チャレンジ/レスポンス認証は水面下で行われ、ユーザーが関知するところではありません。秘密鍵を持ってさえいれば (通常は ~/.ssh/ ディレクトリに鍵が保存されます)、SSH クライアントはサーバーに適切なレスポンスを返すことが可能です。

秘密鍵は機密情報として考えてよく、暗号化された形式でディスクに保存することをお勧めします。暗号化された秘密鍵が必要になったとき、最初にパスフレーズを入力して秘密鍵を復号化する必要があります。これは表面的には、SSH サーバーにログインパスワードを入力するのと変わりないように見えますが、実際にはローカルシステム上の秘密鍵を復号化するためにのみ使用されます。パスフレーズはネットワーク経由で送信されることはありません。

SSH 鍵のペアを生成

SSH 鍵のペアは ssh-keygen コマンドを実行することで生成できます。デフォルトは 3072 ビット RSA (および SHA256) で、ssh-keygen(1) のマニュアルページには、「一般的に十分と見なされ」、事実上すべてのクライアントとサーバに互換性があるはずです。

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/<username>/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/<username>/.ssh/id_rsa.
Your public key has been saved in /home/<username>/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:gGJtSsV8BM+7w018d39Ji57F8iO6c0N2GZq3/RY2NhI username@hostname
The key's randomart image is:
+---[RSA 3072]----+
|   ooo.          |
|   oo+.          |
|  + +.+          |
| o +   +     E . |
|  .   . S . . =.o|
|     . + . . B+@o|
|      + .   oo*=O|
|       .   ..+=o+|
|           o=ooo+|
+----[SHA256]-----+

ランダムアートイメージintroduced in OpenSSH 5.1 で導入されたもので、鍵の指紋を視覚的に識別しやすくするためのものです。

ノート: -a スイッチを使うことで、パスワード暗号化の KDF ラウンドの数を指定できます。

-C スイッチを使って公開鍵にコメントフィールドを追加して、~/.ssh/known_hosts~/.ssh/authorized_keys などの場所や ssh-add -L の出力で公開鍵を簡単に識別できるようにすることができます。例:

$ ssh-keygen -C "$(whoami)@$(hostname)-$(date -I)"

上記のコマンドで、どのマシンとユーザーで作成した鍵なのか、作成日時はいつなのかというコメントが追加されます。

認証鍵の種類を選択

OpenSSH はいくつかの署名アルゴリズム (認証鍵用) をサポートしていますが、それらは利用する数学的性質によって 2つのグループに分けることができます。

  1. DSARSA は、2つの大きな素数の積を因数分解することの実際的な難しさに依存しています。
  2. 楕円曲線離散対数問題を利用した ECDSAEd25519。()

楕円曲線暗号 (ECC) アルゴリズムは、公開鍵暗号方式に最近になって追加されたアルゴリズムです。その主な利点の一つは、より小さな鍵で同じレベルのセキュリティを提供できることで、計算負荷の少ない操作(鍵の生成、暗号化、復号化の高速化)と、ストレージや伝送要件の低減を実現します。

OpenSSH 7.0 では、発見された脆弱性のために DSA 鍵のサポートは廃止され、無効になりました。したがって、暗号システムの選択は RSA または 2 種類の ECC のうちの 1 つになります。

#RSA 鍵は最も移植性が高く、#Ed25519 は最もセキュリティが高いが、クライアントとサーバの最新版が必要である[1]#ECDSAは Ed25519 より互換性が高いが(それでも RSA より劣るが)、その安全性には疑惑がある(後述)。

ノート: 鍵が使用されるのは認証を行うときだけです。強固な鍵にすることで、SSH によってデータを送信する際の CPU の負担が増えることはありません。

RSA

ssh-keygen のデフォルトは RSA なので -t オプションを指定する必要はありません。RSA はすべてのアルゴリズムの中で最高の互換性を備えていますが、十分なセキュリティを提供するためには鍵のサイズを大きくする必要があります。

鍵のサイズは最小で 1024 ビット、デフォルトは 3072 ( ssh-keygen(1) を参照)、最大は 16384 です。

より強力な RSA 鍵ペアを生成する場合 (例えば、最先端または未知の攻撃やより高度な攻撃者から保護するため)、-b オプションにデフォルトよりも高いビット値を指定するだけです。

$ ssh-keygen -b 4096

しかし、より長い鍵を使うことには限界があることに注意してください[2][3]。GnuPG の FAQ にはこうあります。「RSA-2048 が提供する以上のセキュリティが必要な場合は、RSA を使い続けるのではなく、楕円曲線暗号に切り替えるほうが良いでしょう[4]

一方、NSA Fact Sheet Suite B Cryptography の最新版では、RSA のモジュラスを 3072 ビット以上にして、「来たるべき量子耐性アルゴリズムへの移行に備える」ことを提案しています。[5]

ECDSA

楕円曲線デジタル署名アルゴリズム (ECDSA) は、in OpenSSH 5.7 で認証のための好ましいアルゴリズムとして導入されました。また、一部のベンダーは潜在的な特許の問題から、必要な実装を無効にしています。

それには、2種類の懸念があります。

  1. 政治的懸念、NSA が進んでソフトウェアやハードウェア部品、公表されている標準規格にバックドアを挿入していることが明らかになった後、NIST が作成した曲線の信頼性が疑問視されています、著名な暗号技術者が NISTの曲線の設計方法について疑問を表明しており、自主的な汚染は過去にすでに証明されています。
  2. 技術的な懸念として、規格を適切に実装することの難しさや、遅さなど設計上の欠陥があり、十分な注意を払わない実装ではセキュリティが低下します。

これらの懸念は、libssh curve25519 introduction に最もよくまとめられています。政治的な懸念はまだ議論の対象ですが、#Ed25519 が技術的に優れており、それゆえ優先されるべきであるという明確なコンセンサスがあります。

Ed25519

Ed25519 は 2014年1月の OpenSSH 6.5 で導入されました。「Ed25519 は ECDSA や DSA よりも優れたセキュリティと優れたパフォーマンスを提供する楕円曲線署名方式です」。その主な強みは、その速度、一定時間の実行時間(およびサイドチャネル攻撃への耐性)、そして曖昧なハードコードされた定数がないことです[6]。動作方法については、Mozilla の開発者によるこのブログ記事 も参照してください。

これはすでに多くのアプリケーションやライブラリで実装されており、OpenSSH のデフォルトの鍵交換アルゴリズム(鍵署名とは異なります)です。

Ed25519 の鍵ペアは以下の方法で生成できます。

$ ssh-keygen -t ed25519

すべての Ed25519 鍵は 256 ビットなので、鍵のサイズを設定する必要はありません。

古い SSH クライアントやサーバは、この鍵に対応していないかもしれないことに注意してください。

FIDO/U2F

FIDO/U2F ハードウェア認証機能のサポートが OpenSSH バージョン 8.2 で追加され、上記の楕円曲線署名方式のいずれにも対応しました。これは USB やその他の手段で接続されたハードウェアトークンを、 秘密鍵と並ぶ第二の要素として機能させることができるようにするものです。

ノート: クライアントとサーバーの両方が ed25519-skecdsa-sk の鍵タイプに対応している必要があります。

ハードウェアトークンサポートのため、libfido2 が必要です。

ノート: OpenSSH はハードウェアトークンとの通信にミドルウェアライブラリを使用し、USB トークンをサポートする内部ミドルウェアが付属しています。その他のミドルウェアは sshd_config(5) § SecurityKeyProvider ディレクティブや、ssh-keygen および ssh-addSSH_SK_PROVIDER 環境変数で指定することが可能です。

互換性のある FIDO 鍵を添付した後、鍵ペアを生成することができる。

$ ssh-keygen -t ed25519-sk

通常、生成の確認のため、PIN の入力やトークンのタップが必要になります。サーバに接続する場合は、生成時に -O no-touch-required コマンドラインオプションを使用し、サーバで sshd(8) § no-touch-required authorized_keys オプションが設定されていない限り、通常トークンをタップする必要があります。

タッチイベントを必要としないキーを作成するには、no-touch-required オプションを使用してキーペアを生成します。例えば:

$ ssh-keygen -O no-touch-required -t ed25519-sk
ノート: すべてのハードウェアトークンがこのオプションに対応しているわけではありません。YubiKey を使用している場合、ed25519-sk の鍵タイプにはファームウェアのバージョン 5.2.3 が必要です。[7]

さらに、sshd はデフォルトで no-touch-required キーを拒否します。このオプションで生成されたキーを許可するには、authorized_keys ファイル内の個々のキーに対してこのオプションを有効にします。

no-touch-required sk-ssh-ed25519@openssh.com AAAAInN... user@example.com

または、/etc/ssh/sshd_config を編集してシステム全体を対象にします

PubkeyAuthOptions none

ECDSA ベースのキーペアは、ecdsa-sk キータイプを使用して生成することもできますが、上記の #ECDSA セクションの関連する懸念事項が引き続き適用されます。

$ ssh-keygen -t ecdsa-sk

鍵の場所とパスフレーズを選択

ssh-keygen コマンドの実行時に、秘密鍵の名前と保存場所について尋ねられます。デフォルトでは、鍵は ~/.ssh/ ディレクトリに保存され、名前は使用する暗号化のタイプに合わせて付けられます。この記事に出てくるサンプルコードをそのまま使用できるようにするため、デフォルトの名前と場所を使うことを推奨します。

パスフレーズを求められたら、秘密鍵のセキュリティを考慮して推測が困難なものを入力してください。一般的には長くてランダムなパスワードの方が強度が高く、悪意ある人の手に渡っても解読されにくいでしょう。

パスフレーズを設定しないで秘密鍵を作成することも可能です。パスフレーズが不要なことは便利である一方、リスクも伴うということを理解してください。パスフレーズを設定しなかった場合、秘密鍵はディスク上に平文で保存されることになります。秘密鍵ファイルにアクセスすることさえできれば、誰でも (鍵を使って認証を行っている) SSH サーバーの認証を掻い潜ることができてしまいます。さらに、パスフレーズを設定しないということは、root ユーザーを無条件で信頼することになります。root ユーザーはファイルのパーミッションを回避していつでも秘密鍵ファイルにアクセスすることができます。

ノート: 以前は、秘密鍵のパスワードは安全でない方法でエンコードされていました: MD5 ハッシュの一回分だけです。OpenSSH 6.5 以降では、秘密鍵をエンコードするための新しい、より安全な形式を サポートしています。この形式は OpenSSH version 7.8 以降のデフォルトです。Ed25519 の鍵は常に新しいエンコーディング形式を使用しています。新しい形式にアップグレードするには、次のセクションで説明するように、 鍵のパスフレーズを変更するだけです。

鍵を変更せずに秘密鍵のパスフレーズを変更する

最初に作成した SSH 鍵のパスフレーズが好ましくない、あるいは変更しなくてはならない場合、ssh-keygen コマンドを使うことで、実際の鍵を変更することなくパスフレーズを変更することができます。これは、パスワードのエンコード形式を新しい標準に変更するためにも使用できます。

$ ssh-keygen -f ~/.ssh/id_rsa -p

複数の鍵の管理

複数の SSH ID がある場合、設定内で Match および IdentityFile ディレクティブを使用して、異なるホストまたはリモートユーザーに使用する異なる鍵を設定することができます。

~/.ssh/config
Match host=SERVER1
   IdentitiesOnly yes
   IdentityFile ~/.ssh/id_rsa_IDENTITY1

Match host=SERVER2,SERVER3
   IdentitiesOnly yes
   IdentityFile ~/.ssh/id_ed25519_IDENTITY2

他のオプションについては、ssh_config(5) を参照してください。

SSH 鍵をハードウェアトークンに保存する

SSH 鍵は、スマートカードや USB トークンなどのセキュリティ・トークンに保存することも可能です。この場合、秘密鍵はディスクに保存されるのではなく、トークン上に安全に保存されるという利点があります。セキュリティ・トークンを使用する場合、機密性の高い秘密鍵が PC の RAM 上に存在することはなく、暗号化処理はトークン自体で実行されます。また、暗号化トークンは、1 台のパソコンに縛られることなく、簡単にパソコンから取り外して持ち運び、他のパソコンで使用することができるという利点もあります。

ハードウェアトークンの例としては、以下のようなものがあります。

リモートサーバーに公開鍵をコピー

鍵ペアを生成したら、公開鍵をリモートサーバーにコピーして、SSH 鍵認証が使えるようにする必要があります。公開鍵のファイル名は秘密鍵のファイル名に .pub 拡張子を付けたものになります。秘密鍵は共有せず、ローカルマシンに残しておくようにしてください。

シンプルな方法

ノート: この方法はリモートサーバーが sh 以外のシェル (tcsh など) をデフォルトで使っている場合や OpenSSH が 6.6.1p1 より古い場合は失敗します。このバグレポート を参照。

鍵のファイルが ~/.ssh/id_rsa.pub の場合、次のコマンドを実行します。

$ ssh-copy-id remote-server.org

リモートマシンでユーザー名が異なる場合、サーバーの名前の前に @ とユーザー名を書きます。

$ ssh-copy-id username@remote-server.org

公開鍵のファイル名がデフォルトの ~/.ssh/id_rsa.pub ではない場合、/usr/bin/ssh-copy-id: ERROR: No identities found というエラーが表示されます。その場合、公開鍵の場所を明示してください。

$ ssh-copy-id -i ~/.ssh/id_ecdsa.pub username@remote-server.org

ssh サーバーがデフォルトの22番ポート以外を使っている場合、ポート番号を付して下さい。

$ ssh-copy-id -i ~/.ssh/id_ecdsa.pub -p 221 username@remote-server.org

手動方法

デフォルトで、OpenSSH では、公開鍵は ~/.ssh/authorized_keys と連結する必要があります。まず公開鍵をリモートサーバーにコピーしてください。

$ scp ~/.ssh/id_ecdsa.pub username@remote-server.org:

上記の例では scp によって公開鍵 (id_ecdsa.pub) をリモートサーバーのホームディレクトリにコピーしています。サーバーアドレスの最後にはかならず : を付けるのを忘れないで下さい。また、必要に応じて上記の例にある公開鍵の名前は置き換えるようにしてください。

リモートサーバー側では、(ディレクトリが存在しない場合) ~/.ssh ディレクトリを作成して authorized_keys ファイルに公開鍵を追記する必要があります。

$ ssh username@remote-server.org
username@remote-server.org's password:
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ cat ~/id_ecdsa.pub >> ~/.ssh/authorized_keys
$ rm ~/id_ecdsa.pub
$ chmod 600 ~/.ssh/authorized_keys

最後の2つのコマンドではサーバーから公開鍵ファイルを削除して、authorized_keys ファイルにパーミッションを設定して、所有者である貴方以外のユーザーが読み書きできないようにしています。

SSH エージェント

秘密鍵をパスフレーズで暗号化した場合、公開鍵認証を使って SSH サーバーに接続するたびに設定したパスフレーズを入力する必要があります。認証を進める前に秘密鍵を復号化するために sshscp が呼ばれるたびにパスフレーズが求められるのです。

SSH エージェントは復号化された秘密鍵をキャッシュして、あなたに代わって SSH クライアントプログラムに鍵を提出します。この場合、パスフレーズを入力するのは一度だけでよく、その時に秘密鍵がエージェントのキャッシュに追加されます。これは頻繁に SSH 接続を行う場合にとても便利です。

大抵、エージェントはログイン時に自動的に実行されるように設定され、ログインセッションの間はずっと実行し続けます。この効果を得るのに様々なエージェント、フロントエンド、設定が存在します。このセクションでは様々なソリューションを並べているので、必要に応じて選びとるようにしてください。

ssh-agent

ssh-agent は OpenSSH に含まれているデフォルトのエージェントです。直接使用することもできますし、後のセクションで触れている、フロントエンドのためのバックエンドとして使うこともできます。ssh-agent が実行されると、ssh-agent は自分をバックグラウンドにフォークして、使用する環境変数を出力します。

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-vEGjCM2147/agent.2147; export SSH_AUTH_SOCK;
SSH_AGENT_PID=2148; export SSH_AGENT_PID;
echo Agent pid 2148;

これらの変数を利用するには、eval コマンドを通してコマンドを実行してください。

$ eval $(ssh-agent)
Agent pid 2157
ヒント: 上記のコマンドを ~/.bash_profile スクリプトに追加すればログインシェルが起動した時に自動で実行されます。

ssh-agent を実行したら、秘密鍵をキャッシュに追加する必要があります:

$ ssh-add ~/.ssh/id_ecdsa
Enter passphrase for /home/user/.ssh/id_ecdsa:
Identity added: /home/user/.ssh/id_ecdsa (/home/user/.ssh/id_ecdsa)

秘密鍵が暗号化されている場合、ssh-add はパスフレーズを入力するように要求します。秘密鍵がエージェントに追加されたら、パスフレーズを入力することなく SSH 接続を行うことができるようになります。

ヒント: git を含むすべての ssh クライアントが、初回使用時に鍵をエージェントに保存するようにするには、~/.ssh/configAddKeysToAgent yes という設定項目を追加してください。他に指定できる値は confirmask および no (デフォルト) です。

鍵が必要になるまでパスフレーズの入力をしないようにするには、以下を ~/.bashrc に追加します:

if ! pgrep -u $USER ssh-agent > /dev/null; then
    ssh-agent > ~/.ssh-agent-thing
fi
if [[ "$SSH_AGENT_PID" == "" ]]; then
    eval $(<~/.ssh-agent-thing)
fi
ssh-add -l >/dev/null || alias ssh='ssh-add -l >/dev/null || ssh-add && unalias ssh; ssh'

ssh-agent プロセスが存在しない場合にプロセスが実行され、出力が保存されます。プロセスが既に存在する場合、キャッシュされた ssh-agent の出力を取得して必要な環境変数を設定します。また、必要なときは、ssh にエイリアスを作成してエージェントに鍵を追加し、それからエイリアスを削除します。この方法の欠点は git など、ssh 以外の秘密鍵を使用するコマンドでは鍵は追加されないということです。

後で述べるように、この問題を回避できる ssh-agent のフロントエンドや代替エージェントも多数存在します。

systemd ユーザーで ssh-agent を起動

systemd/ユーザー機能を使ってエージェントを起動することができます。~/.config/systemd/user フォルダに以下のユニットファイルを配置してください:

~/.config/systemd/user/ssh-agent.service
[Unit]
Description=SSH key agent

[Service]
Type=forking
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket" をシェルのスタートアップファイルに追加してください。例えば Bash の場合 .bash_profile です。その後、サービスを有効化・起動してください。

ssh エージェントの転送

ローカルの ssh-agent をリモートに 転送 するとき (たとえば、コマンドライン引数 ssh -A remote または設定ファイル内の ForwardAgent yes を介して)、リモートマシンが環境変数 SSH_AUTH_SOCK を上書きしないことが重要です。したがって、リモートマシンが前述の systemd ユニット を使用してエージェントを起動する場合、ユーザーが SSH 経由でログインするときに環境に SSH_AUTH_SOCK を設定しないでください。そうしないと、転送が失敗し、リモートマシン上で ssh-add -l を使用して既存のキーを確認するときにエラー (例:The agent has no identities) が表示される可能性があります。

たとえば、bash を使用する場合、.bashrc は次のようになります:

~/.bashrc
...
if [[ -z "${SSH_CONNECTION}" ]]; then
    export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"
fi
...

このように、SSH_AUTH_SOCK は、現在のセッションが SSH ログインではない場合にのみ設定されます。これが SSH セッションの場合、転送が機能するように、リモートマシン上の SSH_AUTH_SOCK がローカルマシンによって設定されます。

ssh-agent をラッパープログラムとして使う

ssh-agent を (X セッションごとに) 起動する別の方法は UC Berkeley Labs による ssh-agent チュートリアル に載っています。startx コマンドで X を起動する場合に、以下のように ssh-agentstartx の前に付けることができます:

$ ssh-agent startx

そのため、考える必要もなく、.bash_aliases ファイルまたは同等のファイルにエイリアスを置くことができます。

alias startx='ssh-agent startx'

このようにすることで、ログインセッション間で余計な ssh-agent インスタンスが浮遊する問題を回避することができます。まさに1つのインスタンスが、X セッション全体と共存し、死んでいくのです。

ノート: ssh-agent startx を呼び出す代わりに、~/.xinitrceval $(ssh-agent)を追加することもできます。

鍵をエージェントに即座に追加する方法については、以下の #ssh-add で x11-ssh-askpass を呼び出すを参照してください。

GnuPG エージェント

gpg-agent は OpenSSH エージェントプロトコルエミュレーションを持っています。必要な設定については、GnuPG#SSH エージェント を参照してください。

Keychain

Keychain はできる限りユーザーの手を煩わせることなく SSH 鍵の管理を楽にするために作られたプログラムです。ssh-agentssh-add の両方を動かすシェルスクリプトとして実装されています。Keychain の特徴として、複数のログインセッションで単一の ssh-agent プロセスを維持することができます。したがって、パスフレーズを入力するのはマシンを起動したときだけで済みます。

インストール

keychain パッケージをインストールしてください。

設定

警告: 2015-09-26 現在 -Q, --quick オプションには、再ログイン時に keychain が新しく生成された ssh-agent に切り替わるという予期せぬ副作用があり(少なくとも GNOME を使用しているシステムでは)、以前に登録した鍵をすべて再入力しなければなりません

シェルの設定ファイルに以下のような行を追加してください。例えば、Bash を使用している場合。

~/.bashrc
eval $(keychain --eval --quiet id_ed25519 id_rsa ~/.keys/my_custom_key)
ノート: ~/.bashrc が上流で推奨されている ~/.bash_profile の代わりに使われているのは、Arch ではログインシェルと非ログインシェルの両方で source されるため、テキストとグラフィックの両方の環境に適しているからです。これらの違いについては、Bash#実行を参照してください。

上記の例では

  • --eval スイッチは、最初の eval コマンドで評価される行を出力します。これにより、ssh クライアントがエージェントを見つけるために必要な環境変数が設定されます。
  • --quiet は出力を警告、エラー、ユーザープロンプトに制限します。

例にあるように、コマンドラインで複数の鍵を指定できます。keychain はデフォルトで ~/.ssh/ ディレクトリ内の鍵ペアを検索しますが、標準的でない場所にある鍵には絶対パスを指定します。また、--confhost オプションを使用して、~/.ssh/config で特定のホストに定義された IdentityFile 設定を検索し、これらのパスを使用して鍵を探すように keychain に通知することもできます。

他のシェルでの keychain の設定については、keychain --help または keychain(1) を参照してください。

Keychain をテストするには、新しいターミナルエミュレータを開くか、ログアウトしてセッションに戻ります。すると、$SSH_ASKPASS で設定したプログラムを使って、あるいはターミネル上で、指定した鍵のパスフレーズを入力するように求められます。

Keychain は連続ログイン時に同じ ssh-agent プロセスを再利用するため、次回ログイン時や新しい端末を開いたときにパスフレーズを入力する必要はありません。パスフレーズの入力は、マシンを再起動するたびに一度だけ行われます。

Tips

  • keychain は、公開鍵ファイルが秘密鍵と同じディレクトリに存在し、拡張子が .pub であることを期待します。秘密鍵がシンボリックリンクの場合、公開鍵はシンボリックリンクと一緒に、またはシンボリックリンクのターゲットと同じディレクトリにあります (この機能を使用するには、システム上で readlink コマンドが使用可能であることが必要です)。
  • グラフィカルプロンプトを無効にして、常に端末上でパスフレーズを入力する場合は、--nogui オプションを使用します。これにより、例えばパスワードマネージャから長いパスフレーズをコピーペーストすることができます。
  • 鍵のロック解除をすぐに要求されるのではなく、必要な時まで待ちたい場合は、--noask オプションを使用します。
ノート: Keychain は GPG の鍵も同じように管理することができます。デフォルトでは ssh-agent のみを起動しようとしますが、 --agents オプションを使ってこの動作を変更することができます (例: --agents ssh,gpg)。keychain(1) を参照してください。

x11-ssh-askpass

x11-ssh-askpass パッケージは、X セッションを実行する際にパスフレーズを入力するためのグラフィカルなダイアログを提供します。x11-ssh-askpasslibx11libxt ライブラリのみに依存し、x11-ssh-askpass の外観はカスタマイズが可能です。このプログラムは ssh-add プログラムによって起動され、復号化された鍵を ssh-agent にロードしますが、次の手順では、前述の Keychain スクリプトによって x11-ssh-askpass が起動されるように設定します。

keychainx11-ssh-askpass をインストールしてください。どちらも公式リポジトリに入っています。

~/.xinitrc ファイルを編集し、以下の行を追加します。必要であれば、秘密鍵の名前と場所を置き換えてください。これらのコマンドは、必ずウィンドウマネージャを起動する行の に記述してください。

~/.xinitrc
keychain ~/.ssh/id_ecdsa
[ -f ~/.keychain/$HOSTNAME-sh ] && . ~/.keychain/$HOSTNAME-sh 2>/dev/null
[ -f ~/.keychain/$HOSTNAME-sh-gpg ] && . ~/.keychain/$HOSTNAME-sh-gpg 2>/dev/null
...
exec openbox-session

上記の例では、1行目で keychain を起動し、秘密鍵の名前と場所を渡しています。もし keychain の起動が初めてでなければ、次の2行で $HOSTNAME-sh$HOSTNAME-sh-gpg の内容を読み込みます(存在する場合)。これらのファイルには、以前の keychain のインスタンスの環境変数が保存されています。

ssh-add で x11-ssh-askpass を呼び出す

ssh-add のマニュアルページでは、DISPLAY 変数の定義に加えて、SSH_ASKPASS にあなたの askpass プログラムの名前 (この場合 x11-ssh-askpass) を設定する必要があることを明記しています。Arch Linux のデフォルトインストールでは、x11-ssh-askpass のバイナリは /usr/lib/ssh/ に置かれ、ほとんどの人の PATH には入っていないことに留意してください。これは SSH_ASKPASS 変数を宣言するときだけでなく、テーマ設定するときにも少し面倒です。どこでもフルパスを指定しなければならないのです。この2つの不都合はシンボリックリンクによって同時に解決することができます。

$ ln -sv /usr/lib/ssh/x11-ssh-askpass ~/bin/ssh-askpass

これは ~/binPATH に入っていると仮定しています。これで .xinitrc でウィンドウマネージャを呼び出す前に、環境変数 SSH_ASKPASS を書き出すだけでよくなりました。

$ export SSH_ASKPASS=ssh-askpass

といったものが X resources に含まれることになります。

ssh-askpass*background: #000000

この方法は、上記の ssh-agent をラッパー・プログラムとして使う方法とうまく連動しています。ssh-agent startx で X を起動し、ssh-add をウィンドウマネージャのスタートアッププログラムのリストに追加します。

テーマ

x11-ssh-askpass ダイアログの外観は X resources を設定することでカスタマイズできます。x11-ssh-askpassホームページ にはいくつか サンプルテーマ が挙げられています。詳しくは x11-ssh-askpass のマニュアルページを見て下さい。

他のパスフレーズダイアログ

x11-ssh-askpass の代わりに他のパスフレーズダイアログプログラムを使うこともできます:

  • ksshaskpass は公式リポジトリからインストールできます。kdelibsAUR に依存しており KDE デスクトップ環境にうってつけです。
  • openssh-askpassqt4AUR ライブラリに依存しており公式リポジトリからインストールできます。

pam_ssh

pam_ssh プロジェクトは SSH 秘密鍵の Pluggable Authentication Module (PAM) を提供しています。このモジュールを使うことで SSH 接続のシングルサインオンができます。ログイン時に、伝統的なシステムパスワードの代わりに、もしくはそれに加えて、SSH 秘密鍵のパスフレーズを入力することができます。認証が完了したら、pam_ssh モジュールは ssh-agent を生成して復号化された秘密鍵をセッションの間だけ保存します。

tty ログインプロンプトでシングルサインオンを有効にしたいときは、Arch User Repository から非公式の pam_sshAUR パッケージをインストールしてください。

ノート: pam_ssh 2.0 では認証プロセスに使用する秘密鍵を ~/.ssh/login-keys.d/ 下に配置する必要があります。

秘密鍵ファイルのシンボリックリンクを作成して ~/.ssh/login-keys.d/ に配置します。以下の例の id_rsa をあなたの秘密鍵ファイルの名前に置き換えて下さい:

$ mkdir ~/.ssh/login-keys.d/
$ cd ~/.ssh/login-keys.d/
$ ln -s ../id_rsa

/etc/pam.d/login ファイルを編集して以下の例で太字でハイライトされているテキストを記述してください。これらの行の順番は重要で、ログインに影響します。

警告: PAM の設定を誤ると、システムがすべてのユーザーがロックアウトされた状態になる可能性があります。 変更を加える前に、PAM 設定がどのように機能するかを理解し、ロックアウトされて変更を元に戻す必要がある場合に備えて、Arch LiveCD などの PAM 設定ファイルにアクセスするためのバックアップ手段を理解しておく必要があります。 PAM 設定をさらに詳細に説明する IBMdeveloperWorks の記事が利用可能です。
/etc/pam.d/login
#%PAM-1.0

auth       required     pam_securetty.so
auth       requisite    pam_nologin.so
auth       include      system-local-login
auth       optional     pam_ssh.so        try_first_pass
account    include      system-local-login
session    include      system-local-login
session    optional     pam_ssh.so

上記の例では、最初にログイン認証が通常通り行われ、ユーザーパスワードの入力が促されます。認証スタックの最後に追加された auth 認証ルールは、~/.ssh/login-keys.d ディレクトリにある秘密鍵の復号化を試みるよう、 pam_ssh モジュールに指示を出します。try_first_pass オプションは pam_ssh モジュールに渡され、以前に入力されたユーザーパスワードを使用して SSH 秘密鍵を最初に復号化しようとするように指示します。ユーザーの秘密鍵のパスフレーズとユーザーパスワードが同じであれば、これは成功し、ユーザーは同じパスワードを 2 回入力するように要求されることはないはずです。秘密鍵のパスフレーズとユーザーパスワードが異なる場合、pam_ssh モジュールはユーザーパスワードの入力後に SSH パスフレーズを入力するようユーザーに促します。optional 制御値は、SSH 秘密鍵を持たないユーザーでもログインできるようにします。このように、pam_ssh の使用は、SSH 秘密鍵を持たないユーザーには透過的になります。

SLiMXDM のような X11 ディスプレイマネージャのような他のログイン手段を使用し、同様の機能を提供させたい場合、関連する PAM 設定ファイルを同様の方法で編集する必要があります。PAM をサポートしているパッケージは、通常 /etc/pam.d/ ディレクトリにデフォルトの設定ファイルを配置します。

pam_ssh の使用方法の詳細とオプションの一覧は pam_ssh(8) の man ページにあります。

SSH 鍵のロック解除に別のパスワードを使用する

鍵のパスフレーズを使うか、(異なる)ログインパスワードを使うかによって、SSH 鍵を解除するかしないかを決めたい場合は、/etc/pam.d/system-auth を以下のように変更します。

/etc/pam.d/system-auth
#%PAM-1.0

auth      [success=1 new_authtok_reqd=1 ignore=ignore default=ignore]  pam_unix.so     try_first_pass nullok
auth      required  pam_ssh.so      use_first_pass
auth      optional  pam_permit.so
auth      required  pam_env.so

account   required  pam_unix.so
account   optional  pam_permit.so
account   required  pam_time.so

password  required  pam_unix.so     try_first_pass nullok sha512 shadow
password  optional  pam_permit.so

session   required  pam_limits.so
session   required  pam_unix.so
session   optional  pam_permit.so
session   optional  pam_ssh.so

説明については、[8]を参照してください。

pam_ssh の既知の問題

pam_ssh プロジェクトの作業は頻繁には行われず、提供される文書もまばらです。パッケージ自体には記載されていない制限事項があることを認識しておく必要があります。

  • pam_ssh のバージョン 2.0 より前のものは、ECDSA (楕円曲線) 暗号の新しいオプションを採用した SSH 鍵をサポートしていません。もし、それ以前のバージョンの pam_ssh を使っているならば、RSA か DSA 鍵を使わなければなりません。
  • pam_ssh によって生成された ssh-agent プロセスは、ユーザログインの間持続しません。GNU Screen セッションをログイン後もアクティブにしておきたい場合、 Screen セッションに再接続すると、ssh-agent と通信できなくなることに気づくかもしれません。これは、GNU Screen 環境とその子環境は、GNU Screen が起動されたときに存在していた ssh-agent のインスタンスをまだ参照しており、以前のログアウトで強制終了されたからです。Keychain フロントエンドは、ログインの間 ssh-agent プロセスを存続させることでこの問題を回避しています。

pam_exec-ssh

pam_ssh の代わりに pam_exec-sshAUR を使うことができます。これは pam_exec を使うシェルスクリプトです。設定に関するヘルプは アップストリームにあります。

GNOME Keyring

GNOME デスクトップを使用する場合、GNOME Keyring ツールを SSH エージェントとして使うことができます。詳しくは GNOME Keyring の記事を見て下さい。

Kwallet を使って SSH 鍵を保存

kwallet を使って SSH 鍵を保存する方法は、KDE Wallet#KDE ウォレットを使って ssh 鍵のパスフレーズを保存を見て下さい。

KeePass2 と KeeAgent プラグイン

KeeAgentKeePass のプラグインで、SSH 鍵を KeePass データベースに保存することができ、他のプログラムから SSH 認証に使用されます。

  • PuTTY と OpenSSH の秘密鍵フォーマットをサポート。
  • Linux/Mac のネイティブの SSH エージェントと Windows の PuTTY で動作。

KeePass#プラグインのインストールを見て、keepass-plugin-keeagent パッケージをインストールしてください。新しい機能が早く追加されるベータ版も存在します: keepass-plugin-keeagent-betaAUR[リンク切れ: パッケージが存在しません]

KeePassXC

KeePass の KeePassXC フォークは デフォルトで SSH エージェントとしての使用をサポートしています。また、KeeAgent のデータベース形式とも互換性があります。

トラブルシューティング

サーバーによって無視される鍵

SSH サーバーが鍵を無視しているように見える場合は、関連するすべてのファイルに適切なパーミッションが設定されていることを確認してください。
ローカルマシンの場合:

$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/key

リモートマシンの場合:

$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys

リモートマシンの場合は、ターゲットユーザーのホームディレクトリに正しいアクセス許可があることも確認します(グループなどが書き込み可能であってはなりません)。

$ chmod go-w /home/target_user
  • パーミッションの設定で問題が解決しないときは sshd_configStrictModes を一時的に no に設定してみてください。StrictModes off で認証が成功する場合、おそらくファイルのパーミッションにまだ問題が存在します。
  • ~/.ssh/authorized_keys のキーが正しく入力されていることを確認し、1 行のみを使用してください。
  • リモートマシンが使用しているタイプの鍵をサポートしていることを確認してください。サーバーが ECDSA 鍵をサポートしていない場合、RSA あるいは DSA 鍵を使ってみてください。
  • それでも認証できない場合、sshd をデバッグモードで実行して接続時の出力を確認してください:
# /usr/bin/sshd -d
  • id_rsa_server など、鍵に別の名前を付けた場合は、-i オプションで接続する必要があります。
$ ssh -i id_rsa_server user@server

エージェントが操作を拒否しました

秘密鍵にパスワードが必要な場合 (または、たとえば PIN 付きのハードウェアキーがある場合)、ssh-agent にパスワードが提供されていない場合、ssh は失敗します:

sign_and_send_pubkey: signing failed for ECDSA-SK user@host from agent: agent refused operation

この潜在的な原因の 1 つは、ssh-agent がパスワードの入力を要求できないことです。ssh-agent がディスプレイサーバー (DISPLAY 環境変数経由) または TTY にアクセスできることを確認します。

ハードウェア認証システムを使用している場合、別の原因としては、キーの故障またはプラグが抜けていることが考えられます。

現在、-O verify-required で作成された ED25519-sk や ECDSA-SK などの認証キーを使用すると、"agent refused operation" エラーが発生する未解決の バグ が存在します。この問題を回避するには、-o IdentityAgent=none オプションを ssh コマンドに使用するか、関連するホストの ssh_config ファイルに追加します。

Host myserver.tld
    IdentityAgent none

参照