为OpenSSH配置FIDO2认证

发布于 2022-03-20  2416 次阅读


从OpenSSH 8.2版本开始,引入了通过FIDO2进行验证的方法。和PGP智能卡方式相比,使用FIDO2免去了更改SSH代理的麻烦,开箱即用。而对于更常见的使用私钥文件来说,由于FIDO2是独立的硬件设备,即使电脑本身不安全也不会泄露私钥。但由于标准的FIDO2设备无法复制备份私钥,一旦硬件设备损毁或丢失,在没有备用方案的情况下,就会无法通过SSH连接到服务器,所以强烈建议增加一个备用方案,例如:至少使用两个设备生成密钥、使用其他方式创建备用密钥并保留好,或是添加其他连接方式。

准备工作

首先准备FIDO2设备,不同的设备可能支持不同的加密方式,首选支持ed25519-sk方式的设备,如果没有的话可以退而求次选择支持ecdsa-sk方式的,至于更古老的RSA方式,现在已经不推荐使用了。

如果打算购买新设备的话可以选择Yubico的设备,如果有更高要求的话,也可选择其他设备或是通过开源项目自行打造。这里使用的是Yubikey 5C NFC。

其次要准备的是SSH客户端,输入ssh -V来检查版本,如果版本高于8.2,则支持FIDO2认证。若版本低于8.2,则需要升级SSH客户端版本。

在Windows系统上,可以在PowerShell的OpenSSH项目中下载新版本,下载并解压后执行install-sshd.ps1脚本安装服务。

在macOS系统上,即使客户端版本大于8.2似乎也无法使用FIDO2,原因可能是苹果的keychain也提供了保存SSH密钥的功能,所以引起了冲突。如果要使用的话,需要额外安装SSH客户端,例如用Homebrew安装。

最后,服务器端的版本也有要求,在Ubuntu 18.04 LTS中的OpenSSH 7.6p1中无法识别添加的ed25519公钥,而在Ubuntu 20.04 LTS中的OpenSSH 8.2p1中则可以正常使用。

生成密钥

FIDO2有两种密钥生成方式,分别是可发现凭证(Discoverable Credential)模式和不可发现凭证(non-Discoverable Credential)模式,这两种模式曾经被称为常驻密钥模式(Resident Key)和非常驻密钥(non-Resident Key)模式。两者的区别是可发现凭证模式会在FIDO2的存储空间内放置用户标识,另一种则不会。

体现在SSH验证中,可发现凭证模式可以在插上电脑后直接连接到SSH代理,而另一种需要配合私钥文件才会被识别,下文将会提到,这个私钥文件中并没有真正的私钥。两者之间的取舍主要是安全和便利的取舍,如果计划使用可发现凭证,最好修改PIN码来避免被盗用。

虽然由于存储空间有限,FIDO2设备中可以放置的可发现凭证是有限的,但实际上使用可发现凭证的地方并不多,除了用于ssh中,目前只见到过微软账号的无账号功能会用到,对于Yubikey 5C的25个数量限制来说,其实空间很足够。

使用如下命令来生成密钥:

ssh-keygen -t 加密方式 -f 文件输出路径
或
ssh-keygen -t 加密方式 -O resident -f 文件输出路径

例如:

ssh-keygen -t ed25519-sk -O resident -f ~/.ssh/id_ ed25519-sk

其中-O resident参数的意思是生成可发现凭证,-f参数为指定输出文件的路径,可以省略不写,这时通常会输出到~/.ssh/中。此外,可以在命令中加入no-touch-required取消认证时需要按下设备上的按钮,但会降低安全性,并不推荐。

执行之后按照提示,插入设备,输入PIN码和按下按钮,此时密钥就生成完成了。接下来还会要求输入私钥的文件的密码和文件名,当然这两项可以不填。这时生成的私钥和通常情况下不同,根据OpenSSH的说法,这个私钥文件中并没有真正的私钥,而是“密钥句柄”,这个文件的作用是替代私钥被SSH客户端所识别;另一个后缀为.pub的则是公钥。如果生成的不是可发现凭证,记得保留好两个文件。

生成完成后,将输出文件中的公钥放入服务器的authorized_keys中即可。

使用

将之前生成的私钥放入~/.ssh/中并插入设备即可使用,如果有多个的话,使用ssh -i 文件路径来指定使用的私钥。

如果使用可发现凭证,即使没有私钥,在插入设备后,也可以通过执行ssh-add -K命令的方式让SSH代理识别到,使用ssh-add -L来检查SSH代理存储的内容,不过这种方式重启后就会失效。如果执行ssh-keygen -K则可以读取设备来重新生成私钥和公钥。

安全提醒

虽然将私钥放置在加密设备中可以避免被远程盗取,但如果电脑本身不安全也可能会趁着连接的时候偷偷执行命令。另外,如果原本使用密码登录的话,记得关闭密码登录,不然即使设置了私钥登录也无法阻止密码登录。

题外话

在测试时使用VMware安装Ubuntu来测试Linux上的用法,然而发现VMware的智能卡直通并不能完全将Yubikey直通进虚拟机导致无法读取,参考了一下Yubico的说明VMware的论坛在虚拟机的vmx文件中添加如下配置就可以将Yubikey给虚拟机独占来解决问题:

usb.generic.allowHID = "TRUE"
usb.generic.allowLastHID = "TRUE"

usb.generic.allowCCID = "TRUE"
usb.ccid.disable = "TRUE"

另外在Windows中测试时即使下载了新版本的SSH,也总是无法通过ssh-add -K来加载,或许等到以后正式搭载到Windows中就能解决问题了。

参考文章

https://blog.getevo.top/archives/ssh配置fido2usb验证器无密码登录

https://www.freebuf.com/articles/system/247237.html

https://www.stavros.io/posts/u2f-fido2-with-ssh/