Skip to content

Instantly share code, notes, and snippets.

@takeru
Last active February 26, 2024 00:48
Show Gist options
  • Save takeru/d8778402fed39a6fa3c13936cd189ad6 to your computer and use it in GitHub Desktop.
Save takeru/d8778402fed39a6fa3c13936cd189ad6 to your computer and use it in GitHub Desktop.
ssh-agent-forward tmux

et/vscodeでgit pullするとssh-agentがなんかへんなときがある

  • いにしえのscreen時代からのssh-agentが変にならない設定
    • なにしてるかわからん
  • moshがいいなってときもあったけどscreen->tmuxになって、いまはet+tmuxをつかってる
    • moshはagent-forward/port-forwardできないから
  • なんかへんなときがある
    • etつかってるとなんかへんなときがあるような
    • vscodeのターミナルも使いだして、なんかへんなときがふえたような?
    • てきとうに再接続してごまかしてる

今の設定(.zshrc)

agent="$HOME/.ssh/agent"
if [ -S "$SSH_AUTH_SOCK" ]; then
    case $SSH_AUTH_SOCK in
    # /tmp/*/agent.[0-9]*)
    /run/user/*/vscode-ssh-auth-sock-*|/tmp/et_forward_sock_*/sock)
        ln -snf "$SSH_AUTH_SOCK" $agent && export SSH_AUTH_SOCK=$agent
    esac
elif [ -S $agent ]; then
    export SSH_AUTH_SOCK=$agent
else
    echo "no ssh-agent"
fi
  • zshrcにこれが入ってた。
  • vscode/etにあわせてパスが改造されてる。
  • zshひらくときに、
    • 元の$SSH_AUTH_SOCK -> $HOME/.ssh/agentにln -s
    • SSH_AUTH_SOCKに$HOME/.ssh/agentをセット
  • いつ?
    • .zshrcが読まれるとき
    • vscode/etでログインしたとき
    • tmuxであたらしいペイン開いたとき
    • SSH_AUTH_SOCKが "-S FILE FILE exists and is a socket"
      • symlinkでも先がsocketならtrue
[[ $SSH_AUTH_SOCK != $HOME/.ssh/sock && -S $SSH_AUTH_SOCK ]] \
    && ln -snf "$SSH_AUTH_SOCK" "$HOME/.ssh/sock" \
    && export SSH_AUTH_SOCK="$HOME/.ssh/sock"

ssh-agentの基本

https://smallstep.com/blog/ssh-agent-explained/

ssh-agentはなにをしているのか。忘れるので書いておく。

tkrmbp % env | grep SSH
SSH_AUTH_SOCK=/var/folders/j_/vbwswll565d0jpmxmbvdjj180000gn/T//ssh-1O8YRZljvxhy/agent.1177
SSH_AGENT_PID=1178
  • ssh-agentはメモリに公開鍵+秘密鍵を保持して常駐している
    • ssh-agent起動時にパスフレーズをいれて、鍵をメモリにロードする
    • SSH_AUTH_SOCK(UNIXドメインソケット)で待っているサーバ
  • sshは、SSH_AUTH_SOCKを利用してメッセージに署名してもらう
    • sshするときには、パスフレーズをいれなくていいのはこのため

ssh-agentを利用してsshするとき

  • ssh-agentが、SSH_AUTH_SOCKで起動しているとき、
  • sshは、SSH_AUTH_SOCKを利用してssh-agentに署名してもらい、serverとハンドシェイクし接続する

ssh -Aするとき

  • clientでssh-agentが、SSH_AUTH_SOCK(client)で起動しているとき、
  • sshはSSH_AUTH_SOCK(client)をserverに"forward"する
    • 鍵を送るのではない
    • SSH_AUTH_SOCK(client) <- SSH_AUTH_SOCK(server)のポートフォワード(のようなもの?)
  • serverのsshdは、UNIXドメインソケットのファイルを作って、そのパスをSSH_AUTH_SOCK(server)にセットしてshellを起動
  • ここ(今接続したserverのshell)で、sshするとSSH_AUTH_SOCK(server)を利用して署名しようとする。
  • SSH_AUTH_SOCK(server)は、接続元clientのssh-agentに"forward"されているので、
  • serverのsshが、clientで起動しているssh-agentを利用することになる。

git pullするとき

  • gitがSSH_AUTH_SOCKを利用してssh-agentをつかう
  • 上のsshとおなじ

ssh+screen/tmuxでの問題と対策

