起因
突发奇想,花了巨大的价钱在淘宝购买了一个Yubikey Bio-C
安全密钥(这个密钥支持使用指纹识别来替换掉PIN码输入的流程),用来作为每次都得输入PIN码的Yubikey 5C-NFC
安全密钥的备份。
到货后才发现是FIDO2 Edition
,上网查询后发现多协议版本目前还不对公众市场开放。而且一般来说,只支持FIDO2
特性的安全密钥会比较便宜。又不太想退货,后来发现其实OpenSSH
在8.3
版本就已经支持了使用FIDO2
来进行SSH登录。Yubico已经发布了一个教程来告诉大家怎么操作,不过我现在再用中文阐述一遍这个流程。
一些声明
首先你要对FIDO2
有个大致的了解。
我直接从Yubico
的官网上复制一些话来进行描述:
FIDO2
以 8.2p1 为起点,OpenSSH 增加了对使用 FIDO2 凭证进行注册和身份验证的支持。OpenSSH 支持可发现凭据和不可发现凭据,允许使用安全密钥和 YubiKey,包括 YubiKey 生物密钥。FIDO2 凭证允许简化 YubiKey 的注册和身份验证体验。
有关使用 FIDO2 和 YubiKey 设置 SSH 的说明,请访问:使用 FIDO2 保护 SSH
FIDO2 的优势
FIDO2 允许在 YubiKey 本身内直接生成密钥,无需 PKI 框架或其他应用程序来生成密钥。OpenSSH 直接与 YubiKey 上的 FIDO2 函数连接,允许它选择密钥算法,以及生成可发现和不可发现的凭据。
由于支持可发现和不可发现的 FIDO2 凭证,FIDO2 允许为本地安全端点提供 SSH 选项,除了凭证应保留在 YubiKey 上的公有开放端点外,还允许使用。
FIDO2 的缺点
截至本页的上次更新,Windows 尚不支持 SSH 上的 FIDO2。(现在已经支持了)
FIDO2 基于去中心化部署,没有中央服务器颁发或撤销密钥。必须单独删除密钥,以便在 YubiKey 丢失或被盗时撤销访问权限。
总结
注意这里面提到的缺点:密钥必须单独删除。这意味着你如果只用FIDO2
进行服务器访问,那么密钥一丢就全完了。所以最好保留第二种访问服务器的方式(比如我就用老的Yubikey 5C-NFC
和一些其他的方式作为备份)。
顺便说一下我的看法:我觉得使用FIDO2
来取代PIV
访问性价比更高,因为支持PIV
的多协议版本一般来说价格更贵。
通用流程
升级SSH版本
首先得确保SSH
版本足够高(大于等于8.3版本),从而支持这个FIDO2
的特性。至于版本我们可以用以下命令进行检查:
ssh -V
否则我们需要升级。一般来说,在Ubuntu
上我们直接用以下命令升级:
apt-get upgrade ssh
生成FIDO2的公钥和私钥
执行命令
ssh-keygen -t ed25519-sk -O resident -O application=ssh:Arc_servers -O verify-required
-C "root@Arc_servers"
这里application
的服务你可以自己起个名字,我这里就叫ssh:Arc_servers
代表这个可以登录我所有的服务器。Comment
是密钥的注释,方便你在一堆密钥中分清哪个是哪个。
随后他会在你指定的文件夹(对于Windows来说,一般是C:\Users\username/.ssh/
里,这里的username
就是你的用户名,有时候只有前几位)生成默认文件名id_ed25519_sk
的私钥和id_ed25519_sk.pub
的公钥。这个私钥文件就不需要进行特别的保护了,因为其只是一个接口,直接对应到了安全密钥上(所以我就没有设置Passphrase),从而不用担心文件本身被破解(如果是老方法直接在本机生成密钥,一个很弱的PIN码或者没有PIN码会让人觉得很不安全)。
在登录服务器时使用FIDO2
添加公钥
一般来说,我们直接在root
用户里面添加公钥就行了。具体来说,就是打开/root/.ssh/authorized_keys
这个文件,在里面新加一行,内容是上面提到的id_ed25519_sk.pub
的内容就可以了。
修改本地config文件
为了登录方便,我们直接在本地的SSH Config
里面添加好对应的信息。这个文件一般在C:\Users\username\.ssh\config
这个位置。
文件内容大致如下:
Host Your_Server_Name
HostName ip1.ip2.ip3.ip4
Port 22
User root
IdentityFile C:\Users\username\.ssh\id_ed25519_sk
这样就可以直接用VSCode
登录连接了。其实这后半段流程和正常加个普通的安全密钥基本上是一回事。
在Git里使用FIDO2
虽然我们已经在服务器登录中使用了FIDO2
来实现无密码登录(我这个安全密钥是扫指纹的),当然也可以在Git中使用安全密钥来进行登录。Yubico给了一个教程,不过我们一样稍微简单的叙述一下流程。
考虑到其实大家一般用Git
都是连接到Github
,所以我们就针对这个来进行简单讲解。
添加SSH认证密钥与签名密钥
打开网址,我们把通用流程中生成的FIDO2 私钥
保存到里面。我们可以选择类型,不过为了方便之后步骤我们把这个私钥既设置成签名,又设置成认证(也就是存两遍)。
随后我们直接测试是否可以登录:
$ ssh -T [email protected]
Confirm user presence for key ED25519-SK SHA256:e6a//1234567
User presence confirmed
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
一般来说这样就至少设置成功了。为什么在这里我们不需要进行额外的其他设置呢?这应该也算是一个FIDO2
的特性(也就是类似SSH
里添加多个密钥进行交互,其实就是一个个比对)。所以直接就设置好了。
修改本地Git设置来支持本地Git签名
考虑到另一个需求:我们要支持类似PGP
的签名方式,所以还是得操作一下。
以下操作是在Ubuntu
上实现的。
首先升级Git
到版本2.34
,升级方法和之前说的SSH
一样,查询版本用命令git --version
。
修改全局Git
签名格式到SSH
(一般来说就改全局,方便):
git config --system gpg.format ssh
随后把之前的FIDO2 私钥
复制到/root/.ssh/id_ed25519_sk
里面。
设置正确的密钥权限:
chmod 0600 /root/.ssh/id_ed25519_sk
设置全局Git
签名密钥位置:
git config --system user.signingKey ~/.ssh/id_ed25519_sk
添加可信验证者文件,简单来说类似下面的操作:
$ cat ~/.ssh/allowed_signers
[email protected] [email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJhUXYvdwz3Dx45bWNmxHs1R21mlUm0o63+s4iCzRoFeAAAACnNzaDpnaXRodWI= user@host
保存该文件为全局验证者设置:
git config --system gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
使用ssh-agent进行远程服务器签名(可选)
我们假设本机是Server A
插着安全密钥,我们通过SSH
连接到了机器Server B
上,现在我们要在Server B
上写代码并使用安全密钥签名提交到Github
上面。那么我们就需要一些额外的配置来完成这些。
首先仍然需要上一步的设置。
在Server A
(假设是Windows
操作系统)上自动启动ssh-agent
同时添加合适的密钥:
管理员启动PowerShell
# 自动启动设置
Set-Service ssh-agent -StartupType Automatic
# 启动服务
Start-Service ssh-agent
# 添加安全密钥
ssh-add $env:USERPROFILE\.ssh\id_ed25519_sk
# 验证加没加上去
ssh-add -L
在Server A
(假设是Linux
系统)上设置ssh-agent
同时加入到~/.zshrc
之类的rc
文件或者profile
文件实现登录自动启动:
if [ -z "$SSH_AUTH_SOCK" ]; then
eval $(ssh-agent -s)
ssh-add -l >/dev/null || ssh-add ~/.ssh/id_ed25519_sk
fi
加完之后可以使用类似source ~/.profile
来执行。
在Server A
上设置自动同步ssh-agent
:
在~/.ssh/config
中,在开头添加如下语句:
Host *
ForwardAgent yes
这样就不需要所谓的ssh -A
了,默认添加上去。
在Server B
上默认开启ssh-agent
转发:
打开/etc/ssh/sshd_config
,找到这句话并取消注释(没有的话直接加上去)
AllowAgentForwarding yes
然后我们使用VSCode
连接没有打开ssh-agent
的Server B
,观测效果:
$ ssh-add -L
[email protected] 1234567 root@Arc_servers
这里就验证了ssh-agent
被成功转发了上去。
设置Git自动签名(可选)
在VSCode
里,Git
签名默认不是自动打开的。当然在命令行中使用Git
也不是。我们来开启这些功能来更加自动化。
命令行:
git config --system commit.gpgsign true
VSCode
:
使用Ctrl+,
打开设置界面,搜索gpg
并打开如下功能:
Git: Enable Commit Signing
Enables commit signing with GPG, X.509, or SSH.
这样就实现自动化签名了。
验证是否可以签名
考虑到用一堆命令行把事情变得很复杂,我们直接用VSCode
来尝试进行测试。
首先在Github
建个空的仓库,然后拉下来。 随便写点东西提交,看看是否签名完成就行。
一些彩蛋
可以考虑在VSCode
中关闭以下功能:
Git: Autofetch
When set to true, commits will automatically be fetched from the default remote of the current Git repository. Setting to all will fetch from all remotes.
这个功能会经常让你去碰你的安全密钥,我觉得没必要打开。等到要操作的时候手工拉一下就行。
Comments NOTHING