Bitwarden 桌面客户端可以充当 SSH Agent,让 SSH 私钥保存在 Bitwarden 保险库中,而不是直接存放在 ~/.ssh 目录。
在 Windows 中启用 Bitwarden SSH Agent 后,PowerShell 可以直接使用其中的密钥。但 WSL2 中的 Linux 程序无法直接访问 Windows 的命名管道,因此需要借助 npiperelay 和 socat 建立一座桥梁。
本文介绍如何在 WSL2 中使用 Windows 上的 Bitwarden SSH Agent,同时解决新版 WSL 中运行 ss -a 时出现的:
RTNETLINK answers: Invalid argument工作原理
整个链路如下:
WSL2 中的 ssh/git
│
▼
~/.ssh/agent.sock
│
socat
│
npiperelay.exe
│
▼
\\.\pipe\openssh-ssh-agent
│
▼
Windows Bitwarden SSH Agent
WSL2 中的 SSH 客户端连接 Unix Socket,socat 和 npiperelay 再把请求转发到 Bitwarden 提供的 Windows OpenSSH Agent 命名管道。
私钥仍由 Bitwarden 管理,WSL2 只是把签名请求转发给 Bitwarden。
一、配置 Bitwarden SSH Agent
打开 Bitwarden 桌面客户端,在设置中启用 SSH Agent:
Settings → SSH agent → Enable SSH agent
确保保险库中已经保存了至少一把 SSH 密钥,并保持 Bitwarden 处于解锁状态。
如果 Windows 的 OpenSSH Authentication Agent 服务正在运行,还需要将其停止并禁用,避免和 Bitwarden 使用相同的 Agent 接口。
以管理员身份打开 PowerShell:
Stop-Service ssh-agent
Set-Service ssh-agent -StartupType Disabled
然后在普通 PowerShell 中测试:
ssh-add -L
如果能够看到 Bitwarden 中保存的公钥,说明 Windows 侧已经配置成功。具体设置也可以参考 Bitwarden SSH Agent 官方文档。
如果这里无法列出密钥,应该先检查 Bitwarden 设置,而不是继续排查 WSL2。
二、安装 npiperelay
npiperelay 用于让 WSL2 程序访问 Windows 命名管道。
在 PowerShell 中使用 Chocolatey 安装:
choco install npiperelay
默认安装路径通常为:
C:\ProgramData\chocolatey\lib\npiperelay\tools\npiperelay.exe
在 WSL2 中对应的路径是:
/mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe
也可以使用 Winget:
winget install albertony.npiperelay
不过 Winget 的安装路径会包含用户名和包版本,需要根据实际位置修改后面的脚本。
三、安装 socat
进入 WSL2,安装 socat:
sudo apt update
sudo apt install socat
socat 将负责创建 Linux Unix Socket,并把 Socket 中的数据交给 npiperelay。
四、解决 ss 的 RTNETLINK 报错
在 WSL 2.7.8 中运行:
ss -a
可能会看到:
RTNETLINK answers: Invalid argument
这不是 Bitwarden、SSH Agent 或网络路由配置错误,而是新版 WSL 内核与 Ubuntu 自带旧版 iproute2 之间的兼容问题。
相关环境通常是:
WSL:2.7.8
内核:6.18.33.1-microsoft-standard-WSL2
iproute2:6.1.0
Linux 6.16 已经移除了 DCCP Socket 实现,而旧版 ss 在执行广泛的 Socket 查询时仍然会探测 DCCP。新内核对该请求返回 EINVAL,旧版 ss 随后将其显示为 RTNETLINK 错误。
根据 microsoft/WSL#40774 中的说明,上游 iproute2 7.0.0 已经能够正确处理这种情况。
截至本文编写时,上游最新稳定版本是 7.1.0,因此直接编译安装 7.1.0。kernel.org iproute2 发布目录
安装编译工具
sudo apt install build-essential pkg-config bison flex编译 iproute2 7.1.0
cd /tmp
curl -LO https://www.kernel.org/pub/linux/utils/net/iproute2/iproute2-7.1.0.tar.xz
tar -xf iproute2-7.1.0.tar.xz
cd iproute2-7.1.0
./configure
make -j"$(nproc)"
这里不需要替换 Ubuntu 软件包中的全部程序,只安装新版本的 ss:
sudo install -m 0755 misc/ss /usr/local/sbin/ss
hash -r
检查当前使用的程序和版本:
type -a ss
ss -V
预期可以看到:
ss utility, iproute2-7.1.0
最后测试:
ss -a >/dev/null
正常情况下不应再出现:
RTNETLINK answers: Invalid argument
如果不想手动编译,也可以暂时忽略这个警告,或者等待 Ubuntu 软件源更新 iproute2。
五、创建 SSH Agent 转发脚本
创建脚本目录:
mkdir -p ~/scripts
mkdir -p ~/.ssh
chmod 700 ~/.ssh
创建文件:
nano ~/scripts/agent-bridge.sh
写入以下内容:
#!/usr/bin/env bash
export SSH_AUTH_SOCK="$HOME/.ssh/agent.sock"
if ! ss -a | grep -Fq "$SSH_AUTH_SOCK"; then
rm -f "$SSH_AUTH_SOCK"
(
setsid socat \
UNIX-LISTEN:"$SSH_AUTH_SOCK",fork \
EXEC:"/mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe -ei -s //./pipe/openssh-ssh-agent",nofork &
) >/dev/null 2>&1
fi
该脚本会:
- 将
SSH_AUTH_SOCK指向 WSL2 中的 Unix Socket。 - 检查 Socket 是否已经存在。
- 删除失效的 Socket 文件。
- 通过
socat创建新的 Unix Socket。 - 使用
npiperelay连接 Bitwarden 的 Windows SSH Agent。
如果 npiperelay.exe 不在 Chocolatey 默认目录,需要将脚本中的路径替换为实际安装路径。
这一转发方案参考自 Bitwarden ssh-agent on WSL2。
为脚本添加执行权限:
chmod +x ~/scripts/agent-bridge.sh六、随 Shell 自动启动
如果使用 Bash,在 ~/.bashrc 末尾添加:
source ~/scripts/agent-bridge.sh
如果使用 Zsh,则添加到 ~/.zshrc:
source ~/scripts/agent-bridge.sh
重新打开终端,或者立即加载配置:
source ~/.bashrc七、测试 SSH Agent
在 WSL2 中运行:
ssh-add -l
如果配置成功,应该能够看到 Bitwarden 中保存的 SSH 密钥指纹。
查看完整公钥:
ssh-add -L
也可以测试 GitHub SSH 认证:
ssh -T git@github.com
第一次连接时可能需要确认 GitHub 的主机指纹。随后 Bitwarden 会根据授权设置弹出确认窗口。
配置成功后,下面这些操作都可以直接使用 Bitwarden 中的 SSH 密钥:
git clone git@github.com:username/repository.git
git pull
git push
ssh user@example.com常见问题
PowerShell 中也无法执行 ssh-add -L
先检查:
- Bitwarden 是否已经解锁。
- SSH Agent 功能是否启用。
- 保险库中是否存在 SSH 密钥。
- Windows OpenSSH Authentication Agent 服务是否已经禁用。
- Bitwarden 是否已经完全退出后重新启动。
Windows 侧无法使用时,WSL2 转发也不会成功。
WSL2 中提示无法连接 Agent
检查环境变量:
echo "$SSH_AUTH_SOCK"
预期结果类似:
/home/username/.ssh/agent.sock
检查 Socket:
ls -l "$SSH_AUTH_SOCK"
检查 socat 进程:
pgrep -af socat找不到 npiperelay.exe
检查脚本中的路径:
ls -l /mnt/c/ProgramData/chocolatey/lib/npiperelay/tools/npiperelay.exe
如果通过 Winget 安装,可以在 Windows PowerShell 中查找:
Get-Command npiperelay.exe
然后将 Windows 路径转换为 /mnt/c/... 形式。
仍然出现 RTNETLINK 报错
确认实际调用的是新版本:
type -a ss
command -v ss
ss -V
/usr/local/sbin/ss 应该排在 /usr/bin/ss 前面。
如果 Shell 仍然缓存旧路径,可以执行:
hash -r
然后再次运行:
ss -a总结
通过 socat 和 npiperelay,可以把 WSL2 中的 Unix Socket 转发到 Windows Bitwarden SSH Agent。这样,WSL2 中的 SSH 和 Git 可以直接使用 Bitwarden 管理的密钥,无需在 Windows 与 Linux 之间复制私钥。
对于 WSL 2.7.8 中出现的 RTNETLINK answers: Invalid argument,真正的原因是新内核与旧版 ss 不兼容。安装 iproute2 7.0.0 或更高版本即可解决;本文使用当前最新稳定版 7.1.0。