GNU screen で ssh-agentを使うとおかしくなる問題から色々やってみた
新しくウィンドウを開くとssh-agentのソケット名が変わったりパスワードを入力するのが難しかったり期限切れにできなかったりと、色々大変である。
^A c でウィンドウ開いてssh host、直接screen ssh hostなどで、生存期間内ならパスフレーズなし、期限切れならそこで入力、としたい。
とりあえずssh-agentを使う方法とgpg-agentを使う方法があり、それぞれにsystemdを使う方法と.bashrcなどで自力でやる方法があったが、結局ssh-agentにした。
openssh-client=1:8.2p1-4
systemd=245.5-2
ssh-agent
生存期間を指定すると毎度ssh-addを動かさないといけなくなる。
色々悩んだ結果、sshのラッパー書くことにした。
#!/bin/sh ssh-add -l > /dev/null || ssh-add -t 600 /usr/bin/ssh @$
ssh-agentをどこで起動するか、だが openssh-client パッケージにssh-agent.serviceがあるので利用する。
systemctl enable --user ssh-agent.service
すると、[Install]がないためenableにできない。
なので
systemctl edit --user ssh-agent.service
[Install] WantedBy=default.target
を追加する。(新規ファイル)
その後
systemctl enable --user ssh-agent.service
で追加。新しくユーザーセッションが始まれば起動される。
あとは、SSH_AUTH_SOCKを固定にするため、.bashrcで指定する。
... [ -z ”$PS1” ] && return ... export SSH_AUTH_SOCK=/run/user/$(id -u)/openssh_agent if [[ ! $TERM =~ screen*|dumb ]]; then ~/bin/ssh -V 2> /dev/null screen -RR -D fi
これで普通にログインするとssh-add用のパスワードを聞いてきた後、screenが立ち上がり、既にセッションがあればアタッチする。(-RDDオプション)
欠点はscreen動かしたくない時(コンソールとか)にも動いてしまうこと。
生存期間が過ぎていればパスワード入力時にctrl-Cで止めることは可能。
loginctl
テストしているとssh-agentがいっぱい動いたりキャッシュがあったりなかったりでよくわからなくなってくる。
そこで、
sudo loginctl terminate-user username
とすると、usernameのプロセスがまとめて消える。
(もちろんログアウトされる)
gpg-agent
gpg-agentはsudoのように認証後しばらく保持して、10分後に使うときは再度パスワードの入力を求める、などができるんだけど、このパスワード入力がpinentryを使用するのだが、これに問題がある。
どこに表示するか、をGPG_TTYに登録する必要があるのだが、screen上で
screen ssh server
などとやると新しい窓が開いてsshしようとするのだが、GPG_TTYが前の窓のままなので戻ってパスワードを入力する必要があったりする。
かつこのパスワード入力はCtrl-Cとか押すとその後表示がおかしくなったりそもそも中止できなかったり、どの窓で入力待ちをしているのかわからなくなったりで非常に使いづらい。
一応、やったことを残しておく。
... [ -z ”$PS1” ] && return ... if [ -x /usr/bin/gpg-agent ]; then export GPG_TTY=$(tty) gpg-connect-agent updatestartuptty /bye export SSH_AUTH_SOCK=”$(gpgconf --list-dirs agent-ssh-socket)” fi
pinentry-program /usr/bin/pinentry-tty enable-ssh-support default-cache-ttl 600 max-cache-ttl-ssh 1800
5月11日追記
~/bin/ssh みたいなことをしなくても、
~/.ssh/config に
AddKeysToAgent yes
と書けばよかったみたい。
有効期限はssh-agentに-t 有効期限でいいようだ。
ssh-agent.serviceは、システムの物を再利用するより新しく作った方が良さげ。
[Unit] Description=OpenSSH Agent Documentation=man:ssh-agent(1) Wants=dbus.socket After=dbus.socket [Service] Type=simple Environment=SSH_AUTH_SOCK=%t/openssh_agent ExecStart=/usr/bin/ssh-agent -D -t 600 -a $SSH_AUTH_SOCK [Install] WantedBy=default.target
コメントを残す