適用於 Windows 的 OpenSSH 中的金鑰型驗證

適用於 Windows Server 2022、Windows Server 2019、Windows 10 (組建 1809 及更高版本)

Windows 環境中大部分的驗證都是利用使用者名稱-密碼對來完成,這適用於共用通用網域的系統。 跨網域 (例如在內部部署和雲端託管系統之間) 工作時,會變得容易遭到暴力密碼破解入侵。

相較之下,Linux 環境通常會使用公開金鑰/私密金鑰組來驅動驗證,不需要使用可猜測的密碼。 OpenSSH 包含有助於支援金鑰型驗證的工具,尤其是:

  • ssh-keygen,用來產生安全金鑰
  • ssh-agentssh-add,用來安全地儲存私密金鑰
  • scpsftp,在初始使用伺服器期間安全地複製公開金鑰檔案

本文件概述如何在 Windows 上使用這些工具,開始搭配 SSH 使用金鑰型驗證。 如果您不熟悉 SSH 金鑰管理,我們強烈建議您檢閱 NIST 文件 IR 7966,標題為「使用安全殼層 (SSH) 的互動式和自動化存取管理的安全性」。

關於金鑰組

金鑰組指的是特定驗證通訊協定所使用的公開和私密金鑰檔案。

SSH 公開金鑰驗證會使用非對稱式密碼編譯演算法來產生兩個金鑰檔案 - 一個「私密」、另一個「公用」。 私密金鑰檔案相當於密碼,且在所有情況下都應受到保護。 如果有人取得您的私密金鑰,他們就可以登入您有權存取的任何 SSH 伺服器。 公開金鑰是放在 SSH 伺服器上的金鑰,而且可以在不危及私密金鑰的情況下共用。

金鑰型驗證會啟用 SSH 伺服器和用戶端來根據私密金鑰提供的使用者名稱來比較公開金鑰。 如果無法根據用戶端私密金鑰驗證伺服器端公開金鑰,驗證就會失敗。

多重要素驗證可以使用金鑰組來實作,方法是在產生金鑰組時輸入複雜密碼 (請參閱以下的使用者金鑰產生)。 在驗證期間,系統會提示使用者輸入複雜密碼。 複雜密碼與 SSH 用戶端上存在的私密金鑰一起使用,以對使用者進行身分驗證。

重要

透過金鑰型驗證開啟的遠端工作階段沒有相關聯的使用者認證,因此無法以使用者身分進行輸出驗證,這是設計使然。

主機金鑰產生

公開金鑰具有特定的 ACL 需求,在 Windows 上等同於只允許系統管理員和系統的存取權。 第一次使用 sshd 時,將會自動產生主機的金鑰組。

重要

您必須先安裝 OpenSSH 伺服器。 請參閱開始使用 OpenSSH

根據預設,sshd 服務會設定為手動啟動。 若要在每次重新啟動伺服器時啟動該服務,請伺服器上提升權限的 PowerShell 提示字元執行下列命令:

# Set the sshd service to be started automatically
Get-Service -Name sshd | Set-Service -StartupType Automatic

# Now start the sshd service
Start-Service sshd

因為沒有與 sshd 服務相關聯的使用者,所以主機金鑰會儲存在 C:\ProgramData\ssh 底下。

使用者金鑰產生

若要使用金鑰型驗證,您必須先為您的用戶端產生公開/私密金鑰組。 ssh-keygen.exe 可用來產生金鑰檔案,而且可以指定 DSA、RSA、ECDSA 或 Ed25519 演算法。 如果未指定任何演算法,則會使用 RSA。 應使用強式演算法和金鑰長度,例如本範例中的 Ed25519。

若要使用 Ed25519 演算法產生金鑰檔案,可在用戶端上從 PowerShell 或 Cmd 提示字元執行下列命令:

ssh-keygen -t ed25519

命令的輸出應顯示下列輸出 (其中 “username” 會由您的使用者名稱取代):

Generating public/private ed25519 key pair.
Enter file in which to save the key (C:\Users\username/.ssh/id_ed25519):

您可以按 Enter 鍵接受預設值,或指定您想要產生金鑰所在的路徑及或檔案名稱。 此時,系統會提示您使用複雜密碼來加密您的私密金鑰檔案。 複雜密碼可以是空的,但不建議這麼做。 複雜密碼可與金鑰檔案搭配使用,以提供雙因素驗證。 在此範例中,我們會將複雜密碼保留空白。

Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\username/.ssh/id_ed25519.
Your public key has been saved in C:\Users\username/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:OIzc1yE7joL2Bzy8!gS0j8eGK7bYaH1FmF3sDuMeSj8 username@LOCAL-HOSTNAME

The key's randomart image is:
+--[ED25519 256]--+
|        .        |
|         o       |
|    . + + .      |
|   o B * = .     |
|   o= B S .      |
|   .=B O o       |
|  + =+% o        |
| *oo.O.E         |
|+.o+=o. .        |
+----[SHA256]-----+

現在,您在指定的位置中有公用/私人 ed25519 金鑰組。 .pub 檔案是公開金鑰,沒有副檔名的檔案是私密金鑰:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----         6/3/2021   2:55 PM            464 id_ed25519
-a----         6/3/2021   2:55 PM            103 id_ed25519.pub

