如果你在管理一堆unix機器,每次登錄都要輸入密碼是挺煩的事情,一方面為了安全我們一般不會將所有機器的密碼都設置成一樣,另一方面就算一樣每次都輸入一遍也很麻煩。
這種情況下我們一般是用ssh key來代替密碼鑒權,也就是無密碼登錄了。這在scp/sftp傳送文件、rsync同步文件、sshfs 映射遠端目錄時都能帶來很大的便利。(另外,通過ssh方式讀寫github的git庫其實也基本是這個原理,只不過提交public key給對方讓對方信任是在web界面上進行的。)
1. 基本用法
1.1 基本說明
ssh key是一對密鑰文件,一個public key文件是要給放到多端讓其加到信任列表的,一個private key是留存本地,在鑒權的時候才需要。
下面的詳細說明來自 SSH 安全性和配置入門:
為了幫助驗證身份,SSH 有一個密鑰管理功能和相關的代理。當配置為公鑰身份驗證時,您的密鑰證明您在遠程 SSH 主機上的身份。一個基於 SSH 的身份包括兩個部分:一個公鑰和一個私鑰。私有 SSH 密鑰是用於出站 SSH 連接的用戶身份,且應當保密。當用戶發起一個 SSH 或 SCP 會話到遠程主機或服務器時,他或她被認為是 SSH 客戶端。通過一個數學算法,一個私鑰如同您的電子身份證;公鑰如同您向其出示身份證的鎖或門機制。您的私鑰說,“這真的是 Fred Smythe”;公鑰說,“是的,您確實是真正的 Fred Smythe;您已通過身份驗證:請進入。”
您的公鑰代表您允許通過您的大門或鎖進入的人。公鑰需要保密;它們不能用於泄漏一個系統或對系統進行未經授權的訪問。在一個 Linux 或 UNIX 系統上,這些私有和公共密鑰對存儲在 ASCII 文本系統中;在 Windows 系統上,一些程序將密鑰對存儲為文本文件,一些存儲在 Windows 注冊表中。
1.2 生成密鑰對
[fsmythe@example.com ~]$ /usr/bin/ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/fsmythe/.ssh/id_dsa):
Enter passphrase (empty for no passphrase): ****** (Enter 'mypassword')
Enter same passphrase again: ****** (Enter 'mypassword')
Your identification has been saved in /home/fsmythe/.ssh/id_dsa.
Your public key has been saved in /home/fsmythe/.ssh/id_dsa.pub.
The key fingerprint is:
33:af:35:cd:58:9c:11:91:0f:4a:0c:3a:d8:1f:0e:e6 fsmythe@example.com
[fsmythe@example.com ~]$
- 密鑰有多種類型(DSA, RSA, ECDSA, ED25519等),上面用的是DSA,不指定類型時ssh-keygen默認類型是RSA.
- 我們可以生成多個密鑰,每個保存在不同的文件中.本例中生成的密鑰保存在
/home/fsmythe/.ssh/id_dsa和/home/fsmythe/.ssh/id_dsa.pub中(前者是私鑰,后者是公鑰) - Passphrase也是一種密碼,是在程序讀取你的私鑰文件時要用到的(即你的私鑰文件被加密保存了).如果你想完全自動登錄對端(不想交互式輸入任何東西)那么這里可以不輸入passphrase(直接回車),不過從安全性上面來說並不是太好(更好的辦法是采用
ssh-agent來加載你的密鑰(加載時輸入passphrase),然后在后面使用過程中就是 ssh-agent 與對端交互,不再需要輸入passphrase了)
1.3 配置自動登錄
要用這個ssh key自動登錄另一個機器的話,需要在本機執行這個:
ssh-copy-id -i ~/.ssh/id_rsa_xxx.pub johndoe@210.32.142.88
(當然,這一次還是要輸入密碼的.如果你生成密鑰時輸入了passphrase的話,這里還得輸入passphrase)
這樣下次就可以直接用 ssh johndoe@210.32.142.88 來直接登錄對端機器了.當然 scp johndoe@210.32.142.88:/home/johndoe/.bashrc . 也不會再詢問你密碼,rsync -av johndoe@210.32.142.88:/h[[ome/johndoe/Downloads]] . 也不會.
1.4 參考文檔:
- 如何在 CentOS / RHEL 上設置 SSH 免密碼登錄 (其實內容並不只是適用於 RHEL/CentOS,甚至連 RHEL/CentOS 上典型的selinux的問題(見本文后面的補充說明)都沒有提到)
- SSH 安全性和配置入門: ( 跟我們這里相關的是中間"SSH 的私鑰和公鑰對" 和 "配置公私 SSH 密鑰對的步驟"這兩節 )
2. 各種細節問題
2.1 目錄權限問題導致ssh key不被接受
如果你自動登錄不成功,在屏幕上見到如下字樣:
$ ssh admin@210.32.142.88
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0755 for '/home/johndoe/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /home/johndoe/.ssh/id_rsa
admin@210.32.142.88's password:
這里的文字已經把原因說得比較清楚了,是 /home/johndoe/.ssh/id_rsa 的權限設置得太寬泛,ssh認為密鑰文件可以被其它人讀取/拷貝,所以拒絕使用它.解決辦法是去除其它人的讀寫權限(chmod go-rw ~/.ssh/id_rsa )--當然,前提是你確認這個文件沒有被被人盜用(或者你不在乎這個).
2.2 RHEL/CentOS的selinux干擾導致登錄不成功
對RHEL6服務器配置ssh key自動登錄死活不成功,ubuntu就一點問題沒有,結果是SELinux在搞鬼,在你排除了其它明顯的原因后可以試試這一句(在對端上(即RHEL/CentOS上)執行):
restorecon -Rv /home/myname/.ssh
參考: Can't get SSH public key authentication to work - Server Fault
2.3 沒有ssh-copy-id時如何手工設置
也許你會好奇 ssh-copy-id 到底干了什么,或者你的系統上沒有這個工具(后面我們將putty key加到openssl信任列表時就會需要了解這個).
其實挺簡單,它只是將你的public key 加了對端的 ~/.ssh/authorized_keys 這個文件中(每條密鑰一行).
不過這里也有一個細節: 對端的 ~/.ssh 目錄和 ~/.ssh/authorized_keys 文件均不能是其它人可以寫入的(即為了防止其它人寫這個文件來達到登錄當前帳號).
所以 ssh-copy-id 的比較完整的手工設置方法是:
$ ssh username@www-03.nixcraft.in "umask 077; mkdir .ssh"
$ cat $HOME/.ssh/id_rsa.pub | ssh username@www-03.nixcraft.in "cat >> .ssh/authorized_keys"
參考: Install / Append SSH Key In A Remote Linux / UNIX Servers Authorized_keys
2.4 多個服務器需要用不同的ssh key登錄
前面說過,我們可以生成多個密鑰,每個保存在不同的文件中.ssh-keygen 會詢問你保存的位置,你也可以對密鑰文件改名(只要兩個文件的基本名一致即可).
登錄某個服務器時如何指定具體的密鑰呢?
ssh -i ~/.ssh/id_rsa_inner admin@210.32.151.66
scp -i [[~/.ssh/id_rsa_inner]] admin@210.32.151.66:/home/admin/.bashrc .
ssh-copy-i -i [[~/.ssh/id_rsa_inner]] admin@210.32.151.66
如果你覺得這樣比較繁瑣,或者像rsync這樣的工具並沒有提供類似 -i 選項讓你指定密鑰文件,那么可以配置 ~/.ssh/config 文件來解決
Host 210.32.151.66
IdentityFile ~/.ssh/id_rsa_inner
UserName admin
Host bbs1
HostName 210.32.142.88
IdentityFile ~/.ssh/id_rsa_bbs
Host 10.93.*
IdentityFile ~/.ssh/id_rsa_group
這種情況下,登錄不同的地址就會自動采用不同的密鑰了.
參考:
2.5 設置默認用戶名
不指定用戶名時,ssh默認采用當前本地用戶名,試圖連接對端同名用戶。指定的方法有兩種:
ssh user@host
ssh -l user host
第一種方法更常用一些,比如rsync, scp等均支持.
不想在命令行里面指定的,也可以編輯 ~/.ssh/config,在相應的 Host 下面配置 UserName 即可(參考上一節的例子).
2.6 putty怎么無密碼登錄
這里有幾個問題:
- 如何指定用哪個key來登錄某個服務器;
- PuTTY的密鑰生成工具puttygen所生成的密鑰文件是自己的格式(一般只需要保存私鑰文件,擴展名為
ppk,其實里面包含了公鑰數據和私鑰數據.puttygen並不強行要求你單獨保存 public key文件). - PuTTY並沒有提供類似
ssh-copy-id這樣的工具,要將自己的public key加到對端的信任列表里面得自己動手
這幾個問題的答案是:
- 在 Session 的設置界面里面
Connection->SSH->Auth->Private key file for authentication指定,它只接受它自己的 ppk 格式