sshで再接続した後に、tmux -aでアタッチするとダメ

  • sshで接続(ssh接続A)し、SSH_AUTH_SOCK=/tmp/aaaaaがセットされる。
  • tmuxを起動し作業する。
    • SSH_AUTH_SOCK=/tmp/aaaaaを利用して、clientのssh-agentを利用できる
  • ssh接続Aが切れる
    • この時点で/tmp/aaaaaが消える
  • sshで接続(ssh接続B)し、SSH_AUTH_SOCK=/tmp/bbbbbがセットされる。
  • tmux -aでアタッチして作業する。
    • SSH_AUTH_SOCK=/tmp/aaaaaのままなので、/tmp/bbbbb経由でclientのssh-agentを利用できない

対策

  • sshで接続するたびに
    • SSH_AUTH_SOCK=/tmp/xxxxx/agent.xxx -> ~/.ssh/agent にシンボリックリンク
    • SSH_AUTH_SOCK=~/.ssh/agentにする
  • 最後に接続されたssh接続のSSH_AUTH_SOCKが使われる
    • sshで再接続して、tmux -a した後でもOK

sshで複数回接続して、後に接続したほうが切れるとダメ

  • sshで接続(ssh接続A)し、SSH_AUTH_SOCK=/tmp/aaaaa/agent.aaa
    • ln -s /tmp/aaaaa/agent.aaa -> ~/.ssh/agent
    • SSH_AUTH_SOCK=~/.ssh/agent
  • sshで接続(ssh接続B)し、SSH_AUTH_SOCK=/tmp/bbbbb/agent.bbb
    • ln -s /tmp/bbbbb/agent.bbb -> ~/.ssh/agent
    • SSH_AUTH_SOCK=~/.ssh/agent
  • ssh接続Aでもssh接続BでもSSH_AUTH_SOCK=~/.ssh/agent 経由で/tmp/bbbbb/agent.bbbが利用される
  • ssh接続Bが切れる
    • /tmp/bbbbb/agent.bbbが消える
    • SSH_AUTH_SOCK=~/.ssh/agent も使えなくなる
  • ssh接続Aでもssh-agentが利用できなくなる

どうすればいいか

  • 常に、SSH_AUTH_SOCK=~/.ssh/agent が有効になるように設定する
  • 「最後に接続したssh接続のSSH_AUTH_SOCKを使う」はうまくいってない

どうなってるのか

et

  • etのコネクション復帰時にはSSH_AUTH_SOCKはどうなる?
  • どうなってるのか
  • バックエンドで接続が復帰した場合もSSH_AUTH_SOCKが生きてる気がする★★★
    • だめになっちゃうのは他のコネクションで共有のシンボリックリンクを書き換えたあと切れてるからでは?
    • たぶん「他のコネクション == vscode」★★★

vscode

  • リモート機能使ってると勝手にsshしてるとおもうけど大丈夫?
  • どうなってるのか
    • zshrcにログ仕込んでみても余計なことにはなっていなさそう

どうするか

  • vscode

    • tmuxをつかわないので「SSH_AUTH_SOCKをいじらない」
    • SSH_AUTH_SOCK=/run/user//vscode-ssh-auth-sock- をそのままつかう
  • et

    • SSH_AUTH_SOCKはずっと生きているので「SSH_AUTH_SOCKをいじらない」でよいのでは?
      • 意図的に切断、再接続するとダメ
        • mac再起動とか
    • etのときだけ、いつもの対策をいれる
      • /tmp/et_forward_sock_*/sock -> /.ssh/et_forward_sock ; SSH_AUTH_SOCK=/.ssh/et_forward_sock
    • 2番目の接続が切れると1番目の接続が駄目になる問題
      • etを2つ接続することはほぼない
      • vscode(ssh)でSSH_AUTH_SOCKをいじらないのであれば、ほとんどおこらない
      • 発生したら→ tmuxデタッチ、et切断/再接続、tmux -aする
  • ★★★ etのときだけ例の対策入れればおkでは? ★★★

    • sshのときは「SSH_AUTH_SOCKをいじらない」
    • vscodeのときは「SSH_AUTH_SOCKをいじらない」
    • etのときはいつもの対策
