SSH 密鑰

出自 Arch Linux 中文维基

對於使用公鑰加密質詢-應答式認證的 SSH 服務器,SSH 密鑰可以為您提供證明身份的方法。基於密鑰的認證主要優點在於,與密碼認證相比,它不易遭受暴力破解攻擊,且在服務器被攻破的情況下也不會泄露您的有效憑證。[1]

不僅如此,與傳統的密碼認證相比,SSH 密鑰認證也可以更加便利。當與被稱作 SSH agent 的程序共用時,SSH 密鑰可以讓您無需記住或輸入每個系統的密碼,就能夠連接到一個或多個服務器。

基於密鑰的認證並非沒有缺點,可能也並非適用於一切環境,但在很多情況下可以提供一些有力的優勢。對 SSH 密鑰如何工作的概略理解會幫助您決定如何以及何時使用它們,以滿足您的需求。

本文假定您已經對於 SSH 有了基本理解,並安裝openssh 軟件包。

背景[編輯 | 編輯原始碼]

SSH 密鑰都是成對生成的,其一稱為公鑰,另一則稱為私鑰。私鑰只由您所知,必須安全保管。相對地,公鑰可以向您想連接的任何 SSH 服務器自由地共享。

如果一個 SSH 服務器在文件中存有您的公鑰,並收到了您的連接請求,就會使用您的公鑰構建一個質詢問題並發送給您。這一質詢問題是一條加密信息,必須得到正確應答,服務器才能允許您訪問。這條編碼信息特別安全是在於,只有私鑰持有者才能理解它。公鑰可以用來加密信息,但不能用來解密同一條信息。只有您,私鑰的持有者,能夠正確理解這一質詢問題並產生合適的應答。

這一質詢-應答過程發生在後台,對用戶不可見。只要您持有私鑰(一般存放在 ~/.ssh/ 目錄下),您的 SSH 客戶端就應當能夠向服務器回復正確的應答。

私鑰是受保護的秘密,因此建議以加密形式將其存儲在磁盤上。當需要被加密的私鑰時,為了解密它,需要先輸入密碼。雖然這在表面上可能像是您在向 SSH 服務器提供登錄密碼,但該密碼只用於解密本地系統上的私鑰。該密碼並未通過網絡傳輸。

生成密鑰對[編輯 | 編輯原始碼]

通過運行 ssh-keygen 命令可以生成密鑰對,默認為3072位的 RSA(以及 SHA256),ssh-keygen(1) 手冊頁稱其「一般被認為充足」且應當兼容於幾乎所有客戶端和服務器:

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/<username>/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/<username>/.ssh/id_rsa.
Your public key has been saved in /home/<username>/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:gGJtSsV8BM+7w018d39Ji57F8iO6c0N2GZq3/RY2NhI username@hostname
The key's randomart image is:
+---[RSA 3072]----+
|   ooo.          |
|   oo+.          |
|  + +.+          |
| o +   +     E . |
|  .   . S . . =.o|
|     . + . . B+@o|
|      + .   oo*=O|
|       .   ..+=o+|
|           o=ooo+|
+----[SHA256]-----+

randomart 圖像作為一種簡便的密鑰指紋視覺辨識方式在 OpenSSH 5.1 中引入。

注意: 可以使用 -a 開關來指定密碼加密的 KDF rounds 數量。

也可以用 -C 開關對公鑰添加可選的注釋欄,從而在 ~/.ssh/known_hosts~/.ssh/authorized_keys 以及 ssh-add -L 輸出等處更輕鬆地辨識它。例如:

$ ssh-keygen -C "$(whoami)@$(uname -n)-$(date -I)"

會添加一條注釋,說明是哪個用戶何時在哪台機器上創建的密鑰。

選擇認證密鑰種類[編輯 | 編輯原始碼]

