慣性聚合 高效追蹤和閱讀你感興趣的部落格、新聞、科技資訊
閱讀原文 在慣性聚合中打開

推薦訂閱源

博客园 - 司徒正美
V
V2EX
T
Tailwind CSS Blog
有赞技术团队
有赞技术团队
aimingoo的专栏
aimingoo的专栏
Apple Machine Learning Research
Apple Machine Learning Research
IT之家
IT之家
Blog — PlanetScale
Blog — PlanetScale
A
About on SuperTechFans
月光博客
月光博客
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
Martin Fowler
Martin Fowler
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
V
Visual Studio Blog
WordPress大学
WordPress大学
酷 壳 – CoolShell
酷 壳 – CoolShell
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI

阮一峰的网络日志

科技爱好者周刊(第 396 期):互联网通信的替代方案 科技爱好者周刊(第 396 期):互联网通信的替代方案 - 阮一峰的网络日志 科技爱好者周刊(第 395 期):软件开发的第三种方式 科技爱好者周刊(第 395 期):软件开发的第三种方式 - 阮一峰的网络日志 科技爱好者周刊(第 393 期):脑腐状态 科技爱好者周刊(第 392 期):axios 投毒与好莱坞式骗术 科技爱好者周刊(第 391 期):AI 的贫富分化 科技爱好者周刊(第 390 期):没有语料,大模型就是智障 套壳中国大模型撑起500亿美元估值?扒一扒 Cursor 的"套壳"疑云 科技爱好者周刊(第 389 期):未来如何招聘程序员 科技爱好者周刊(第 388 期):测试是新的护城河 零安装的"云养虾":ArkClaw 使用指南 科技爱好者周刊(第 387 期):你是领先的 科技爱好者周刊(第 386 期):当外卖员接入 AI 字节全家桶 Seed 2.0 + TRAE 玩转 Skill 科技爱好者周刊(第 385 期):马斯克害怕中国车企吗? 智谱旗舰 GLM-5 实测:对比 Opus 4.6 和 GPT-5.3-Codex 科技爱好者周刊(第 384 期):为什么软件股下跌 科技爱好者周刊(第 383 期):你是第几级 AI 编程 Kimi 的一体化,Manus 的分层 科技爱好者周刊(第 382 期):独立软件的黄昏 AI native Workspace 也许是智能体的下一阶段 科技爱好者周刊(第 381 期):中国 AI 大模型领导者在想什么 科技爱好者周刊(第 380 期):为什么人们拥抱"不对称收益" 科技爱好者周刊(第 379 期):《硅谷钢铁侠》摘录 我如何用 AI 处理历史遗留代码:MiniMax M2.1 升级体验 科技爱好者周刊(第 378 期):预测是新的互联网热点 科技爱好者周刊(第 377 期):14万美元的贫困线 科技爱好者周刊(第 376 期):太空数据中心的争议 科技爱好者周刊(第 375 期):一扇门的 Bug 终于有人做了 Subagent,TRAE 国内版 SOLO 模式来了 科技爱好者周刊(第 374 期):6GHz 的问题 VS Code 使用国产大模型 MiniMax M2 教程 科技爱好者周刊(第 373 期):数据模型是新产品的核心 国产大模型接入 Claude Code 教程:以 Doubao-Seed-Code 为例 科技爱好者周刊(第 372 期):软件界面如何设计 大模型比拼:MiniMax M2 vs GLM 4.6 vs Claude Sonnet 4.5 科技爱好者周刊(第 371 期):一个乐观主义者的专访 科技爱好者周刊(第 370 期):正确的代码高亮 错误处理:异常好于状态码 科技爱好者周刊(第 369 期):Tim 与罗永浩的对谈 科技爱好者周刊(第 368 期):不要这样管理软件团队 一天之内,智谱和 Anthropic 都发了最强编程模型 科技爱好者周刊(第 367 期):Nano Banana 的几个妙用 科技爱好者周刊(第 366 期):旧金山疯狂的 AI 广告 科技爱好者周刊(第 365 期):流量变现正在崩塌 科技爱好者周刊(第 364 期):最难还原的魔方 科技爱好者周刊(第 363 期):最好懂的神经网络解释 科技爱好者周刊(第 362 期):GitHub 工程师谈系统设计 科技爱好者周刊(第 361 期):暗网 Tor 安全吗?
SSH 證書登錄教程
阮一峰 · 2020-07-08 · via 阮一峰的网络日志

