Bitwarden 桌面客户端可以充当 SSH Agent,让 SSH 私钥保存在 Bitwarden 保险库中,而不是直接存放在 ~/.ssh 目录。

在 Windows 中启用 Bitwarden SSH Agent 后,PowerShell 可以直接使用其中的密钥。但 WSL2 中的 Linux 程序无法直接访问 Windows 的命名管道,因此需要借助 npiperelaysocat 建立一座桥梁。

本文介绍如何在 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,socatnpiperelay 再把请求转发到 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

在 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.0kernel.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

该脚本会:

  1. SSH_AUTH_SOCK 指向 WSL2 中的 Unix Socket。
  2. 检查 Socket 是否已经存在。
  3. 删除失效的 Socket 文件。
  4. 通过 socat 创建新的 Unix Socket。
  5. 使用 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

先检查:

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/... 形式。

确认实际调用的是新版本:

type -a ss
command -v ss
ss -V

/usr/local/sbin/ss 应该排在 /usr/bin/ss 前面。

如果 Shell 仍然缓存旧路径,可以执行:

hash -r

然后再次运行:

ss -a

总结

通过 socatnpiperelay,可以把 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