發現最近幾年 OpenSSH 開始支援 FIDO2 驗證,於是買了一支 Security Key NFC by Yubico 來試試。(這是只有 FIDO 功能的實體金鑰,不是完整版的 Yubikey。)
前置準備
雖然使用 Security Key NFC (下稱 FIDO2 key) 在登入各種網頁服務的時候通常不需要輸入 FIDO2 PIN,但若想用在 SSH 則必須為它設定一組 PIN。(無論後續登入 SSH 是否要求 PIN 都需要設定。)
參照 Understanding YubiKey PINs 的說明,新的 Key 沒有設定初始的 FIDO2 PIN,於是我們來為它設定一組 PIN。
註:由於 FIDO2 驗證需要 OpenSSH 8.3 以上版本,此處作業系統環境以安裝 OpenSSH 8.9p1 的 Ubuntu 22.04 LTS 為例。
雖然參考文件提到 OpenSSH 8.2p1 亦部份支援 Non-discoverable key 認證,但筆者在安裝 OpenSSH 8.2p1 的 Ubuntu 20.04 LTS 環境只能實做出「觸摸」FIDO2 key 即完成驗證的設定,做不出「會詢問 FIDO2 PIN」的設定。
我們可以使用 ykman (YubiKey Manager CLI) 設定 FIDO2 PIN。以 Ubuntu 為例,從 PPA 安裝 ykman 的指令為:
sudo apt-add-repository ppa:yubico/stable sudo apt update sudo apt install yubikey-manager
安裝完成後,可使用 ykman fido access change-pin
指令設定初始 FIDO2 PIN,例如將 PIN 設定為「123456」:
ykman fido access change-pin --new-pin 123456
Authenticator-hosted 金鑰的兩種模式
參照 Securing SSH with FIDO2 的介紹,綁定 FIDO2 的 SSH key 有兩種運作模式,分別是 Non-Discoverable 與 Discoverable (resident) 兩種類型的金鑰。
Non-discoverable 金鑰有以下特點:
- SSH 公私鑰 (即置於
~/.ssh/
的 Identity file) 與 FIDO2 Key 是綁定在一起的,如同其他類型的金鑰,不同的私鑰不能跟同一組公鑰 + FIDO2 Key 做驗證。 - 對注重隱私的使用者來說,即使遺失了 FIDO2 key,若沒持有對應的 SSH 私鑰也不會被誤用。
Discoverable (resident) 金鑰有以下特點:
- 不同的 SSH 私鑰可以跟同一組公鑰 + FIDO2 key 做驗證。
- 適合在不同的本地端 (如公用電腦) 上使用,不需要複製原本的秘鑰 (Identity file),可以隨時隨地產生跟 FIDO2 key 配對的私鑰後,SSH 登入遠端的伺服器。
使用 Non-discoverable 金鑰的 FIDO2 key 設定方法
本地端設定
- 將 FIDO2 key 插入電腦。
- 在終端機使用以下指令產生跟 FIDO2 key 配對的 SSH 公私鑰 (以 ed25519 演算法秘鑰為例):
ssh-keygen -t ed25519-sk -O verify-required
執行過程如下:
~$ ssh-keygen -t ed25519-sk -O verify-required Generating public/private ed25519-sk key pair. You may need to touch your authenticator to authorize key generation. Enter PIN for authenticator: (輸入 FIDO2 PIN,如 123456) (此時 FIDO2 key 實體鍵會閃爍,觸摸它。) Enter file in which to save the key (/home/alice/.ssh/id_ed25519_sk): Enter passphrase (empty for no passphrase): (為私鑰設定密碼,可留空) Enter same passphrase again: (再輸入一次私鑰密碼,或是留空) Your identification has been saved in /home/alice/.ssh/id_ed25519_sk Your public key has been saved in /home/alice/.ssh/id_ed25519_sk.pub The key fingerprint is: SHA256:K4C/oYWhJ0QBCUQDgm5AXbPpmkMySq5nj84CrSX4Ys4 alice@myhost The key's randomart image is: +[ED25519-SK 256]-+ |&B. .o | |= o. + | |o. o | |.o .. | |o*o... S | |O.*+o. . | |=*o++ . . | |*=++.o . | |+E=.o | +----[SHA256]-----+
於是我們在家目錄的 ~/.ssh/
產生了一組公私鑰 id_ed25519_sk
與 id_ed25519_sk.pub
。
接著,將公鑰複製到遠端的伺服器上:
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub alice@myserver1
註:alice 是遠端的使用者名稱,myserver1 是遠端的主機名稱(或域名)。請代換為您的設定。
遠端設定
雖然我們將公鑰複製到遠端伺服器了,若此時直接從本地端登入遠端,OpenSSH 預設只會要求使用者觸摸 FIDO2 key,而不會要求輸入 FIDO2 PIN。為了讓 OpenSSH 能夠要求 FIDO2 PIN,我們需要在遠端伺服器做額外設定。
我們已經在遠端家目錄的 ~/.ssh/authorized_keys
儲存了一筆公鑰,長得像這樣:
[email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIilYYxbMZ5adtCH1ueFuIsbUqPM4B/ytDDho0iKfX6VAAAABHNzaDo= alice@myhost
編輯 ~/.ssh/authorized_keys
,在這支公鑰設定的最前面插入 verify-required
字樣,並與最前面的 sk-ssh-ed25519...
以空號分隔。編輯後的設定會像這樣:
verify-required [email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIIilYYxbMZ5adtCH1ueFuIsbUqPM4B/ytDDho0iKfX6VAAAABHNzaDo= alice@myhost
至此,我們完成了設定,讓遠端的 OpenSSH server 會在登入時要求 FIDO2 PIN 做驗證了。
註:亦可在遠端的 OpenSSH server 啟用全域設定。
編輯
/etc/ssh/sshd_config
並插入以下設定:PubkeyAuthOptions verify-required即可對所有跟 FIDO2 key 配對的公鑰進行 FIDO2 PIN 驗證。這不影響其他沒有跟實體金鑰配對的金鑰 (即不是 Authenticator-hosted 的金鑰。)
從本地端測試 SSH + FIDO2 key 登入遠端
回到本地端,我們終於可以來實測 SSH + FIDO2 key 登入遠端了。步驟如下:
- 將 FIDO2 key 插入電腦。
- 在終端機使用以下指令登入遠端:
ssh -i ~/.ssh/id_ed25519_sk alice@myserver1
執行過程如下:
~$ ssh -i ~/.ssh/id_ed25519_sk alice@myserver1 Enter passphrase for key '/home/alice/.ssh/id_ed25519_sk': (輸入 SSH 私鑰的密碼,如果有的話) Enter PIN for ED25519-SK key /home/alice/.ssh/id_ed25519_sk: (輸入 FIDO2 PIN,如 123456) (此時 FIDO2 key 實體鍵會閃爍,觸摸它。) Confirm user presence for key ED25519-SK SHA256:K4C/oYWhJ0QBCUQDgm5AXbPpmkMySq5nj84CrSX4Ys4 User presence confirmed Welcome to Ubuntu 22.04.2 LTS ... alice@myserver1:~$
經由上述過程,我們成功透過輸入 FIDO2 PIN 之後登入遠端伺服器了。
使用 Discoverable (resident) 金鑰的 FIDO2 key 設定方法
這節將介紹如何使用多把秘鑰跟一組公鑰 + FIDO2 key 做配對,並登入遠端伺服器。
在第一台本地端做設定
- 將 FIDO2 key 插入電腦。
- 在終端機使用以下指令產生跟 FIDO2 key 配對的 SSH 公私鑰 (以 ed25519 演算法秘鑰為例):
ssh-keygen -t ed25519-sk -O resident -O application=ssh:mykey1 -O verify-required
註:mykey1 可以自取為任何名稱,方便自己辨識鑰匙即可。
執行過程如下:
~$ ssh-keygen -t ed25519-sk -O resident -O application=ssh:mykey1 -O verify-required Generating public/private ed25519-sk key pair. You may need to touch your authenticator to authorize key generation. Enter PIN for authenticator: (輸入 FIDO2 PIN,如 123456) (此時 FIDO2 key 實體鍵會閃爍,觸摸它。) Enter file in which to save the key (/home/alice/.ssh/id_ed25519_sk): Enter passphrase (empty for no passphrase): (為私鑰設定密碼,可留空) Enter same passphrase again: (再輸入一次私鑰密碼,或是留空) Your identification has been saved in /home/alice/.ssh/id_ed25519_sk Your public key has been saved in /home/alice/.ssh/id_ed25519_sk.pub The key fingerprint is: SHA256:+6GG/KmF/C7welqRP3V11yn5G9tLAkcEbzwoRGoRhi8 alice@myhost1 The key's randomart image is: +[ED25519-SK 256]-+ | .+oo ... | | .. + = . o| | .o . . O..+| | E.o . o.+..| | + S .... o | | .. + o .o =| | ++.= . . +.| | .*o.= . o .| | o+.** . . | +----[SHA256]-----+
於是我們在家目錄的 ~/.ssh/
產生了一組公私鑰 id_ed25519_sk
與 id_ed25519_sk.pub
。
接著,將公鑰複製到遠端的伺服器上:
ssh-copy-id -i ~/.ssh/id_ed25519_sk.pub alice@myserver1
註:alice 是遠端的使用者名稱,myserver1 是遠端的主機名稱(或域名)。請代換為您的設定。
遠端設定
為了讓 OpenSSH 能夠要求 FIDO2 PIN,我們需要在遠端伺服器做額外設定。
我們已經在遠端家目錄的 ~/.ssh/authorized_keys
儲存了一筆公鑰,長得像這樣:
[email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIBDe/oKY7ph1d7immr2PgHKW72NfUB11r0P/OnkamNaoAAAACnNzaDpteWtleTE= alice@myhost1
編輯 ~/.ssh/authorized_keys
,在這支公鑰設定的最前面插入 verify-required
字樣,並與最前面的 sk-ssh-ed25519...
以空號分隔。編輯後的設定會像這樣:
verify-required [email protected] AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIBDe/oKY7ph1d7immr2PgHKW72NfUB11r0P/OnkamNaoAAAACnNzaDpteWtleTE= alice@myhost1
至此,我們完成了設定,讓遠端的 OpenSSH server 會在登入時要求 FIDO2 PIN 做驗證了。
從第一台本地端登入遠端
回到第一台本地端,我們可以來實測 SSH + FIDO2 key 登入遠端了。步驟如下:
- 將 FIDO2 key 插入電腦。
- 在終端機使用以下指令登入遠端:
ssh -i ~/.ssh/id_ed25519_sk alice@myserver1
執行過程如下:
$ ssh -i ~/.ssh/id_ed25519_sk alice@myserver1 Enter passphrase for key '/home/alice/.ssh/id_ed25519_sk': (輸入 SSH 私鑰的密碼,如果有的話) Enter PIN for ED25519-SK key /home/alice/.ssh/id_ed25519_sk: (輸入 FIDO2 PIN,如 123456) (此時 FIDO2 key 實體鍵會閃爍,觸摸它。) Confirm user presence for key ED25519-SK SHA256:+6GG/KmF/C7welqRP3V11yn5G9tLAkcEbzwoRGoRhi8 User presence confirmed Welcome to Ubuntu 22.04.2 LTS ... alice@myserver1:~$
於是,我們確認了從第一台本地端 SSH 能夠在輸入 FIDO2 PIN 之後登入遠端伺服器了。
在第二台(或更多台)的本地端產生公私鑰、並登入遠端
前面兩節介紹了如何在最一開始產生第一把跟 FIDO2 key 配對好的 SSH 公私鑰匙,此處會繼續介紹如何在第二台(以及第三台、第四台、…)以上的本地端產生各自的私鑰,並以此登入同一台遠端伺服器。
- 將 FIDO2 key 插入電腦。
- 在終端機使用以下指令,從 FIDO2 key 下載 resident key 並產生對應的 SSH 公私鑰 (以 ed25519 演算法秘鑰為例):
ssh-keygen -t ed25519-sk -K
執行過程如下:
~$ ssh-keygen -t ed25519-sk -K Enter PIN for authenticator: (輸入 FIDO2 PIN,如 123456) (此時 FIDO2 key 實體鍵會閃爍,觸摸它。) You may need to touch your authenticator to authorize key download. Enter passphrase (empty for no passphrase): (為私鑰設定密碼,可留空) Enter same passphrase again: (再輸入一次私鑰密碼,或是留空) Saved ED25519-SK key ssh:mykey1 to id_ed25519_sk_rk_mykey1
於是我們在工作目錄產生了一組公私鑰 id_ed25519_sk_rk_mykey1
與 id_ed25519_sk_rk_mykey1.pub
。不需要再將此處的公鑰以 ssh-copy-id
上傳到遠端。
註:這裡產生的公私鑰不會自動存到家目錄的
~/.ssh/
。如果這組公私鑰是這台本地端電腦上唯一的一組秘鑰,可以考慮將它們更名為id_ed25519_sk
&id_ed25519_sk.pub
並移動到~/.ssh/
目錄下。
有了第二台(或更多台)本地端的新私鑰,我們可以直接拿它來登入遠端了。步驟如下:
- 一樣,將 FIDO2 key 插入電腦。
- 在終端機使用以下指令登入遠端:
ssh -i ./id_ed25519_sk_rk_mykey1 alice@myserver1
執行過程如下:
~$ ssh -i ./id_ed25519_sk_rk_mykey1 alice@myserver1 Enter passphrase for key './id_ed25519_sk_rk_mykey1': (輸入 SSH 私鑰的密碼,如果有的話) Enter PIN for ED25519-SK key ./id_ed25519_sk_rk_mykey1: (輸入 FIDO2 PIN,如 123456) (此時 FIDO2 key 實體鍵會閃爍,觸摸它。) Confirm user presence for key ED25519-SK SHA256:+6GG/KmF/C7welqRP3V11yn5G9tLAkcEbzwoRGoRhi8 User presence confirmed Welcome to Ubuntu 22.04.2 LTS ... alice@myserver1:~$
最後,我們確認了從第二台(或更多台)本地端能夠使用不同 SSH 私鑰,登入「儲存了從第一台本地端 FIDO2 key 配對產生的公鑰」的遠端伺服器了。