Win10 Bash下使用KeePass KeeAgent插件

Win10 Bash 使用 KeeAgent 问题

出于管理不同服务器以及自己几个 VPS 的需要,我都会把这些 SSH 密钥保存到自己的 KeePass 密码数据库中,KeePass 软件安装了 KeeAgent 插件之后,可以在用户需要登录服务器时方便地自动加载 SSH 密钥。KeeAgent 同时支持 PuTTY 和 OpenSSH 格式的私钥,而且支持 Windows / Linux / Mac 系统。我在平时使用中无论用 Windows 下的 PuTTY / SecureCRT / XShell 软件还是 Linux 下用 ssh 命令都能愉快的自动加载 KeeAgent 保存的 SSH 证书,这里也强烈建议各位将 SSH 密钥用 KeeAgent 插件保存到 KeePass 密码库中。

不过自从将工作的电脑系统升级到 Windows 10 之后,虽然我使用 Win10 系统自带的 Bash shell 的场合也越来越多了(原来的 MSYS 和 Cygwin 环境基本很少开启了),但也发现 Win10 Bash 自带的 ssh 命令却不支持 KeeAgent 插件,仍然需要手工选择私钥文件或者输入密码登录服务器。

KeeAgent 在 Linux / Mac 系统下是支持原生的 SSH agent 的,SSH agent 使用的是基于 Unix socket 文件工作方式,也因此 Linux / Mac 系统下的 ssh 命令直接就能自动加载 KeeAgent 保存的密钥。

虽然 Win10 WSL(Windows Subsystem for Linux)子系统内部是支持 Unix socket 文件的,但 WSL 子系统外的 Windows 版本 KeeAgent 插件要想支持 WSL 内部的 socket 文件就不太容易了,还需要通过别的方法来绕过这个限制。

msysGit to Unix socket 代理

看了 KeePass 的 KeeAgent 插件选项可以看到该插件是支持 Cygwin 和 msysGit(现在已更名为 Git for Windows)兼容的 socket 文件的,这样原来的 Cygwin 和 MSYS 用户也可以自动加载 KeeAgent 中保存的密钥,例如我的 KeeAgent 配置如下:

KeeAgent 的 msysGit socket 选项

虽然 KeeAgent 不能直接支持 Win10 WSL 子系统内的 Unix socket 文件,但已经有人写了个 msysGit socket to Unix socket 的 Python 代理程序,借助此 msysgit2unix-socket.py 代理程序就可以让 Win10 Bash shell 通过 SSH agent 加载 KeeAgent 中的密钥咯。

该代理程序启动时会创建一个用于 SSH 认证的 Unix socket 文件,然后 TCP 连接到本地 KeeAgent 插件创建的 msysGit socket 文件,收到 ssh、scp 等命令的认证请求后将数据转发到 KeeAgent 插件,最后将结果返回到 Unix socket 文件。代理程序的工作机制大概如我粗画的这张图:

msysGit to Unix socket 代理工作机制

不过我在使用中还是发现该代理程序存在一点小问题:

第一次 SSH 认证可以通过 KeeAgent 插件返回成功,后续再有新的认证请求时却会一直卡住。调试之后发现前面的认证请求完成之后,虽然 ssh 命令至 Unix socket 文件的连接关闭了,但是代理程序至 msysGit socket 文件的连接却一直保持着未关闭,这样新的认证请求将无法正常从 KeeAgent 插件获取有效的证书数据。

为了解决这个问题,我 fork 了这个 msysGit to Unix socket 代理程序,并做了小改动,也放到了 Gist 上:

https://gist.github.com/zohead/b3cbb709fdfd2c0da31bff1b3f436af7

使用 socket 代理程序

首先下载 msysgit2unix-socket.py 代理程序,可以直接放到 Win10 Bash shell 用户主目录中,然后编辑 ~/.bashrc 文件增加下面这几行:

export SSH_AUTH_SOCK="/tmp/.ssh-auth-sock"
if [ -s /mnt/d/msys/keeagent.sock ]; then
	~/msysgit2unix-socket.py /mnt/d/msys/keeagent.sock:$SSH_AUTH_SOCK 2>/dev/null
	trap "~/msysgit2unix-socket-exit.sh $$" EXIT
fi

这样运行 bash 命令后会自动启动该程序,msysgit2unix-socket.py 程序启动之后会自动转为后台守护进程,并在 /tmp 目录(实际在 Windows 系统的 C:\Users\user\AppData\Local\lxss\rootfs\tmp 目录下)下生成兼容 ssh 命令的 socket 文件,而且如果开启多个 Bash 会话也不会影响,只会在后台保持运行一个 msysgit2unix-socket.py 代理程序。

上面内容第二行的 /mnt/d/msys/keeagent.sock 路径就是 KeeAgent 选项中的 Create msysGit compatible socket file 文件路径,请根据情况自行修改。

我增加的一行 trap 退出操作是为了能在最后一个 Win10 Bash 会话退出之时能执行自定义的清理脚本以删除 msysgit2unix-socket.py 程序产生的临时文件,不然下次再开启 Bash 运行 msysgit2unix-socket.py 程序时会因为已经存在临时的 socket 及 PID 文件导致程序退出。

我增加的 msysgit2unix-socket-exit.sh 脚本程序也非常简单:

#!/bin/sh
BASHPIDS=`pidof bash -o %PPID -o $1`
[ "x$BASHPIDS" != "x" ] && exit 0
rm -f /tmp/msysgit2unix-socket.pid /tmp/.ssh-auth-sock

这里使用 pidof 命令判断当前退出的是不是最后一个 Win10 Bash 会话(通过参数忽略了父 bash 进程和脚本程序自身进程),如果是最后一个 Bash 会话则删除 msysgit2unix-socket.py 程序产生的临时文件。

当然你也可以去掉增加的清理脚本,直接在 ~/.bashrc 文件中判断 msysgit2unix-socket.py 程序运行状态并删除之前产生的临时文件:

export SSH_AUTH_SOCK="/tmp/.ssh-auth-sock"
if [ -s /mnt/d/msys/keeagent.sock ]; then
	pgrep -f msysgit2unix-socket.py >/dev/null 2>&1
	if [ $? -ne 0 ]; then
		rm -f /tmp/msysgit2unix-socket.pid /tmp/.ssh-auth-sock
		~/msysgit2unix-socket.py /mnt/d/msys/keeagent.sock:$SSH_AUTH_SOCK 2>/dev/null
	fi
fi

这样修改之后就能在 Win10 Bash 里畅快地使用 ssh、scp 等命令通过 KeeAgent 插件自动登录服务器进行管理咯,祝大家在这个看起来不太冷的 12 月玩得开心 ^_^。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*