if [ 1 -eq 1 ]; then
  if [ -z "$SSH_AUTH_SOCK" ]; then
    # Check for a currently running instance of the agent
    RUNNING_AGENT="`ps -ax | grep 'ssh-agent -s' | grep -v grep | wc -l | tr -d '[:space:]'`"
    if [ "$RUNNING_AGENT" = "0" ]; then
      # Launch a new instance of the agent
      ssh-agent -s &> .ssh/ssh-agent
    fi
    eval `cat .ssh/ssh-agent`
  fi

  agent="$HOME/.ssh/agent"
  if [ -S "$SSH_AUTH_SOCK" ]; then
    case $SSH_AUTH_SOCK in
    # /tmp/*/agent.[0-9]*)
    #     ;;
    # /run/user/*/vscode-ssh-auth-sock-*)
    #     ;;
    /tmp/et_forward_sock_*/sock)
        ln -snf "$SSH_AUTH_SOCK" $agent && export SSH_AUTH_SOCK=$agent
        ;;
    *)
        echo "INFO: SSH_AUTH_SOCK=$SSH_AUTH_SOCK is not linked to shared ssh-agent file($agent)"
        ;;
    esac
  elif [ -S $agent ]; then
    export SSH_AUTH_SOCK=$agent
  else
    echo "no ssh-agent"
  fi
fi

memo

env | grep SSH_AUTH_SOCK


---------------------------
(ssh)
SSH_AUTH_SOCK=/tmp/ssh-XXXXGjHtz6/agent.36256

% ls -l /tmp/ssh-XXXXGjHtz6/agent.36256
srwxrwxr-x 1 ubuntu ubuntu 0 Sep 11 09:08 /tmp/ssh-XXXXGjHtz6/agent.36256

---------------------------
(et)

SSH_AUTH_SOCK=/tmp/et_forward_sock_r2MSdX/sock
% ls -l /tmp/et_forward_sock_r2MSdX/sock
srwx------ 1 ubuntu ubuntu 0 Sep 11 03:54 /tmp/et_forward_sock_r2MSdX/sock

---------------------------
(vscode)
SSH_AUTH_SOCK=/run/user/1000/vscode-ssh-auth-sock-219138363

% ls -l /run/user/1000/vscode-ssh-auth-sock-219138363
lrwxrwxrwx 1 ubuntu ubuntu 31 Sep 11 07:02 /run/user/1000/vscode-ssh-auth-sock-219138363 -> /tmp/ssh-XXXXB8nqly/agent.30223

% ls -l /tmp/ssh-XXXXB8nqly/agent.30223
srwxrwxr-x 1 ubuntu ubuntu 0 Sep 11 07:02 /tmp/ssh-XXXXB8nqly/agent.30223
% find /tmp -name "agent.*" 2>/dev/null | grep "/tmp/ssh-" ; find /tmp -name "sock" 2>/dev/null | grep "/tmp/et_forward_sock_"
/tmp/ssh-XXXXB8nqly/agent.30223
/tmp/ssh-XXXXGjHtz6/agent.36256
/tmp/et_forward_sock_r2MSdX/sock
/tmp/et_forward_sock_KBMsk6/sock
/tmp/et_forward_sock_19E48b/sock
/tmp/et_forward_sock_KNyK0A/sock
/tmp/et_forward_sock_KsWIdu/sock

ssh-add -l # ssh-agentに登録されている鍵のリスト SSH_AUTH_SOCK経由で問い合わせてる。たぶん。

% SSH_AUTH_SOCK=/tmp/et_forward_sock_KsWIdu/sock ssh-add -l
Error connecting to agent: Connection refused

% SSH_AUTH_SOCK=/tmp/et_forward_sock_KNyK0A/sock ssh-add -l
Error connecting to agent: Connection refused

% SSH_AUTH_SOCK=/tmp/et_forward_sock_19E48b/sock ssh-add -l
Error connecting to agent: Connection refused

% SSH_AUTH_SOCK=/tmp/et_forward_sock_KBMsk6/sock ssh-add -l
Error connecting to agent: Connection refused

% SSH_AUTH_SOCK=/tmp/ssh-XXXX27FlKu/agent.37939 ssh-add -l
2048 SHA256:xxxxxxx /Users/takeru/.ssh/id_rsa (RSA)
3072 SHA256:xxxxxxx ubuntu@xxxxxxx (RSA)


こんなふうに生きてるSSH_AUTH_SOCKを探してセットすればよさそう
#############################################################
# ssh-agent
# http://www.snowelm.com/~t/doc/tips/20030625.ja.html
if [ -f ~/.ssh-agent-info ]; then
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
fi
ssh_keys=(
"$HOME/.ssh/id_rsa"
"$HOME/.ssh/google_compute_engine"
)
added_fingerprints=$(ssh-add -l | awk '{print $2}')
for key in "${ssh_keys[@]}"; do
fingerprint=$(ssh-keygen -E sha256 -lf "$key" | awk '{print $2}')
if [[ "$added_fingerprints" != *"$fingerprint"* ]]; then
ssh-add "$key"
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment