ssh agent forwardingをscreenの中で使う
sshでログインしたホストAから、さらに別のホストBにsshで接続する際に、ssh agent forwardingという便利な仕組みがある。ssh agent forwardingを使えば、ホストAのログインに使用したprivate key/public keyのペアを、ホストBへのssh接続に利用できる上に、パスフレーズはホストAへのログインの際に1回だけ入力すればOK。
仕組みとしては、ホストAからホストBへのssh接続の際に、ホストBからの鍵要求をホストAがログイン元へ転送することで、ホストAのログインに使用した鍵ペアの利用を可能にしている。OpenSSHの場合、ssh agent forwardingにおける情報のやりとりはUNIX domain socketを使って行っている。UNIX domain socketは、/tmp/ssh-"ランダムな文字列"/agent."sshdのPID"という名前でsshdが用意して、環境変数SSH_AUTH_SOCKに格納される。
この仕組みは、screenと非常に相性が悪い。screenをdetachしてログアウトしてから、再びログインすると、環境変数SSH_AUTH_SOCKは以前のままで、UNIX domain socketだけが再作成されるため、agent forwardingができなくなる。
これじゃ困るので、quick hack。環境変数は固定のファイル名にしておいて、そこから実際のUNIX domain socketへsymlinkを張ってやる方針で対応することにした。うちはzshの.zloginでscreenを起動しているので、screen起動直前にsymlinkの処理を追加した。
agent="$HOME/tmp/.ssh-agent-`hostname`" if [ -S "$agent" ]; then export SSH_AUTH_SOCK=$agent elif [ ! -S "$SSH_AUTH_SOCK" ]; then export SSH_AUTH_SOCK=$agent elif [ ! -L "$SSH_AUTH_SOCK" ]; then ln -snf "$SSH_AUTH_SOCK" $agent && export SSH_AUTH_SOCK=$agent fi
二重ログイン対策として、symlink先にすでにsocketがある場合は何もしないことにした。最初にログインしていたsshdがいなくなると、symlink先が行方不明になるけど、うちじゃあんまり二重ログインしないから割り切った。これでsshした先からscpしたりsvnしたりするのが楽になったぞ、と。