如果你的key只有少數幾個,都要用來登錄很多個服務器,那么不必在所有session里面一個個地設置,可以預先用 pageant 工具加載你的常用ppk,然后putty登錄時會自動跟pageant聯系,只有用里面的key登錄失敗之后才會讓你輸入密碼(這與openssh里面ssh-agent原理差不多)
-
用puttygen工具打開ppk文件,即可看到對應的public key;也可以將openssh的
ssh-keygen生成的私鑰轉換成putty ppk(在puttygen工具的菜單Conversions->Import key) -
自己用上面的方法將public key寫入對端的
.ssh/authorized_keys文件(每個key一行,注意保證目錄和文件權限均是700)
詳細說明: Key-Based SSH Logins With PuTTY - Page 3
2.7 passphrase與ssh agent
前面說過生成ssh key的時候,從安全的角度來講,是應該指定 passphrase 的,不過這樣一來,每次用這個key登錄服務器的時候,都需要輸入一遍 passphrase,這比較煩人.
解決的辦法就是用ssh agent(putty的對應工具叫 pageant),它負責加載你的ssh key,你只在這個時候需要輸入 passphrase,然后ssh/scp這些工具都是跟ssh agent聯系了.
原理並不復雜,但openssh的ssh agent用起來還是有點麻煩的 (想了解的可以閱讀:SSH 安全性和配置入門 : 配置和使用 ssh-agent ),所以你可以從putty的pageant開始了解如何使用,因為你只需要在圖形界面操作幾下而已,詳細說明請閱讀:Let Pageant Remember Your Key Passphrase.你掌握了putty pageant的用法之后再來看openssh agent就比較簡單了. (P.S. putty其實也是有linux版本的)