SSH 是服務器登錄工具,提供密碼登錄和密鑰登錄。

但是,SSH 還有第三種登錄方法,那就是證書登錄。很多情況下,它是更合理、更安全的登錄方法,本文就介紹這種登錄方法。

一、非證書登錄的缺點

密碼登錄和密鑰登錄,都有各自的缺點。

密碼登錄需要輸入服務器密碼,這非常麻煩,也不安全,存在被暴力破解的風險。

密鑰登錄需要服務器保存用戶的公鑰,也需要用戶保存服務器公鑰的指紋。這對於多用戶、多服務器的大型機構很不方便,如果有員工離職,需要將他的公鑰從每臺服務器刪除。

二、證書登錄是什麼?

證書登錄就是為了解決上面的缺點而設計的。它引入了一個證書頒發機構(Certificate1 authority,簡稱 CA),對信任的服務器頒發服務器證書,對信任的用戶頒發用戶證書。

登錄時,用戶和服務器不需要提前知道彼此的公鑰,只需要交換各自的證書,驗證是否可信即可。

證書登錄的主要優點有兩個:(1)用戶和服務器不用交換公鑰,這更容易管理,也具有更好的可擴展性。(2)證書可以設置到期時間,而公鑰沒有到期時間。針對不同的情況,可以設置有效期很短的證書,進一步提高安全性。

三、證書登錄的流程

SSH 證書登錄之前,如果還沒有證書,需要生成證書。具體方法是:(1)用戶和服務器都將自己的公鑰,發給 CA;(2)CA 使用服務器公鑰,生成服務器證書,發給服務器;(3)CA 使用用戶的公鑰,生成用戶證書,發給用戶。

有了證書以後,用戶就可以登錄服務器了。整個過程都是 SSH 自動處理,用戶無感知。

第一步,用戶登錄服務器時,SSH 自動將用戶證書發給服務器。

第二步,服務器檢查用戶證書是否有效,以及是否由可信的 CA 頒發。

第三步,SSH 自動將服務器證書發給用戶。

第四步,用戶檢查服務器證書是否有效,以及是否由信任的 CA 頒發。

第五步,雙方建立連接,服務器允許用戶登錄。

四、生成 CA 的密鑰

證書登錄的前提是,必須有一個 CA,而 CA 本質上就是一對密鑰,跟其他密鑰沒有不同,CA 就用這對密鑰去簽發證書。

雖然 CA 可以用同一對密碼簽發用戶證書和服務器證書,但是出於安全性和靈活性,最好用不同的密鑰分別簽發。所以,CA 至少需要兩對密鑰,一對是簽發用戶證書的密鑰,假設叫做user_ca,另一對是簽發服務器證書的密鑰,假設叫做host_ca

使用下面的命令,生成user_ca


# 生成 CA 簽發用戶證書的密鑰
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/user_ca -C user_ca

上面的命令會在~/.ssh目錄生成一對密鑰:user_ca(私鑰)和user_ca.pub(公鑰)。

這個命令的各個參數含義如下。

  • -t rsa:指定密鑰算法 RSA。
  • -b 4096:指定密鑰的位數是4096位。安全性要求不高的場合,這個值可以小一點,但是不應小於1024。
  • -f ~/.ssh/user_ca:指定生成密鑰的位置和文件名。
  • -C user_ca:指定密鑰的識別字符串,相當於註釋,可以隨意設置。

使用下面的命令,生成host_ca


# 生成 CA 簽發服務器證書的密鑰
$ ssh-keygen -t rsa -b 4096 -f host_ca -C host_ca

上面的命令會在~/.ssh目錄生成一對密鑰:host_ca(私鑰)和host_ca.pub(公鑰)。

