Happy ssh life with ssh-agent

ssh は便利だ。ほかのコンピュータにアクセスする方法として、安全で手軽であるだけでなく、各種スクリプトの中に組み込んだり、他のプログラムから呼び出したりすることで高度な動作を簡単に実現できる。また、TCP のポートフォワーディングが設定できるため、たいていのプログラムを簡単にリモートアクセス対応にできる。

しかし、面倒なことがひとつだけある。パスワードの入力だ。毎回毎回パスワードを入力しなければならないのは本当に面倒だ。特に、ファイルコピーだとか CVS アクセスだとか、他のプログラムから利用する場合には、いやになるぐらい何度もパスワードを入力しなければいけない。

ssh はパスワード以外の認証方法をサポートしている。特に有名なのが公開鍵方式であるが、これも鍵を守るためのパスフレーズと呼ばれるキー入力が必要だ。これは通常のパスワードより短いパスフレーズでは意味がない、とされている(だからパス「フレーズ」)。かといって、長いパスフレーズを使うと、毎回打ち込むのはやってられない。パスワードなしで ssh ログインしたいんだ、なんていってパスフレーズなしの秘密鍵を作ったりしている人もいるが、これはパスワードをファイルに書いておくのよりも危険な行為である。

そんなときには ssh-agent を使うと便利だ。これは、現在のセッションに限り、パスフレーズをデコードした秘密鍵を保持するものである。パスフレーズやデコード結果はメモリ上にしか保持しないし、いっさい送信もしない(必要な計算は全部 agent 内部でする)ので、そこそこ安全である。しかも、これさえちゃんと動いていれば ssh がパスワードなしで使えるわけで、便利さという点ではかなりグッドである。

ssh-agent 自体の使い方は簡単である。どっちかというと公開鍵のセットアップのほうが難しい。手順は次の通りだ。

  1. ローカル(ログイン元のマシン)で鍵ペアを生成する。
  2. リモート(ログイン先のマシン)に公開鍵をコピーし、設定する。
  3. ここでとりあえず鍵がちゃんと設定されたかテスト。
  4. ssh の設定ファイルで入力量を減らす。
  5. ssh-agent が自動起動するよう設定する。
  6. 幸せな ssh ライフをエンジョイする。

まず最初の鍵ペアの生成だ。ローカル(ログイン元のマシン)で ssh-keygen コマンドを実行し、鍵ペアを生成しよう。以下は OpenSSH の場合 (cygwin や、たいていの Linux はこれです) である。

$ ssh-keygen -t dsa<CR>
Generating public/private dsa key pair.
Enter file in which to save the key (/home/t/.ssh/id_dsa): <CR>
Enter passphrase (empty for no passphrase): <パスフレーズ><CR>
Enter same passphrase again: <パスフレーズ><CR>
Your identification has been saved in /home/t/.ssh/id_dsa.
Your public key has been saved in /home/t/.ssh/id_dsa.pub.
The key fingerprint is:
30:de:5a:1e:46:16:0b:b4:d3:7f:4d:6b:e4:15:45:e8 t@aladdin

これで、DSA 鍵のペアが生成され、ホームディレクトリの .ssh/id_dsa に秘密鍵が、.ssh/id_dsa.pub に公開鍵が格納された。秘密鍵は文字通り秘密であり、このコンピュータから出ることはない。

OpenSSH の公開鍵は次のようなテキストになっている。スペースの都合上、改行をはさんでいるが、本当は1行だ。

$ cat .ssh/id_dsa.pub
ssh-dss AAAAB3NzaC1kc3MAAACBAM+sC05aW4r14jX+js5+Tz4ncrZ51StAwr9L5FqCsq4VyRisntGV
aiyYiXBxNoWoQDWcnLPNiEker7sDitlLKskn1eVEAeC2d10rlY7A9omxRgTpVAuZ0/jH5uaf837+fGKV
FpjDb5HuNR9QNAboNQcUO0dUaMMm4SAt6R/rwunlAAAAFQDrg9RZHWMc/85jqDErpOHZk4aYGQAAAIB+
g2GYJGAuoViwsjDvKiHpia4qQ5YXiI+s7L8atPNCtTiL3K59uu4uJWTSk1GTGbDwnTzAD2fyYdin/q8G
//IAa+rBOAikLqGHPx8YsLrgSrX7EyoCKdKBXaWuZFvCW7GuOaSy/rjTBBUPCAKVUh4ZSN6RLO5ykVKW
87KkVhg/dAAAAIAmFssstIV3V+Y7a7mz8V+rpNTSEwKWdf1HpY54SKiKunoN6Bexyb4TRGXmtt32AxKD
6nC4TpLn+eiUqR3POShBGqqQd6J8x6fJlj3mUCw4TIqoTIEdx0k7LK5rAGAtwy0SXcokw7QurCq/93V0
Qf8Fgqt3lKtNrY++f+0dvZq5Sw== t@aladdin

