本篇介紹如何在 macOS 中使用 SSH 搭配 Yubico 的 FIDO U2F Security Key 實體金鑰認證,登入遠端的 Linux 伺服器。


今天跟同事借了一支 Yubico 的 FIDO U2F Security Key,這一支是比較舊款的實體金鑰,只支援 FIDO U2F,不過還是很適合用於一般的 SSH 遠端登入。

FIDO U2F Security Key

FIDO U2F Security Key

FIDO U2F Security Key

FIDO U2F Security Key

安裝 libfido2

在使用 Yubico 的金鑰之前,要先安裝 Yubico 的 libfido2 函式庫,這裡我以 macOS 為例,以 brew 來安裝:

# 安裝 libfido2
brew install libfido2

安裝 OpenSSH

由於 OpenSSH 在 8.2 版之後才支援 FIDO U2F,所以要先把 macOS 系統上的 OpenSSH 更新到最新版:

# 安裝 openssh
brew install openssh

更新完 OpenSSH 後,開啟新的終端機,確認 ssh 的版本:

# 確認 ssh 版本
ssh -V
OpenSSH_9.0p1, OpenSSL 1.1.1o  3 May 2022

檢查 Yubico 金鑰

若要確認 Yubico 金鑰是否有被 macOS 抓到,可以將金鑰插入 macOS 之後,使用 ioreg 指令查看 USB 的設備:

# 查看 USB 設備
ioreg -p IOUSB
+-o Root  <class IORegistryEntry, id 0x100000100, retain 23>
  +-o AppleUSBXHCI Root Hub Simulation@00000000  <class AppleUSBRootHubDevice, id 0x1000004fa, registered, matched, active, busy 0 (3 ms), retain 12>
  | +-o USB3.0 Hub             @00200000  <class AppleUSBDevice, id 0x100004a0b, registered, matched, active, busy 0 (0 ms), retain 14>
  |   +-o USB 10/100/1000 LAN@00230000  <class AppleUSBDevice, id 0x100004a8a, registered, matched, active, busy 0 (0 ms), retain 14>
  |   +-o USB3.0 Hub             @00220000  <class AppleUSBDevice, id 0x100004a94, registered, matched, active, busy 0 (0 ms), retain 13>
  |     +-o Flash Card Reader/Writer@00224000  <class AppleUSBDevice, id 0x100004aff, registered, matched, active, busy 0 (0 ms), retain 12>
  +-o AppleUSBVHCIBCE Root Hub Simulation@80000000  <class AppleUSBRootHubDevice, id 0x100000501, registered, matched, active, busy 0 (4 ms), retain 15>
  | +-o Headset@80400000  <class AppleUSBDevice, id 0x100000507, registered, matched, active, busy 0 (4 ms), retain 11>
  | +-o Touch Bar Display@80600000  <class AppleUSBDevice, id 0x10000050b, registered, matched, active, busy 0 (4 ms), retain 13>
  | +-o Touch Bar Backlight@80700000  <class AppleUSBDevice, id 0x100000510, registered, matched, active, busy 0 (4 ms), retain 11>
  | +-o Ambient Light Sensor@80300000  <class AppleUSBDevice, id 0x100000515, registered, matched, active, busy 0 (4 ms), retain 11>
  | +-o Apple T2 Controller@80100000  <class AppleUSBDevice, id 0x10000051d, registered, matched, active, busy 0 (4 ms), retain 13>
  | +-o FaceTime HD Camera (Built-in)@80200000  <class AppleUSBDevice, id 0x100000522, registered, matched, active, busy 0 (5 ms), retain 13>
  | +-o Apple Internal Keyboard / Trackpad@80500000  <class AppleUSBDevice, id 0x100004bd6, registered, matched, active, busy 0 (1 ms), retain 20>
  +-o AppleUSBXHCI Root Hub Simulation@14000000  <class AppleUSBRootHubDevice, id 0x10000056e, registered, matched, active, busy 0 (4 ms), retain 9>
    +-o USB2.0 Hub             @14400000  <class AppleUSBDevice, id 0x100004a24, registered, matched, active, busy 0 (0 ms), retain 14>
      +-o USB 2.0 BILLBOARD             @14440000  <class AppleUSBDevice, id 0x100004ac6, registered, matched, active, busy 0 (1 ms), retain 12>
      +-o USB2.0 Hub             @14420000  <class AppleUSBDevice, id 0x100004ad7, registered, matched, active, busy 0 (0 ms), retain 14>
        +-o HD Pro Webcam C920@14422000  <class AppleUSBDevice, id 0x100004b17, registered, matched, active, busy 0 (2 ms), retain 18>
        +-o Security Key by Yubico@14421000  <class AppleUSBDevice, id 0x1000090bb, registered, matched, active, busy 0 (1 ms), retain 12>

若要取得更詳細的 Yubico 實體金鑰資訊,可以使用 YubiKey Manager CLI,這個工具在 macOS 中可透過 brew 安裝:

# 安裝 YubiKey Manager
brew install ykman

安裝好 YubiKey Manager CLI 之後,使用 ykman 查詢 Yubico 實體金鑰資訊:

# 列出所有 Yubico 實體金鑰資訊
ykman list
FIDO U2F Security Key (4.2.7) [FIDO]

顯示 Yubico 實體金鑰詳細訊息:

# 顯示 Yubico 實體金鑰詳細訊息
ykman info
Device type: FIDO U2F Security Key
Firmware version: 4.2.7
Enabled USB interfaces: FIDO

Applications
FIDO2       	Not available	
OTP         	Not available	
FIDO U2F    	Enabled      	
OATH        	Not available	
YubiHSM Auth	Not available	
OpenPGP     	Not available	
PIV         	Not available