現在,~/.ssh目錄應該至少有四把密鑰。

  • ~/.ssh/user_ca
  • ~/.ssh/user_ca.pub
  • ~/.ssh/host_ca
  • ~/.ssh/host_ca.pub

五、CA 簽發服務器證書

有了 CA 以後,就可以簽發服務器證書了。

簽發證書,除了 CA 的密鑰以外,還需要服務器的公鑰。一般來說,SSH 服務器(通常是sshd)安裝時,已經生成密鑰/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(公鑰)。然後,需要把服務器公鑰ssh_host_rsa_key.pub,複製或上傳到 CA 所在的服務器。

上傳以後,CA 就可以使用密鑰host_ca為服務器的公鑰ssh_host_rsa_key.pub簽發服務器證書。


$ ssh-keygen -s host_ca -I host.example.com -h -n host.example.com -V +52w ssh_host_rsa_key.pub

上面的命令會生成服務器證書ssh_host_rsa_key-cert.pub(服務器公鑰名字加後綴-cert)。這個命令各個參數的含義如下。

  • -s:指定 CA 簽發證書的密鑰。
  • -I:身份字符串,可以隨便設置,相當於註釋,方便區分證書,將來可以使用這個字符串撤銷證書。
  • -h:指定該證書是服務器證書,而不是用戶證書。
  • -n host.example.com:指定服務器的域名,表示證書僅對該域名有效。如果有多個域名,則使用逗號分隔。用戶登錄該域名服務器時,SSH 通過證書的這個值,分辨應該使用哪張證書發給用戶,用來證明服務器的可信性。
  • -V +52w:指定證書的有效期,這裡為52周(一年)。默認情況下,證書是永遠有效的。建議使用該參數指定有效期,並且有效期最好短一點,最長不超過52周。
  • ssh_host_rsa_key.pub:服務器公鑰。

生成證書以後,可以使用下面的命令,查看證書的細節。


$ ssh-keygen -L -f ssh_host_rsa_key-cert.pub

最後,為證書設置權限。


$ chmod 600 ssh_host_rsa_key-cert.pub

六、CA 簽發用戶證書

下面,再用 CA 簽發用戶證書。這時需要用戶的公鑰,如果沒有的話,客戶端可以用下面的命令生成一對密鑰。


$ ssh-keygen -f ~/.ssh/user_key -b 4096 -t rsa

上面命令會在~/.ssh目錄,生成user_key(私鑰)和user_key.pub(公鑰)。

然後,將用戶公鑰user_key.pub,上傳或複製到 CA 服務器。接下來,就可以使用 CA 的密鑰user_ca為用戶公鑰user_key.pub簽發用戶證書。


$ ssh-keygen -s user_ca -I [email protected] -n user -V +1d user_key.pub

上面的命令會生成用戶證書user_key-cert.pub(用戶公鑰名字加後綴-cert)。這個命令各個參數的含義如下。

  • -s:指定 CA 簽發證書的密鑰
  • -I:身份字符串,可以隨便設置,相當於註釋,方便區分證書,將來可以使用這個字符串撤銷證書。
  • -n user:指定用戶名,表示證書僅對該用戶名有效。如果有多個用戶名,使用逗號分隔。用戶以該用戶名登錄服務器時,SSH 通過這個值,分辨應該使用哪張證書,證明自己的身份,發給服務器。
  • -V +1d:指定證書的有效期,這裡為1天,強制用戶每天都申請一次證書,提高安全性。默認情況下,證書是永遠有效的。
  • user_key.pub:用戶公鑰。

生成證書以後,可以使用下面的命令,查看證書的細節。


$ ssh-keygen -L -f user_key-cert.pub

最後,為證書設置權限。


$ chmod 600 user_key-cert.pub

七、服務器安裝證書

CA 生成服務器證書ssh_host_rsa_key-cert.pub以後,需要將該證書發回服務器,可以使用下面的scp命令,將證書拷貝過去。


$ scp ~/.ssh/ssh_host_rsa_key-cert.pub [email protected]:/etc/ssh/

然後,將下面一行添加到服務器配置文件/etc/ssh/sshd_config


HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub

上面的代碼告訴 sshd,服務器證書是哪一個文件。

重新啟動 sshd。