請記住,私密金鑰檔案相當於密碼,應該與保護密碼的方式一樣加以保護。 使用 ssh-agent 可安全地將私密金鑰儲存在 Windows 安全性內容中,並與您的 Windows 帳戶產生關聯。 若要在每次重新啟動電腦時啟動 ssh-agent 服務,並使用 ssh-add 來儲存私密金鑰,請從伺服器上己提升權限的 PowerShell 提示字元執行下列命令:

# By default the ssh-agent service is disabled. Configure it to start automatically.
# Make sure you're running as an Administrator.
Get-Service ssh-agent | Set-Service -StartupType Automatic

# Start the service
Start-Service ssh-agent

# This should return a status of Running
Get-Service ssh-agent

# Now load your key files into ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

將私密金鑰新增至用戶端上的 ssh-agent 後,ssh-agent 會自動擷取本機私密金鑰,並將其傳遞至 SSH 用戶端。

重要

強烈建議您將私密金鑰備份至安全的位置,然後在將它新增至 ssh-agent 之後,從本機系統將它刪除。 私密金鑰無法從提供強式演算法的代理程式擷取,例如此範例中的 Ed25519。 如果您失去私密金鑰的存取權,就必須建立新的金鑰組,並且在您互動的所有系統上更新公開金鑰。

部署公開金鑰

若要使用上面建立的使用者密鑰,公開金鑰的內容 (\.ssh\id_ed25519.pub) 必須放在伺服器上,才能放入文字檔中。 檔案的名稱和位置取決於使用者帳戶是本機系統管理員群組的成員,還是標準使用者帳戶。 以下各章節涵蓋標準和系統管理使用者。

標準使用者

公開金鑰的內容 (\.ssh\id_ed25519.pub) 必須放在伺服器上,以 C:\Users\username\.ssh\ 呼叫的文字檔 (稱為 authorized_keys) 中。 您可以使用 OpenSSH scp 安全檔案傳輸公用程式,或使用 PowerShell 將金鑰寫入檔案來複製公開金鑰。

下列範例會將公開金鑰複製到伺服器 (其中 “username” 會由您的使用者名稱取代)。 您一開始需要針對伺服器的使用者帳戶使用密碼。

# Get the public key file generated previously on your client
$authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ed25519.pub

# Generate the PowerShell to be run remote that will copy the public key file generated previously on your client to the authorized_keys file on your server
$remotePowershell = "powershell New-Item -Force -ItemType Directory -Path $env:USERPROFILE\.ssh; Add-Content -Force -Path $env:USERPROFILE\.ssh\authorized_keys -Value '$authorizedKey'"

# Connect to your server and run the PowerShell using the $remotePowerShell variable
ssh username@domain1@contoso.com $remotePowershell

系統管理使用者

公開金鑰的內容 (\.ssh\id_ed25519.pub) 必須放在伺服器上,以 C:\ProgramData\ssh\ 呼叫的文字檔 (稱為 administrators_authorized_keys) 中。 您可以使用 OpenSSH scp 安全檔案傳輸公用程式,或使用 PowerShell 將金鑰寫入檔案來複製公開金鑰。 此檔案上的 ACL 必須設定為只允許存取系統管理員和系統。

下列範例會將公開金鑰複製到伺服器,並設定 ACL (其中 “username” 會取代為您的使用者名稱)。 您一開始需要針對伺服器的使用者帳戶使用密碼。

注意

此範例展示建立 administrators_authorized_keys 檔案的步驟。 這僅適用於管理員帳戶,而且必須使用,而不是使用者設定檔位置中的每個使用者檔案。

# Get the public key file generated previously on your client
$authorizedKey = Get-Content -Path $env:USERPROFILE\.ssh\id_ed25519.pub

# Generate the PowerShell to be run remote that will copy the public key file generated previously on your client to the authorized_keys file on your server
$remotePowershell = "powershell Add-Content -Force -Path $env:ProgramData\ssh\administrators_authorized_keys -Value '''$authorizedKey''';icacls.exe ""$env:ProgramData\ssh\administrators_authorized_keys"" /inheritance:r /grant ""Administrators:F"" /grant ""SYSTEM:F"""

# Connect to your server and run the PowerShell using the $remotePowerShell variable
ssh username@domain1@contoso.com $remotePowershell

針對非英文版的作業系統當地語系化版本,指令碼必須據以修改以反映群組名稱。 若要防止將權限授予群組名稱時發生錯誤,可以在其位置使用安全性識別碼 (SID)。 您可以執行 Get-LocalGroup | Select-Object Name, SID來擷取 SID。 使用 SID 取代群組名稱時,其前面必須加上星號 (*)。 在以下範例中,Administrators 群組會使用 SIDS-1-5-32-544

$remotePowershell = "powershell Add-Content -Force -Path $env:ProgramData\ssh\administrators_authorized_keys -Value '''$authorizedKey''';icacls.exe ""$env:ProgramData\ssh\administrators_authorized_keys"" /inheritance:r /grant ""*S-1-5-32-544:F"" /grant ""SYSTEM:F"""

這些步驟會完成在 Windows 上搭配 OpenSSH 使用金鑰型驗證所需的設定。 執行範例 PowerShell 命令之後,使用者就可以從具有私密金鑰的任何用戶端連線到 sshd 主機。