MacOS使用 YubiKey (远程)验证 SSH
- Yubikey 5C NFC
背景 + 叠甲
首先这大概率是重复造轮子的教程,网上到处都是Yubikey的使用教程。 但是部分只会告诉你答案,不会告诉你每一步在干嘛,受限于MacOS版本不同等原因,对于我这样的彩笔来说跑不通+完全没法debug。
目的
-
用于一般性验证SSH连接
-
Yubikey插在在本地机器,本地机器SSH远程连接到一台Host A时,在Host A上不加载(复制)公私钥的情况下验证SSH链接(其实大部分是Git验证)
选择
FIDO2 + ed25519-sk
理由就是够用 简单 支持多个密钥 以及 通用性高
MacOS环境安装
首先你需要安装brew版本的openssh 苹果版本自带的openssh编译时没加入支持硬件密钥的选项
brew install openssh# yubikey的cli管理工具,可选安装brew install ykman
如果使用系统自带的你会得到类似下面的报错
➜ ~ /usr/bin/ssh-keygen -t ed25519-sk -O resident -O application=ssh:yk5c-main -C "your_email@example.com" -f ~/.ssh/id_yk5cGenerating public/private ed25519-sk key pair.You may need to touch your authenticator to authorize key generation.No FIDO SecurityKeyProvider specifiedKey enrollment failed: invalid format
此时意味着你有2个openssh,我们需要使用的是/opt/homebrew/bin/ssh
➜ ~ type -a sshssh is /opt/homebrew/bin/sshssh is /usr/bin/ssh
你可以使用下面命令来确认是否正确
which ssh
!!非常关键!! 你所有包含ssh的 ssh-* 的命令都需要使用注意一定是HomeBrew的版本,而不是苹果的默认/usr/bin/ssh* 下的任何二进制 所以你遇到任何问题,第一步先检查ssh命令执行路径
配置SSH公私钥
Yubikey官网文档包含了大部分参数,建议自己阅读一遍,下面只是重复造轮子
我们需要 ed25519-sk
的密钥,这是固定的。
有4个可选项 :
-
-O resident 让SSH注册到Yubikey内,你可以在FIDO2页面或者命令行
ykman fido credentials list
查看到,可以在任何机器上插入Yubikey,执行ssh-add -K
并输入PIN就能加载密钥 -
-O verify-required 每次使用都需要输入 PIN 码和进行实体触摸。
-
-O no-touch-required 无需要求触摸
-
-O application=ssh:$name 当搭配resident时,在FIDO页面显示的名字
下面是我的搭配,首先resident基本是必须,同时搭配application备注名字,但是我想要验证PIN,每次输入PIN码其实挺麻烦,需要多好多操作,下面的情况只需要触碰Yubikey进行一下确认即可
$(brew --prefix)/bin/ssh-keygen -t ed25519-sk -O resident -O application=ssh:yk5c-main -C "你的注释" -f ~/.ssh/id_yk5c
完成后就能看见你的SSH公私钥生成了,但是如果没有yubikey,这个私钥是无法用于验证的,因为这个密钥仅包含公钥和“密钥句柄”,真实密钥是被yubikey上出厂写入的AES密钥操作密钥句柄生成反馈的。参考链接
但是此时你使用这个公钥就能搭配Yubikey尝试登陆了。
SSH-AGENT 远程验证
这是另外一个核心需求,我的部分编译工具以及服务都不运行在本地,都在其他Linux机器,当他们需要进行拉取Git以及作为跳板再链接其他机器调试时,把Yubikey物理插到那些机器上,不方便也小丑,所以需要ssh-agent
,他会帮你代理转发并转发ssh key到远程,可以在远程再次验证。
核心参数/环境变量
- SSH_AUTH_SOCK/SSH_AGENT_PID (环境变量)
用于
ssh-agent
的代理在ssh 远程时转发
你需要先禁用自带的服务
launchctl disable user/$UID/com.openssh.ssh-agent
当你使用ssh-agent -s
他就会给出环境变量让你用于加载
➜ ~ $(brew --prefix)/bin/ssh-agent -sSSH_AUTH_SOCK=/var/folders/7f/md23q0_j6xxxxxxycgc1111111gn/T//ssh-r2221dsadacxvO/agent.23603; export SSH_AUTH_SOCK;SSH_AGENT_PID=23604; export SSH_AGENT_PID;echo Agent pid 23604;
你可以手动复制上面ssh-agent -s
输出的信息直接粘贴到命令行生效,或者用eval直接加载。同时你还用ssh-add
需要导入你的私钥给ssh-agent
eval "$(ssh-agent -s)"$(brew --prefix)/bin/ssh-add ~/.ssh/id_yk5c
同时使用ssh-add -L
验证
➜ ~ $(brew --prefix)/bin/ssh-add -Lsk-ssh-ed25519@openssh.com AAxxxxxnNxxxxxWxxxxbg== your_email@example.com
此时你就可以远程连接其他Host了,但是你需要添加一个参数-A
$(brew --prefix)/bin/ssh -A root@xxxxxx
或者为你的~/.ssh/config的host下添加ForwardAgent yes
Host xxxxxxxx User root HostName 1.1.1.1 ForwardAgent yes
当进入远程Host时,同样ssh-add -L
你发现你以及能和上一面一样发现你的密钥成功转发到了远程机器
Debug:
如果你没有看到密钥并出现The agent has no identities.
大概率是SSH_AUTH_SOCK/SSH_AGENT_PID变量加载有问题
你需要在MacOS上查看SSH_AUTH_SOCK/SSH_AGENT_PID变量是否为 /var/folders/xxx
开头,这才是homebrew ssh-agent生成的,同时你可以看一下ssh-agent
的进程路径对不对
ps aux | grep ssh-agent
确认加载密钥后当你远程使用yubikey私钥验证其他时会发现出现类似下面报错
signing failed: agent refused operation
原因出在另外一个关键要素/环境变量
- SSH_ASKPASS
因为SSH(agent)需要去调用Yubikey验证,但是他并不知道应该去哪里调用,尤其是在远程主机时,所以你需要一个工具去帮你拉取MacOS的验证给Yubikey
这里的工具有好多,我选择是 https://github.com/theseal/ssh-askpass
brew install theseal/ssh-askpass/ssh-askpass
那么这时候你需要在上面配置SSH_AUTH_SOCK/SSH_AGENT_PID的同时配置SSH_ASKPASS的环境变量
export SSH_ASKPASS=$(brew --prefix)/bin/ssh-askpassexport DISPLAY=":0"
此时你再去尝试连接,就会出现下面的弹窗,我不用输入PIN,所以直接回车,此时你的Yubikey会闪烁,触碰就可以完成验证。 ![[../images/others/askkey.png]]
保持服务
其实到上面已经完成需求,但是你加载的环境变量只能在当前终端有效,那么你需要加入到你的~/.zshrc
让他能保持服务,简单脚本(未验证)如下,记得source ~/.zshrc
# Homebrew 安装路径BREW_PREFIX="$(brew --prefix)"
# 使用 Homebrew 版本的 ssh-agent 启动(如果没启动)if [ -z "$SSH_AUTH_SOCK" ] || ! pgrep -u "$USER" ssh-agent > /dev/null; then eval "$($BREW_PREFIX/bin/ssh-agent -s)" > /dev/nullfi
# 自动加载 YubiKey 密钥SSH_KEY="$HOME/.ssh/id_yk5c"if [ -f "$SSH_KEY" ]; then "$BREW_PREFIX/bin/ssh-add" "$SSH_KEY" 2>/dev/nullfi
export SSH_ASKPASS="$BREW_PREFIX/bin/ssh-askpass"export DISPLAY=":0"
我自己的话是使用Oh-my-zsh里面的ssh-agent插件,你看了他的插件脚本就会发现本质上区别不大,但是你需要注意的是修改他的脚本,制定ssh-agent路径,不然默认似乎只会加载/usr/bin下的
plugins=(..... ssh-agent)
zstyle :omz:plugins:ssh-agent identities ~/.ssh/id_yk5czstyle :omz:plugins:ssh-agent helper ssh-askpass
另外他里面的zstyle :omz:plugins:ssh-agent agent-forwarding yes
开启似乎会有问题,没空研究,加一嘴
参考
https://blog.nathanhigley.com/posts/hardwaresshkeysonmacos/ https://swjm.blog/the-complete-guide-to-ssh-with-fido2-security-keys-841063a04252