SSH 是服務(wù)器登錄工具,一般情況下都采用密碼登錄或密鑰登錄。
但是,SSH 還有第三種登錄方法,那就是證書登錄。某些情況下,它是更合理、更安全的登錄方法,本文就介紹這種登錄方法。
密碼登錄和密鑰登錄,都有各自的缺點。
密碼登錄需要輸入服務(wù)器密碼,這非常麻煩,也不安全,存在被暴力破解的風(fēng)險。
密鑰登錄需要服務(wù)器保存用戶的公鑰,也需要用戶保存服務(wù)器公鑰的指紋。這對于多用戶、多服務(wù)器的大型機構(gòu)很不方便,如果有員工離職,需要將他的公鑰從每臺服務(wù)器刪除。
證書登錄就是為了解決上面的缺點而設(shè)計的。它引入了一個證書頒發(fā)機構(gòu)(Certificate Authority,簡稱 CA),對信任的服務(wù)器頒發(fā)服務(wù)器證書,對信任的用戶頒發(fā)用戶證書。
登錄時,用戶和服務(wù)器不需要提前知道彼此的公鑰,只需要交換各自的證書,驗證是否可信即可。
證書登錄的主要優(yōu)點有兩個:(1)用戶和服務(wù)器不用交換公鑰,這更容易管理,也具有更好的可擴展性。(2)證書可以設(shè)置到期時間,而公鑰沒有到期時間。針對不同的情況,可以設(shè)置有效期很短的證書,進一步提高安全性。
SSH 證書登錄之前,如果還沒有證書,需要生成證書。具體方法是:(1)用戶和服務(wù)器都將自己的公鑰,發(fā)給 CA;(2)CA 使用服務(wù)器公鑰,生成服務(wù)器證書,發(fā)給服務(wù)器;(3)CA 使用用戶的公鑰,生成用戶證書,發(fā)給用戶。
有了證書以后,用戶就可以登錄服務(wù)器了。整個過程都是 SSH 自動處理,用戶無感知。
第一步,用戶登錄服務(wù)器時,SSH 自動將用戶證書發(fā)給服務(wù)器。
第二步,服務(wù)器檢查用戶證書是否有效,以及是否由可信的 CA 頒發(fā)。證實以后,就可以信任用戶。
第三步,SSH 自動將服務(wù)器證書發(fā)給用戶。
第四步,用戶檢查服務(wù)器證書是否有效,以及是否由信任的 CA 頒發(fā)。證實以后,就可以信任服務(wù)器。
第五步,雙方建立連接,服務(wù)器允許用戶登錄。
證書登錄的前提是,必須有一個 CA,而 CA 本質(zhì)上就是一對密鑰,跟其他密鑰沒有不同,CA 就用這對密鑰去簽發(fā)證書。
雖然 CA 可以用同一對密鑰簽發(fā)用戶證書和服務(wù)器證書,但是出于安全性和靈活性,最好用不同的密鑰分別簽發(fā)。所以,CA 至少需要兩對密鑰,一對是簽發(fā)用戶證書的密鑰,假設(shè)叫做user_ca
,另一對是簽發(fā)服務(wù)器證書的密鑰,假設(shè)叫做host_ca
。
使用下面的命令,生成user_ca
。
# 生成 CA 簽發(fā)用戶證書的密鑰
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/user_ca -C user_ca
上面的命令會在~/.ssh
目錄生成一對密鑰:user_ca
(私鑰)和user_ca.pub
(公鑰)。
這個命令的各個參數(shù)含義如下。
-t rsa
:指定密鑰算法 RSA。
-b 4096
:指定密鑰的位數(shù)是4096位。安全性要求不高的場合,這個值可以小一點,但是不應(yīng)小于1024。
-f ~/.ssh/user_ca
:指定生成密鑰的位置和文件名。
-C user_ca
:指定密鑰的識別字符串,相當(dāng)于注釋,可以隨意設(shè)置。
使用下面的命令,生成host_ca
。
# 生成 CA 簽發(fā)服務(wù)器證書的密鑰
$ ssh-keygen -t rsa -b 4096 -f host_ca -C host_ca
上面的命令會在~/.ssh
目錄生成一對密鑰:host_ca
(私鑰)和host_ca.pub
(公鑰)。
現(xiàn)在,~/.ssh
目錄應(yīng)該至少有四把密鑰。
~/.ssh/user_ca
~/.ssh/user_ca.pub
~/.ssh/host_ca
~/.ssh/host_ca.pub
有了 CA 以后,就可以簽發(fā)服務(wù)器證書了。
簽發(fā)證書,除了 CA 的密鑰以外,還需要服務(wù)器的公鑰。一般來說,SSH 服務(wù)器(通常是sshd
)安裝時,已經(jīng)生成密鑰/etc/ssh/ssh_host_rsa_key
了。如果沒有的話,可以用下面的命令生成。
$ sudo ssh-keygen -f /etc/ssh/ssh_host_rsa_key -b 4096 -t rsa
上面命令會在/etc/ssh
目錄,生成ssh_host_rsa_key
(私鑰)和ssh_host_rsa_key.pub
(公鑰)。然后,需要把服務(wù)器公鑰ssh_host_rsa_key.pub
,復(fù)制或上傳到 CA 所在的服務(wù)器。
上傳以后,CA 就可以使用密鑰host_ca
為服務(wù)器的公鑰ssh_host_rsa_key.pub
簽發(fā)服務(wù)器證書。
$ ssh-keygen -s host_ca -I host.example.com -h -n host.example.com -V +52w ssh_host_rsa_key.pub
上面的命令會生成服務(wù)器證書ssh_host_rsa_key-cert.pub
(服務(wù)器公鑰名字加后綴-cert
)。這個命令各個參數(shù)的含義如下。
-s
:指定 CA 簽發(fā)證書的密鑰。
-I
:身份字符串,可以隨便設(shè)置,相當(dāng)于注釋,方便區(qū)分證書,將來可以使用這個字符串撤銷證書。
-h
:指定該證書是服務(wù)器證書,而不是用戶證書。
-n host.example.com
:指定服務(wù)器的域名,表示證書僅對該域名有效。如果有多個域名,則使用逗號分隔。用戶登錄該域名服務(wù)器時,SSH 通過證書的這個值,分辨應(yīng)該使用哪張證書發(fā)給用戶,用來證明服務(wù)器的可信性。
-V +52w
:指定證書的有效期,這里為52周(一年)。默認(rèn)情況下,證書是永遠(yuǎn)有效的。建議使用該參數(shù)指定有效期,并且有效期最好短一點,最長不超過52周。
ssh_host_rsa_key.pub
:服務(wù)器公鑰。
生成證書以后,可以使用下面的命令,查看證書的細(xì)節(jié)。
$ ssh-keygen -L -f ssh_host_rsa_key-cert.pub
最后,為證書設(shè)置權(quán)限。
$ chmod 600 ssh_host_rsa_key-cert.pub
下面,再用 CA 簽發(fā)用戶證書。這時需要用戶的公鑰,如果沒有的話,客戶端可以用下面的命令生成一對密鑰。
$ ssh-keygen -f ~/.ssh/user_key -b 4096 -t rsa
上面命令會在~/.ssh
目錄,生成user_key
(私鑰)和user_key.pub
(公鑰)。
然后,將用戶公鑰user_key.pub
,上傳或復(fù)制到 CA 服務(wù)器。接下來,就可以使用 CA 的密鑰user_ca
為用戶公鑰user_key.pub
簽發(fā)用戶證書。
$ ssh-keygen -s user_ca -I user@example.com -n user -V +1d user_key.pub
上面的命令會生成用戶證書user_key-cert.pub
(用戶公鑰名字加后綴-cert
)。這個命令各個參數(shù)的含義如下。
-s
:指定 CA 簽發(fā)證書的密鑰
-I
:身份字符串,可以隨便設(shè)置,相當(dāng)于注釋,方便區(qū)分證書,將來可以使用這個字符串撤銷證書。
-n user
:指定用戶名,表示證書僅對該用戶名有效。如果有多個用戶名,使用逗號分隔。用戶以該用戶名登錄服務(wù)器時,SSH 通過這個值,分辨應(yīng)該使用哪張證書,證明自己的身份,發(fā)給服務(wù)器。
-V +1d
:指定證書的有效期,這里為1天,強制用戶每天都申請一次證書,提高安全性。默認(rèn)情況下,證書是永遠(yuǎn)有效的。
user_key.pub
:用戶公鑰。
生成證書以后,可以使用下面的命令,查看證書的細(xì)節(jié)。
$ ssh-keygen -L -f user_key-cert.pub
最后,為證書設(shè)置權(quán)限。
$ chmod 600 user_key-cert.pub
CA 生成服務(wù)器證書ssh_host_rsa_key-cert.pub
以后,需要將該證書發(fā)回服務(wù)器,可以使用下面的scp
命令,將證書拷貝過去。
$ scp ~/.ssh/ssh_host_rsa_key-cert.pub root@host.example.com:/etc/ssh/
然后,將下面一行添加到服務(wù)器配置文件/etc/ssh/sshd_config
。
HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
上面的代碼告訴 sshd,服務(wù)器證書是哪一個文件。
重新啟動 sshd。
$ sudo systemctl restart sshd.service # 或者 $ sudo service sshd restart
為了讓服務(wù)器信任用戶證書,必須將 CA 簽發(fā)用戶證書的公鑰user_ca.pub
,拷貝到服務(wù)器。
$ scp ~/.ssh/user_ca.pub root@host.example.com:/etc/ssh/
上面的命令,將 CA 簽發(fā)用戶證書的公鑰user_ca.pub
,拷貝到 SSH 服務(wù)器的/etc/ssh
目錄。
然后,將下面一行添加到服務(wù)器配置文件/etc/ssh/sshd_config
。
TrustedUserCAKeys /etc/ssh/user_ca.pub
上面的做法是將user_ca.pub
加到/etc/ssh/sshd_config
,這會產(chǎn)生全局效果,即服務(wù)器的所有賬戶都會信任user_ca
簽發(fā)的所有用戶證書。
另一種做法是將user_ca.pub
加到服務(wù)器某個賬戶的~/.ssh/authorized_keys
文件,只讓該賬戶信任user_ca
簽發(fā)的用戶證書。具體方法是打開~/.ssh/authorized_keys
,追加一行,開頭是@cert-authority principals="..."
,然后后面加上user_ca.pub
的內(nèi)容,大概是下面這個樣子。
@cert-authority principals="user" ssh-rsa AAAAB3Nz...XNRM1EX2gQ==
上面代碼中,principals="user"
指定用戶登錄的服務(wù)器賬戶名,一般就是authorized_keys
文件所在的賬戶。
重新啟動 sshd。
$ sudo systemctl restart sshd.service
# 或者
$ sudo service sshd restart
至此,SSH 服務(wù)器已配置為信任user_ca
簽發(fā)的證書。
客戶端安裝用戶證書很簡單,就是從 CA 將用戶證書user_key-cert.pub
復(fù)制到客戶端,與用戶的密鑰user_key
保存在同一個目錄即可。
為了讓客戶端信任服務(wù)器證書,必須將 CA 簽發(fā)服務(wù)器證書的公鑰host_ca.pub
,加到客戶端的/etc/ssh/ssh_known_hosts
文件(全局級別)或者~/.ssh/known_hosts
文件(用戶級別)。
具體做法是打開ssh_known_hosts
或known_hosts
文件,追加一行,開頭為@cert-authority *.example.com
,然后將host_ca.pub
文件的內(nèi)容(即公鑰)粘貼在后面,大概是下面這個樣子。
@cert-authority *.example.com ssh-rsa AAAAB3Nz...XNRM1EX2gQ==
上面代碼中,*.example.com
是域名的模式匹配,表示只要服務(wù)器符合該模式的域名,且簽發(fā)服務(wù)器證書的 CA 匹配后面給出的公鑰,就都可以信任。如果沒有域名限制,這里可以寫成*
。如果有多個域名模式,可以使用逗號分隔;如果服務(wù)器沒有域名,可以用主機名(比如host1,host2,host3
)或者 IP 地址(比如11.12.13.14,21.22.23.24
)。
然后,就可以使用證書,登錄遠(yuǎn)程服務(wù)器了。
$ ssh -i ~/.ssh/user_key user@host.example.com
上面命令的-i
參數(shù)用來指定用戶的密鑰。如果證書與密鑰在同一個目錄,則連接服務(wù)器時將自動使用該證書。
廢除證書的操作,分成用戶證書的廢除和服務(wù)器證書的廢除兩種。
服務(wù)器證書的廢除,用戶需要在known_hosts
文件里面,修改或刪除對應(yīng)的@cert-authority
命令的那一行。
用戶證書的廢除,需要在服務(wù)器新建一個/etc/ssh/revoked_keys
文件,然后在配置文件sshd_config
添加一行,內(nèi)容如下。
RevokedKeys /etc/ssh/revoked_keys
revoked_keys
文件保存不再信任的用戶公鑰,由下面的命令生成。
$ ssh-keygen -kf /etc/ssh/revoked_keys -z 1 ~/.ssh/user1_key.pub
上面命令中,-z
參數(shù)用來指定用戶公鑰保存在revoked_keys
文件的哪一行,這個例子是保存在第1行。
如果以后需要廢除其他的用戶公鑰,可以用下面的命令保存在第2行。
$ ssh-keygen -ukf /etc/ssh/revoked_keys -z 2 ~/.ssh/user2_key.pub