OpenSSH(對於認證密鑰)支持數種簽名算法,按照所採用的數學性質可分為兩類:

  1. DSA 以及 RSA,依賴於對兩個大質數之積進行分解的實際困難
  2. ECDSA 以及 Ed25519,依賴於橢圓曲線離散對數問題。(

橢圓曲線密碼學(ECC)算法是對於公鑰密碼體制的較新發展。其主要優勢之一是以較小密鑰提供同等安全性的能力,使得計算密集操作更少(也就是密鑰創建、加密及解密更快)且存儲及傳輸的要求更低。

由於已發現的漏洞,OpenSSH 7.0廢棄並禁用了對 DSA 密鑰的支持,因此密碼體制的選擇範圍就限定在了 RSA 或兩種 ECC 之一當中。

#RSA 密鑰會提供最大的可移植性,而 #Ed25519 會提供最佳的安全性,但需要新版本的客戶端與服務器[2]。. #ECDSA 兼容性可能比 Ed25519 更好(雖然還是不如 RSA),但存在對於其安全性的懷疑(見下文)。

注意: 這些密鑰只用於認證您的身份;選擇更強的密鑰並不會在通過SSH傳輸數據時加重 CPU 負擔。

RSA[編輯 | 編輯原始碼]

ssh-keygen 默認使用 RSA,因此無需使用 -t 選項指定它。它提供所有算法當中最佳的兼容性,但提供充足安全性所需的密鑰尺寸較大。

密鑰尺寸最小為1024位,默認為3072(見 ssh-keygen(1)),最大為 16384。

如果您想生成較強的 RSA 密鑰對(例如為了防範先進或未知攻擊以及較高級的攻擊者),只需為 -b 選項指定比默認高一點的值:

$ ssh-keygen -b 4096

需要明白的是,使用更長的密鑰存在收益遞減。[3][4] GnuPG 常見問答記載:「如果你需要的安全性比 RSA-2048 所提供的更強,應該做的是改用橢圓曲線密碼學——而不是接着使用 RSA。」[5]

另一方面,最新版本的 NSA Fact Sheet Suite B Cryptography 建議對於 RSA 使用最少3072位的模,同時「為即將到來的抗量子算法遷移(做準備)」。[6]

ECDSA[編輯 | 編輯原始碼]

橢圓曲線數字簽名算法(ECDSA)在 OpenSSH 5.7中作為首選的認證算法被引入。一些提供商也由於潛在的專利問題禁用了所需的實現。

對於它的擔憂有兩種:

  1. 政治上的擔憂:在 NSA(美國國家安全局)被曝在軟件、硬件組件及發布的標準中蓄意植入後門之後,由 NIST(美國國家標準技術研究所)產生的曲線的可信性受到了質疑;密碼領域的知名人士對於 NIST 曲線的設計方式表示 懷疑,並且之前已經有主動的污染 證實
  2. 技術上的擔憂:對於正確實現該標準的困難以及在實現不夠謹慎情況下降低安全性的遲緩與設計缺陷

libssh curve25519 介紹當中很好地總結了上述擔憂。儘管政治上的擔憂仍受到爭議,但有明確的共識認為 #Ed25519 技術上更優越,因此應當優先採用。

Ed25519[編輯 | 編輯原始碼]

Ed25519 在2014年1月被引入 OpenSSH 6.5:「Ed25519 是一種能夠提供比 ECDSA 及 DSA 更佳安全性及良好性能的橢圓曲線簽名體系」。其主要長處在於速度、時間恆定運行時(從而能夠對抗側信道攻擊)以及無需晦暗不明的硬編碼常數。[7] 關於其工作方式,參見由一位 Mozilla 開發者撰寫的博客文章

它已經在眾多應用及庫中得到實現,並且在 OpenSSH 中是默認的密鑰交換算法(與密鑰簽名不同)。

Ed25519 密鑰對生成方法如下:

$ ssh-keygen -t ed25519

所有 Ed25519 密鑰都是256位,故無需設置密鑰尺寸。

注意較老的 SSH 客戶端與服務器可能不支持這些密鑰。

選擇密鑰存儲位置以及密碼短語[編輯 | 編輯原始碼]

運行 ssh-keygen 時,它會詢問您希望的私鑰文件名稱及位置。默認情況下,密鑰保存到 ~/.ssh 目錄下,並根據所使用的加密類型命名。為使下文中的示例代碼正確工作,建議您接受默認的名稱和位置。

當系統向您詢問密碼短語時,如果您在乎私鑰的安全性,請選擇難以猜到的密碼。更長、更隨機的密碼一般會更強,當私鑰落入賊人之手時更不容易被破解掉。

在沒有密碼短語的情況下生成私鑰也是可能的。雖然也許很方便,但您需要明白隨之而來的風險。在沒有密碼短語的情況下,您的私鑰會以未加密形式存儲在硬盤上。任何能接觸到您私鑰文件的人之後都能夠在您使用基於密鑰認證連接的任何 SSH 服務器面前冒用您的身份。更進一步,沒有密碼短語,您也必須信任 root 用戶,因為他可以繞過文件權限並能夠隨時訪問您未加密的私鑰文件。

注意: 從前,私鑰密碼都是以一種不安全的方式編碼的:僅一遍 MD5 散列。OpenSSH 6.5及之後版本支持一種新的、更安全的格式來編碼您的私鑰。從 OpenSSH 版本7.8開始默認使用該格式。Ed25519 密鑰一直採用新的編碼格式。只需按下節所述更改密鑰的密碼短語即可升級到新格式。

不修改密鑰對的情況下修改密碼短語[編輯 | 編輯原始碼]

如果不希望使用原本選擇的 SSH 密鑰密碼短語或者必須更換,可以使用 ssh-keygen 命令來修改密碼短語,而無需改動實際密鑰。此法也可用於將密碼編碼格式改為新標準。

$ ssh-keygen -f ~/.ssh/id_rsa -p

管理多組密鑰對[編輯 | 編輯原始碼]

對多台主機使用同一 SSH 密鑰對是可能的,儘管受到爭議[8] [9]

另一方面,使用您 OpenSSH 配置文件中的 IdentityFile 指令,為多台主機管理不同的密鑰對就比較容易了:

~/.ssh/config
Host SERVER1
   IdentitiesOnly yes
   IdentityFile ~/.ssh/id_rsa_SERVER1

Host SERVER2
   IdentitiesOnly yes
   IdentityFile ~/.ssh/id_ed25519_SERVER2

對於這些選項的完整描述見 ssh_config(5)

在硬件令牌上存儲 SSH 密鑰[編輯 | 編輯原始碼]

SSH 密鑰也可以存儲在智能卡或 USB 令牌等安全令牌上。這樣做的好處是私鑰安全地存儲在令牌上,而不是存儲在磁盤中。當使用安全令牌時,敏感的私鑰也從來不會存在於 PC 的內存當中;密碼學操作在令牌自身上進行。密碼學令牌還有一點好處是,它不與單台電腦綁定;可以將其從一台電腦上輕鬆取下,四處攜帶之後在其他電腦上使用。

硬件令牌的例子如下所述:

將公鑰複製到遠程服務器上[編輯 | 編輯原始碼]

這篇文章的某些內容需要擴充。

原因:強制公鑰認證的情況下如何實現? (在 Talk:SSH 密鑰 中討論)

創建好密鑰對之後,您需要將公鑰上傳到遠程服務器上,以便用於 SSH 密鑰認證登錄。公鑰文件名和私鑰文件名相同,只不過公鑰文件帶有擴展名 .pub 而私鑰文件名則沒有。千萬不要將私鑰上傳,私鑰應該保存在本地。

注意: 如果使用以下兩種方法外的方法請不要忘記註冊公鑰文件,您只需要命令
$ cat ~/.ssh/id_ecdsa.pub >> ~/.ssh/authorized_keys

簡易方式[編輯 | 編輯原始碼]

注意: 如果您的遠程服務器默認使用的是 non-sh 的 shell,比如 tcsh,且使用早於6.6.1p1版本的 OpenSSH,則此方法可能不奏效。見 該 bug 報告

如果您的公鑰文件為 ~/.ssh/id_rsa.pub,您只需要輸入命令

$ ssh-copy-id remote-server.org

如果您的遠程服務器用戶名與本地的不同,您需要指明用戶名

$ ssh-copy-id username@remote-server.org

如果您的公鑰文件名不是默認的 ~/.ssh/id_rsa.pub,您會得到錯誤 /usr/bin/ssh-copy-id: ERROR: No identities found。這種情況下,您需要顯式提供公鑰的位置:

$ ssh-copy-id -i ~/.ssh/id_ecdsa.pub username@remote-server.org

如果遠程服務器監聽端口不是默認的22,請在主機參數中指明:

$ ssh-copy-id -i ~/.ssh/id_ecdsa.pub -p 221 username@remote-server.org

手動方式[編輯 | 編輯原始碼]

對於 OpenSSH,默認需要將公鑰添加到 ~/.ssh/authorized_keys。先從複製公鑰到遠程服務器開始。

$ scp ~/.ssh/id_ecdsa.pub username@remote-server.org:

以上示例通過 scp 將公鑰(id_ecdsa.pub)複製到您在遠程服務器上的主目錄。別忘了加上服務器地址末尾的 :。並請注意,您的公鑰名稱可能與此例所示不同。

在遠程服務器上,如果還沒有 ~/.ssh 目錄,您需要創建一個;然後將您的公鑰追加到 authorized_keys

$ ssh username@remote-server.org
username@remote-server.org's password:
$ mkdir ~/.ssh
$ chmod 700 ~/.ssh
$ cat ~/id_ecdsa.pub >> ~/.ssh/authorized_keys
$ rm ~/id_ecdsa.pub
$ chmod 600 ~/.ssh/authorized_keys

上面最後兩個命令將公鑰文件從服務器上刪除,並設置 authorized_keys 文件的權限,這樣只有作為文件擁有者的您能夠讀取及寫入。

SSH agents[編輯 | 編輯原始碼]

如果您的私鑰使用密碼短語來加密了的話,每一次試圖連接到使用公鑰認證的 SSH 服務器的時候,您都必須輸入密碼短語。每次喚起 sshscp 時都需要密碼短語來解密您的私鑰以便認證能夠繼續。

而 SSH agent 程序能夠將您的已解密的私鑰緩存起來,並代表您將其提供給 SSH 客戶端。這樣子,您就只需要將私鑰加入 SSH agent 緩存的時候輸入一次密碼短語就可以了。這為您經常使用 SSH 連接提供了不少便利。

SSH agent 一般會設置成在登錄會話的時候自動啟動,並在整個會話中保持運行。有多種 agent、前端及配置都能夠達成這一效果。本節概述了多種不同的解決方案,能夠適應以滿足您的特定需求。

ssh-agent[編輯 | 編輯原始碼]

ssh-agent 是 OpenSSH 自帶的默認 agent。它可以直接使用,或者作為下文所述的幾種前端解決方案的後端。ssh-agent 運行時會自動 fork 到後台,然後打印出其所需的環境變量。如

$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-vEGjCM2147/agent.2147; export SSH_AUTH_SOCK;
SSH_AGENT_PID=2148; export SSH_AGENT_PID;
echo Agent pid 2148;

要使用這些環境變量,請使用 eval 命令來運行它。

$ eval $(ssh-agent)
Agent pid 2157

ssh-agent 運行起來之後,您還需要將您的私鑰加入它的緩存。

$ ssh-add ~/.ssh/id_ed25519
Enter passphrase for /home/user/.ssh/id_ed25519:
Identity added: /home/user/.ssh/id_ed25519 (/home/user/.ssh/id_ed25519)

如果您的私鑰已加密,ssh-add 會提示您輸入密碼短語。一旦您的私鑰被成功添加到 agent,您不需要再輸入密碼短語就能夠建立 SSH 連接了。

提示:要讓包括 git 在內的所有 ssh 客戶端在第一次使用時就把密鑰存儲在 agent 中,請將配置 AddKeysToAgent yes 添加到 ~/.ssh/config。其他可能的值有 confirmaskno(默認)。

為了自動啟動 agent 並確保同一時間只有一個 ssh-agent 進程在運行,添加以下內容到您的 ~/.bashrc

if ! pgrep -u "$USER" ssh-agent > /dev/null; then
    ssh-agent -t 1h > "$XDG_RUNTIME_DIR/ssh-agent.env"
fi
if [[ ! "$SSH_AUTH_SOCK" ]]; then
    source "$XDG_RUNTIME_DIR/ssh-agent.env" >/dev/null
fi

如果還沒有 ssh-agent 進程在運行的話,該腳本會自動啟動一個,並保存其輸出。如果已經有一個在運行了,就會讀取緩存的 ssh-agent 輸出並執行之,從而設置必要的環境變量。解密密鑰的存活時間設置為1小時。

本節後面會介紹幾種 ssh-agent 的前端及其他 agent,也能夠避免這一問題。

用 systemd user 啟動 ssh-agent[編輯 | 編輯原始碼]

通過 Systemd/用戶 機制來啟動 agent 同樣可行。如果想要在登錄時運行 SSH agent 而不論 X 是否在運行的話,可用此法。

~/.config/systemd/user/ssh-agent.service
[Unit]
Description=SSH key agent

[Service]
Type=simple
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
# DISPLAY required for ssh-askpass to work
Environment=DISPLAY=:0
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

然後在您的登錄 shell 初始化文件(如 ~/.bash_profile)中 export 環境變量 SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

最後,加上 --user 標誌 enablestart 服務。

注意: 如果您使用 GNOME,該環境變量默認會被覆蓋。見 GNOME/Keyring#禁用鑰匙環的守護進程組件
提示:當按上述方法通過 systemd 啟動 agent 時,可以自動輸入您默認密鑰的密碼短語並將其添加到 agent。詳見 systemd-user-pam-ssh

ssh-agent 作為包裝程序運行[編輯 | 編輯原始碼]

加州大學伯克利分校實驗室的這份 ssh-agent 教程還介紹了一種隨每個 X 會話啟動 ssh-agent 的方法。基本用法是,如果您使用命令 startx 正常啟動 X,您可以改成像這樣在前面加上 ssh-agent

$ ssh-agent startx

您也可以在 .bash_aliases 或等同文件中設置別名,就不用再費心了:

alias startx='ssh-agent startx'

這樣做可以避免多個會話中存在多餘的 ssh-agent 進程。整個 X 會話中只會有一個 ssh-agent 在運行。

注意: 作為調用 ssh-agent startx 的替代方案,可以將 eval $(ssh-agent) 添加到 ~/.xinitrc

下文有關協同使用 x11-ssh-askpass 與 ssh-add 的說明了解如何立即將密鑰添加到 agent。

GnuPG Agent[編輯 | 編輯原始碼]

gpg-agent 提供對 OpenSSH agent 的模擬。必要配置見 GnuPG#SSH agent

Keychain[編輯 | 編輯原始碼]

Keychain 是一個用來方便管理 SSH 密鑰對的程序,它能盡最大努力去減少對用戶的打擾。實際上,它就是一個 shell 腳本,驅動 ssh-agent 或者 gpg-add 來工作。一個值得注意的特性是,keychain 在多個會話中重複使用同一個 ssh-agent 進程。這意味着您只需要在機器啟動時輸入一次密碼短語即可。

安裝[編輯 | 編輯原始碼]

安裝 keychain 軟件包。

配置[編輯 | 編輯原始碼]

警告: 2015-09-26時情況,-Q, --quick 選項存在預期之外的副作用,導致 keychain 在重新登錄時切換到新產生的 ssh-agent (至少在使用 GNOME 的系統上如此),使您不得不重新添加所有先前註冊的密鑰。

將類似以下的行加入到您 shell 的 配置文件中,例如若您使用Bash

~/.bashrc
eval $(keychain --eval --quiet id_ed25519 id_rsa ~/.keys/my_custom_key)
注意: 之所以使用 ~/.bashrc 而非上游建議的 ~/.bash_profile,是因為在 Arch 上登錄與非登錄 shell 都會使用它,因此同樣適用於文字與圖形環境。關於二者之間差異的更多信息見Bash#調用

上例當中,

  • --eval 開關可以輸出供 eval 命令執行的行;這樣可以設置必要的環境變量,讓 SSH 客戶端能夠找到您的 agent。
  • --quiet 會把輸出限制為只包含警告、錯誤及用戶提示。

如例子所示,可在命令行中指定多個密鑰。keychain 默認會在 ~/.ssh/ 目錄中尋找密鑰對,但對於位於非標準位置的密鑰可以使用絕對路徑。也可使用 --confhost 選項告知 keychain 在 ~/.ssh/config 中尋找為特定主機定義的 IdentityFile 設置,並使用這些路徑來定位密鑰。

關於如何為其他 shell 設置keychain的詳情見 keychain --help 或者 keychain(1)

要測試 keychain,只需打開一個終端模擬器,或註銷當前會話再重新登錄。它應該會使用 $SSH_ASKPASS 中設置的程序或在終端上提示您輸入指定私鑰的密碼短語(如果有)。

因為 keychain 重新使用之前的登錄中的 ssh-agent 進程,所以您再次登錄或打開新終端時應該就無需輸入密碼短語了。每當您重啟機器時,您才會被要求再次輸入密碼短語。

提示[編輯 | 編輯原始碼]

  • keychain 需要公鑰文件與相應私鑰存放在同一目錄下,帶有 .pub 擴展名。如私鑰為符號鏈接,公鑰與符號鏈接一起存放或與符號鏈接目標在同一目錄都能找得到(該功能需要系統上有 readlink 命令)。
  • 要禁用圖形提示,始終在終端中輸入密碼短語,請使用 --nogui 選項。舉例來說,這樣可以從密碼管理器中複製粘貼長密碼。
  • 如果您想要等到需要時再提示解鎖密鑰,而不是一開始就提示,請使用 --noask 選項。
注意: Keychain 能夠以同樣的方式管理 GPG 密鑰。它默認只會嘗試啟動 ssh-agent,但使用 --agents 選項可以改變這一行為,例如 --agents ssh,gpg。見 keychain(1)

envoy[編輯 | 編輯原始碼]

注意: 注意: envoy作者已經不再維護該項目,請慎重使用

Envoy 算是 keychain 的一個替代品,您可以從 官方軟件倉庫 下載安裝 envoyAUR,或者從 AUR 安裝 envoy-gitAUR

安裝完成之後,使用以下命令啟用 envoy 套接字 (socket):

# systemctl enable envoy@ssh-agent.socket

加入您的外殼 rc 文件:

 envoy -t ssh-agent -a ssh_key
 source <(envoy -p)

如果您的私鑰為 ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa,或者 ~/.ssh/identity,則不需要 -a ssh_key 參數。

利用 KDE 電子錢包存儲密碼短語並和 envoy 配合工作[編輯 | 編輯原始碼]

如果您的密碼短語很長很複雜,那記憶起來是有點痛苦。您可以讓 KDE 電子錢包來為您記住密碼短語哦!

安裝位於 官方軟件倉庫ksshaskpasskwalletmanager,然後按照上文介紹的方法啟用 envoy 套接字。

添加一個腳本到 ~/.kde4/Autostart/,輸入以下內容:

~/.kde4/Autostart/ssh-agent.sh
#!/bin/sh
envoy -t ssh-agent -a ssh_key

記得加上可執行權限:

$ chmod +x ~/.kde4/Autostart/ssh-agent.sh

添加一個腳本到 ~/.kde4/env/,加入以下內容:

~/.kde4/env/ssh-agent.sh
#!/bin/sh
eval $(envoy -p)

同樣不要忘記加上可執行權限:

$ chmod +x ~/.kde4/env/ssh-agent.sh

當您登錄到 KDE 桌面環境時,它就會自動運行腳本 ssh-agent.sh。這樣子就能夠調用 ksshaskpass,當 envoy 調用 ssh-agent 時,ksshaskpass 就會請求您輸入 KDE 電子錢包的密碼了。而 KDE 電子錢包則會保存您的密碼短語,在 ssh-agent 需要的時候由 KDE 電子錢包提供。

pam_ssh[編輯 | 編輯原始碼]

pam_ssh 項目為 SSH 私鑰提供了一個 插入式驗證模塊 (PAM)。當您的密碼短語與系統登錄用戶密碼相同的時候,可以為您減去再次輸入密碼的麻煩。開機登錄時,您需要輸入您的登錄密碼,如有需要,還要輸入 ssh 密鑰的密碼短語。您成功登錄系統之後,ssh-agent 則會在整個會話期間緩存您已解密的私鑰。

要在 tty 模式下使用 pam_ssh,您需要安裝位於 AURpam_sshAUR

注意: pam_ssh 2.0 要求所有用於認證的私鑰文件必須保存在 ~/.ssh/login-keys.d/ 下。

您可以為您的私鑰文件創建一個軟鏈接,並放到 ~/.ssh/login-keys.d/

$ mkdir ~/.ssh/login-keys.d/
$ cd ~/.ssh/login-keys.d/
$ ln -s ../id_rsa

注意將上述例子中的 id_rsa 換成您對應的私鑰文件。

編輯 /etc/pam.d/login,將下面例子中高亮加粗的那幾行加進去。請注意配置內容的順序會影響到登錄行為,應當按照例子中的來。

警告: PAM 配置丟失會導致系統中所有的用戶被鎖定。因此,您必須在保存任何 PAM 配置並生效之前,做好配置文件的備份,準備好一份 live CD,以防萬一用戶被鎖定時還有辦法恢復原樣。您可以參閱 IBM 的 這篇文章 詳細了解一下 PAM 的配置。
/etc/pam.d/login
#%PAM-1.0

auth       required     pam_securetty.so
auth       requisite    pam_nologin.so
auth       include      system-local-login
auth       optional     pam_ssh.so        try_first_pass
account    include      system-local-login
session    include      system-local-login
session    optional     pam_ssh.so

在上面的例子中,登錄認證初始化進程如平常那樣啟動,用戶要輸入登錄密碼。try_first_pass 選項傳遞給 pam_ssh 模塊,它會嘗試使用用戶密碼作為密碼短語去解密 ~/.ssh/login-keys.d/ 下的私鑰。如果用戶密碼與密碼短語一致,那麼私鑰可以被解密,用戶就無需再次輸入相同的密碼。如果兩者不同,ssh_pam 模塊會在用戶正確輸入登錄密碼之後輸入密碼短語。optional 可以保證 ~/.ssh/login-keys.d/ 下沒有私鑰時,用戶也能夠正常登錄系統。這種情況下,ssh_pam 模塊對於沒有私鑰的用戶來說就等於無。

如果您使用其他方式登錄,比如使用登錄管理器 SLiM 或者 XDM,您必須按照類似的方法來編輯 PAM 配置文件,才能正常工作。/etc/pam.d/ 目錄下保存有默認的配置文件,您可以參考默認配置文件來進行配置。

pam_ssh 已知問題[編輯 | 編輯原始碼]

pam_ssh 並不廣泛使用,其提供的文檔也比較少。您應該注意一下該軟件包的一些使用限制,比如:

  • pam_ssh < 2.0 不支持 ECDSA,您必須使用 RSA 或者 DSA。
  • pam_ssh 調用的 ssh-agent 進程僅限於當前會話,不能在多個會話中共享。上文提到的 keychain 前端可以避免這個問題。

GNOME Keyring[編輯 | 編輯原始碼]

如果您使用 Gnome,您也可以使用 Gnome 鑰匙圈 (GNOME Keyring) 作為 SSH agent。詳情請參考 GNOME Keyring

疑難排解[編輯 | 編輯原始碼]

如果您的 SSH 服務器忽略了您的 SSH 密鑰對,您需要檢查一下相關文件的權限是否正確。

本地機器上:

$ chmod 700 ~/
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/id_ecdsa

服務器上:

$ chmod 700 ~/
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/authorized_keys

如果這樣還不能解決您的問題,您可以試試將 sshd_config 中的 StrictModes 設為 no。如果將 StrictModes 關閉就能夠順利認證的話,說明相關文件的權限還沒有改對。

提示:為保證安全,記得把 StrictModes 設為 yes

請確認您的 SSH 服務器支持您所使用的密鑰類型, 可以實施 RSA 或者 DSA。某些服務器可能不支持 ECDSA 密鑰。

如果還不行,打開 sshd 的 debug 模式,查看連接時的日誌輸出,查找原因吧:

# /usr/bin/sshd -d