次のステップは、リモート(ログイン先のマシン)に公開鍵をコピーして設定することだ。リモート側も OpenSSH であれば、.ssh/authorized_keys というファイルに上記の公開鍵の行を追加すればいい。kterm など使っていれば、ログイン先でこのファイルをエディタで開いて追加すればいいのだが、cygwin の端末ウィンドウだと改行が勝手にはさまっちゃうのでめんどくさい。よって次を推奨する。

$ cat .ssh/id_dsa.pub | ssh -l mak ariel "bash -Cc 'cat >> .ssh/authorized_keys'"
mak@ariel's password: <通常のパスワード><CR>

ここでは、ariel がリモートマシンの名前、mak がリモートマシンでのログイン名である。bash うんちゃらは、追加リダイレクト >> を間違って普通のリダイレクト > にしたときに、以前の authorized_keys の中身を消しちゃわないようにするものである。

これで鍵のセットアップは完了したはずだが、一応テストしよう。いつもと同じように ssh でログインすると、パスワードのかわりにパスフレーズを聞いてくるはずだ。さっき作った鍵のパスフレーズでログインできることを試しておこう。

$ ssh -l mak ariel
Enter passphrase for key '/home/t/.ssh/id_dsa': <さっきのパスフレーズ><CR>

Linux ariel 2.4.19 #9 Tue Jan 21 18:48:26 JST 2003 i686 unknown unknown GNU/Linux
mak@ariel:~$ exit
Connection to ariel closed.

次に、ssh の設定ファイルだ。毎回、長いマシン名とか、ユーザー名とか入力するのは大変ではなかろうか。次のようなファイルを .ssh/config においておくと、手間が大幅に省ける。

Compression Yes

Host ariel
Hostname ariel.snowelm.com
User mak
ForwardAgent Yes

Host ett
Hostname ett.sat.t.u-tokyo.ac.jp
User makino

こうすると、ssh ariel とするだけで、ssh -l mak ariel.snowelm.com とするのと同じ効果になる。さらに、データ圧縮をオンにし、ariel の場合はエージェントの転送(ログイン先からさらに別のマシンにログインするときに同じエージェントが使える)もオンにしている。

最後に、ssh-agent の設定をして、パスフレーズの入力を楽にしよう。 cygwin では、次の設定を .bash_profile か .bashrc に書いておくのをおすすめする。これは、ssh-agent を常駐させて、複数の cygwin ウィンドウを開いても最初の1回しかパスフレーズを聞いてこないようにするものだ。

echo -n "ssh-agent: "
source ~/.ssh-agent-info
ssh-add -l >&/dev/null
if [ $? == 2 ] ; then
	echo -n "ssh-agent: restart...."
	ssh-agent >~/.ssh-agent-info
	source ~/.ssh-agent-info
fi

if ssh-add -l >&/dev/null ; then
	echo "ssh-agent: Identity is already stored."
else
	ssh-add
fi

これで、ウィンドウを開いてみてほしい。

ssh-agent: bash: /home/t/.ssh-agent-info: No such file or directory
ssh-agent: restart....Agent pid 2348
Enter passphrase for /home/t/.ssh/id_dsa: <さっきのパスフレーズ><CR>
Identity added: /home/t/.ssh/id_dsa (/home/t/.ssh/id_dsa)

面倒なときな、パスフレーズを省略してもいい。でも、パスフレーズをちゃんと入力しておくと、そのあと幸せな ssh ライフが送れる。下のように、ssh コマンドを入力するだけで、即ログインできるのだ。

$ ssh ariel

Linux ariel 2.4.19 #9 Tue Jan 21 18:48:26 JST 2003 i686 unknown unknown GNU/Linux
mak@ariel:~$ exit
Connection to ariel closed.

まあ、もちろんこのマシンを誰かに使われたりしたらセキュリティホールになるわけだが、面倒がって短いパスワードを使ったり、パスフレーズなしの鍵を使ったりすることに比べればずっと安全である。しかもとっても便利。これで幸せな ssh ライフを送れることは間違いないであろう。

ついでに。cygwin で EUC 環境のマシンにログインするときには、次のコード変換プログラムを使うと便利です。 http://iwa.ath.cx/software/cygwin/cocot.html