「SSH 鍵」の版間の差分
Kusanaginoturugi (トーク | 投稿記録) (校正(でき・出来)) |
Kusanaginoturugi (トーク | 投稿記録) |
||
1行目: | 1行目: | ||
− | [[Category: |
+ | [[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 で導入されたもので、鍵の指紋を視覚的に識別しやすくするためのものです。
-C
スイッチを使って公開鍵にコメントフィールドを追加して、~/.ssh/known_hosts
や ~/.ssh/authorized_keys
などの場所や ssh-add -L
の出力で公開鍵を簡単に識別できるようにすることができます。例:
$ ssh-keygen -C "$(whoami)@$(hostname)-$(date -I)"
上記のコマンドで、どのマシンとユーザーで作成した鍵なのか、作成日時はいつなのかというコメントが追加されます。
認証鍵の種類を選択
OpenSSH はいくつかの署名アルゴリズム (認証鍵用) をサポートしていますが、それらは利用する数学的性質によって 2つのグループに分けることができます。
楕円曲線暗号 (ECC) アルゴリズムは、公開鍵暗号方式に最近になって追加されたアルゴリズムです。その主な利点の一つは、より小さな鍵で同じレベルのセキュリティを提供できることで、計算負荷の少ない操作(鍵の生成、暗号化、復号化の高速化)と、ストレージや伝送要件の低減を実現します。
OpenSSH 7.0 では、発見された脆弱性のために DSA 鍵のサポートは廃止され、無効になりました。したがって、暗号システムの選択は RSA または 2 種類の ECC のうちの 1 つになります。
#RSA 鍵は最も移植性が高く、#Ed25519 は最もセキュリティが高いが、クライアントとサーバの最新版が必要である[1]。#ECDSAは Ed25519 より互換性が高いが(それでも RSA より劣るが)、その安全性には疑惑がある(後述)。
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種類の懸念があります。
- 政治的懸念、NSA が進んでソフトウェアやハードウェア部品、公表されている標準規格にバックドアを挿入していることが明らかになった後、NIST が作成した曲線の信頼性が疑問視されています、著名な暗号技術者が NISTの曲線の設計方法について疑問を表明しており、自主的な汚染は過去にすでに証明されています。
- 技術的な懸念として、規格を適切に実装することの難しさや、遅さなど設計上の欠陥があり、十分な注意を払わない実装ではセキュリティが低下します。
これらの懸念は、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 やその他の手段で接続されたハードウェアトークンを、 秘密鍵と並ぶ第二の要素として機能させることができるようにするものです。
ハードウェアトークンサポートのため、libfido2 が必要です。
互換性のある 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
さらに、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 ユーザーはファイルのパーミッションを回避していつでも秘密鍵ファイルにアクセスすることができます。
鍵を変更せずに秘密鍵のパスフレーズを変更する
最初に作成した 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 台のパソコンに縛られることなく、簡単にパソコンから取り外して持ち運び、他のパソコンで使用することができるという利点もあります。
ハードウェアトークンの例としては、以下のようなものがあります。
- YubiKey#SSH notes FIDO/U2F 鍵の OpenSSH ネイティブサポート
- YubiKey#SSH keys
- Trusted Platform Module#SSH 鍵のセキュア化
リモートサーバーに公開鍵をコピー
鍵ペアを生成したら、公開鍵をリモートサーバーにコピーして、SSH 鍵認証が使えるようにする必要があります。公開鍵のファイル名は秘密鍵のファイル名に .pub
拡張子を付けたものになります。秘密鍵は共有せず、ローカルマシンに残しておくようにしてください。
シンプルな方法
鍵のファイルが ~/.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 サーバーに接続するたびに設定したパスフレーズを入力する必要があります。認証を進める前に秘密鍵を復号化するために ssh
や scp
が呼ばれるたびにパスフレーズが求められるのです。
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
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 接続を行うことができるようになります。
鍵が必要になるまでパスフレーズの入力をしないようにするには、以下を ~/.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-agent
を startx
の前に付けることができます:
$ ssh-agent startx
そのため、考える必要もなく、.bash_aliases
ファイルまたは同等のファイルにエイリアスを置くことができます。
alias startx='ssh-agent startx'
このようにすることで、ログインセッション間で余計な ssh-agent
インスタンスが浮遊する問題を回避することができます。まさに1つのインスタンスが、X セッション全体と共存し、死んでいくのです。
鍵をエージェントに即座に追加する方法については、以下の #ssh-add で x11-ssh-askpass を呼び出すを参照してください。
GnuPG エージェント
gpg-agent は OpenSSH エージェントプロトコルエミュレーションを持っています。必要な設定については、GnuPG#SSH エージェント を参照してください。
Keychain
Keychain はできる限りユーザーの手を煩わせることなく SSH 鍵の管理を楽にするために作られたプログラムです。ssh-agent と ssh-add の両方を動かすシェルスクリプトとして実装されています。Keychain の特徴として、複数のログインセッションで単一の ssh-agent プロセスを維持することができます。したがって、パスフレーズを入力するのはマシンを起動したときだけで済みます。
インストール
設定
シェルの設定ファイルに以下のような行を追加してください。例えば、Bash を使用している場合。
~/.bashrc
eval $(keychain --eval --quiet id_ed25519 id_rsa ~/.keys/my_custom_key)
上記の例では
--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
オプションを使用します。
x11-ssh-askpass
x11-ssh-askpass パッケージは、X セッションを実行する際にパスフレーズを入力するためのグラフィカルなダイアログを提供します。x11-ssh-askpass は libx11 と libxt ライブラリのみに依存し、x11-ssh-askpass の外観はカスタマイズが可能です。このプログラムは ssh-add プログラムによって起動され、復号化された鍵を ssh-agent にロードしますが、次の手順では、前述の Keychain スクリプトによって x11-ssh-askpass が起動されるように設定します。
keychain と x11-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
これは ~/bin
が PATH
に入っていると仮定しています。これで .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-askpass は qt4AUR ライブラリに依存しており公式リポジトリからインストールできます。
pam_ssh
pam_ssh プロジェクトは SSH 秘密鍵の Pluggable Authentication Module (PAM) を提供しています。このモジュールを使うことで SSH 接続のシングルサインオンができます。ログイン時に、伝統的なシステムパスワードの代わりに、もしくはそれに加えて、SSH 秘密鍵のパスフレーズを入力することができます。認証が完了したら、pam_ssh モジュールは ssh-agent を生成して復号化された秘密鍵をセッションの間だけ保存します。
tty ログインプロンプトでシングルサインオンを有効にしたいときは、Arch User Repository から非公式の pam_sshAUR パッケージをインストールしてください。
秘密鍵ファイルのシンボリックリンクを作成して ~/.ssh/login-keys.d/
に配置します。以下の例の id_rsa
をあなたの秘密鍵ファイルの名前に置き換えて下さい:
$ mkdir ~/.ssh/login-keys.d/ $ cd ~/.ssh/login-keys.d/ $ ln -s ../id_rsa
/etc/pam.d/login
ファイルを編集して以下の例で太字でハイライトされているテキストを記述してください。これらの行の順番は重要で、ログインに影響します。
/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 秘密鍵を持たないユーザーには透過的になります。
SLiM や XDM のような 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 プラグイン
KeeAgent は KeePass のプラグインで、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_config
でStrictModes
を一時的に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
参照
- OpenSSH 鍵管理 Part 1 Part 2 Part 3
- Secure Secure Shell