$ sudo systemctl restart sshd
# 或者
$ sudo service sshd restart

八、服務器安裝 CA 公鑰

為了讓服務器信任用戶證書,必須將 CA 簽發用戶證書的公鑰user_ca.pub,拷貝到服務器。


$ scp ~/.ssh/user_ca.pub [email protected]:/etc/ssh/

上面的命令,將 CA 簽發用戶證書的公鑰user_ca.pub,拷貝到 SSH 服務器的/etc/ssh目錄。

然後,將下面一行添加到服務器配置文件/etc/ssh/sshd_config


TrustedUserCAKeys /etc/ssh/user_ca.pub

上面的做法是將user_ca.pub加到/etc/ssh/sshd_config,這會產生全局效果,即服務器的所有賬戶都會信任user_ca簽發的所有用戶證書。

另一種做法是將user_ca.pub加到服務器某個賬戶的~/.ssh/authorized_keys文件,只讓該賬戶信任user_ca簽發的用戶證書。具體方法是打開~/.ssh/authorized_keys,追加一行,開頭是@cert-authority principals="...",然後後面加上user_ca.pub的內容,大概是下面這個樣子。


@cert-authority principals="user" ssh-rsa AAAAB3Nz...XNRM1EX2gQ==

上面代碼中,principals="user"指定用戶登錄的服務器賬戶名,一般就是authorized_keys文件所在的賬戶。

重新啟動 sshd。


$ sudo systemctl restart sshd
# 或者
$ sudo service sshd restart

至此,SSH 服務器已配置為信任user_ca簽發的證書。

九、客戶端安裝證書

客戶端安裝用戶證書很簡單,就是從 CA 將用戶證書user_key-cert.pub複製到客戶端,與用戶的密鑰user_key保存在同一個目錄即可。

十、客戶端安裝 CA 公鑰

為了讓客戶端信任服務器證書,必須將 CA 簽發服務器證書的公鑰host_ca.pub,加到客戶端的/etc/ssh/ssh_known_hosts文件(全局級別)或者~/.ssh/known_hosts文件(用戶級別)。

具體做法是打開ssh_known_hostsknown_hosts文件,追加一行,開頭為@cert-authority *.example.com,然後將host_ca.pub文件的內容(即公鑰)粘貼在後面,大概是下面這個樣子。


@cert-authority *.example.com ssh-rsa AAAAB3Nz...XNRM1EX2gQ==

上面代碼中,*.example.com是域名的模式匹配,表示只要服務器符合該模式的域名,且簽發服務器證書的 CA 匹配後面給出的公鑰,就都可以信任。如果沒有域名限制,這裡可以寫成*。如果有多個域名模式,可以使用逗號分隔;如果服務器沒有域名,可以用主機名(比如host1,host2,host3)或者 IP 地址(比如11.12.13.14,21.22.23.24)。

然後,就可以使用證書,登錄遠程服務器了。


$ ssh -i ~/.ssh/user_key [email protected]

上面命令的-i參數用來指定用戶的密鑰。如果證書與密鑰在同一個目錄,則連接服務器時將自動使用該證書。

十一、廢除證書

廢除證書的操作,分成用戶證書的廢除和服務器證書的廢除兩種。

服務器證書的廢除,用戶需要在known_hosts文件裡面,修改或刪除對應的@cert-authority命令的那一行。

用戶證書的廢除,需要在服務器新建一個/etc/ssh/revoked_keys文件,然後在配置文件sshd_config添加一行,內容如下。


RevokedKeys /etc/ssh/revoked_keys

revoked_keys文件保存不再信任的用戶公鑰,由下面的命令生成。


$ ssh-keygen -kf /etc/ssh/revoked_keys -z 1 ~/.ssh/user1_key.pub

上面命令中,-z參數用來指定用戶公鑰保存在revoked_keys文件的哪一行,這個例子是保存在第1行。

如果以後需要廢除其他的用戶公鑰,可以用下面的命令保存在第2行。


$ ssh-keygen -ukf /etc/ssh/revoked_keys -z 2 ~/.ssh/user2_key.pub

十二、參考鏈接

(完)