設定 SSH 金鑰登入

將 Yubico 實體金鑰插入 macOS 電腦中,接著使用 ssh-keygen 指令建立公私鑰檔案:

# 建立 ecdsa-sk 格式公私鑰檔案
ssh-keygen -t ecdsa-sk -f ~/.ssh/id_ecdsa_sk
Generating public/private ecdsa-sk key pair.
You may need to touch your authenticator to authorize key generation.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/seal/.ssh/id_ecdsa_sk
Your public key has been saved in /Users/seal/.ssh/id_ecdsa_sk.pub
The key fingerprint is:
SHA256:SICBg/TVFPPrSEfB/V2/GuneI+AxPjiu1OaOAbCdnFU seal@MacBookPro
The key's randomart image is:
+-[ECDSA-SK 256]--+
|oo.o..o+oE.      |
|+ o .. .+...    .|
| . o  .. o  . . o|
|    =.+.. .  . ..|
|   . *..So    . .|
|      o =  + o . |
|       + ++ = o  |
|      . =o + +.. |
|       o++. o....|
+----[SHA256]-----+

執行上面這一行指令之後,要用手指按一下 Yubico 實體金鑰,並設定保護金鑰的密碼(也可以不設定,直接按下 Enter 跳過),最後就會產生一個私鑰檔案 ~/.ssh/id_ecdsa_sk 與一個公鑰檔案 ~/.ssh/id_ecdsa_sk.pub

接著將公鑰複製到遠端 Linux 伺服器,假設我們想要將 Yubico 實體金鑰用於 192.168.0.1 這台 Linux 主機的 myuser 使用者登入,可以用 ssh-copy-id 將公鑰複製到該台 Linux 主機的 myuser 帳號下:

# 將公鑰複製到遠端 Linux 伺服器
ssh-copy-id -i ~/.ssh/id_ecdsa_sk myuser@192.168.0.1

在執行這一行指令時,會需要輸入 myuser 的密碼,這行指令實際做的事情就是將公鑰內容寫入 myuser 帳號的 ~/.ssh/authorized_keys 檔案中。

由於這一支 Yubico 的 FIDO U2F Security Key 韌體版本比較舊,不支援 ed25519-sk 的金鑰格式,如果是比較新版的 Yubico 實體金鑰,可以考慮使用比較新的 ed25519-sk 金鑰格式:

# 建立 ed25519-sk 格式公私鑰檔案
ssh-keygen -t ed25519-sk -f ~/.ssh/id_ed25519_sk

測試 Yubico 實體金鑰登入

設定完成後,我們就可以嘗試使用 Yubico 實體金鑰來登入遠端的 Linux 主機:

# 以 Yubico 實體金鑰登入遠端 Linux 主機
ssh myuser@192.168.0.1

執行登入指令後,我們要用手指按一下 Yubico 實體金鑰,這樣就可以使用 Yubico 實體金鑰登入遠端 Linux 主機了。

Confirm user presence for key ECDSA-SK SHA256:UfKCcfDhXt7sHCGjpSZ5wBirQ/3C546b7L9jPMFecrg
User presence confirmed
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-110-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Mon May 16 15:09:24 CST 2022

  System load:  0.04               Processes:             171
  Usage of /:   78.0% of 93.73GB   Users logged in:       0
  Memory usage: 5%                 IPv4 address for ens3: 192.168.0.1
  Swap usage:   0%

 * Super-optimized for small spaces - read how we shrank the memory
   footprint of MicroK8s to make it the smallest full K8s around.

   https://ubuntu.com/blog/microk8s-memory-optimisation

0 updates can be applied immediately.


Last login: Mon May 16 15:08:55 2022 from 192.168.0.2

如果在執行 ssh 登入指令時,沒有插入 Yubico 實體金鑰,就無法使用該實體金鑰登入,錯誤訊息會類似這樣:

Confirm user presence for key ECDSA-SK SHA256:UfKCcfDhXt7sHCGjpSZ5wBirQ/3C546b7L9jPMFecrg
sign_and_send_pubkey: signing failed for ECDSA-SK "/Users/seal/.ssh/id_ecdsa_sk": device not found

限制實體金鑰登入

如果測試過實體金鑰可以正常登入之後,可以考慮將密碼認證功能關閉,並只接受實體金鑰登入,排除其他軟體類型的金鑰,讓系統更安全:

# 不接受密碼認證
PasswordAuthentication no

# 只接受 ed25519-sk 與 ecdsa-sk 類型的金鑰
PubkeyAcceptedKeyTypes sk-ecdsa-sha2-nistp256@openssh.com,sk-ssh-ed25519@openssh.com

不過這樣的設定需要非常小心,因為一但實體金鑰不見了,就會完全無法透過 SSH 登入系統。各種金鑰類型的比較,可參考 SSH implementation comparison

設定完成後,重新啟動 ssh 服務:

# 重新啟動 ssh 服務
sudo systemctl restart ssh

使用 ssh-agent

macOS 系統預設啟動的 ssh-agent/System/Library/LaunchAgents/com.openssh.ssh-agent.plist 中指定的 /usr/bin/ssh-agent,但是這個版本太舊了,無法支援 FIDO U2F,所以若要使用 ssh-agent 的功能,就必須手動啟動 /usr/local/bin/ssh-agent,以下是操作範例。

# 啟動 ssh-agent
eval `ssh-agent`

# 加入金鑰
ssh-add ~/.ssh/id_ed25519_sk

# 進行 SSH 連線(啟用 agent forwarding)
ssh -A myuser@192.168.0.1

# 停止 ssh-agent
ssh-agent -k

參考資料