SSH 证书登录教程

Wesley13
• 阅读 569

点击关注上方“杰哥的IT之旅”,

后台回复“Python自动化”获取精心整理的PDF。

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 user@example.com -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 root@host.example.com:/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 root@host.example.com:/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_hosts 或 known_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 user@host.example.com
      
 
     
     
     
     

    
    
    

上面命令的 -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
      
 
     
     
     
     

    
    
    

十二、参考链接

  • SSH Emergency Access, Carl Tashian

  • Using OpenSSH Certificate Authentication, Red Hat Enterprise Linux Deployment Guide

  • How to SSH Properly, Gus Luxton

来自:阮一峰的网络日志 

链接:https://tinyurl.com/yc9xrc7t

- End -

本公众号全部博文已整理成一个目录,请在公众号后台回复「 m 」获取!

推荐阅读:

1、 30 个 Python 的最佳实践、小贴士和技巧!
2、 精心整理了 50 个数据源网站!
3、 TCP三次握手和四次挥手以及11种状态
4、 好奇!滴滴在 GitHub 开源了哪些有意思的项目?
5、 浅析 Linux 中的零拷贝技术
6、 数据量很大,分页查询很慢,有什么优化方案?

             关注微信公众号『 
            杰哥的IT之旅』,后台回复“ 
            1024”查看更多内容,回复“ 
            微信”添加我微信。 
            
            
             
            
            
             
            
            
             
              
               
                
                 
                  
                   
                    
                     
                     好文和朋友一起看~ 
                     
                    
                   
                  
                 
                
               
              
             
            
           
         
         
   
        
        
        
        
  
       
       
       
       
 
      
      
      
      

     
     
     

本文分享自微信公众号 - 杰哥的IT之旅(Jake_Internet)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
2个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
VS Code 的 7 个开源替代品!
点击关注上方“杰哥的IT之旅”,后台回复“Python自动化(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzAwMjg1NjY3Nw%3D%3D%26mid%3D2247491317%26id
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
2020年8月程序员工资统计,平均14401元,下跌势头止住了!
点击关注上方“杰哥的IT之旅”,后台回复“Python自动化(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzAwMjg1NjY3Nw%3D%3D%26mid%3D2247491317%26id
Stella981 Stella981
2年前
GitHub 数据告诉你:最幸福的码农在用什么编程语言?
点击关注上方“杰哥的IT之旅”,后台回复“Python自动化(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzAwMjg1NjY3Nw%3D%3D%26mid%3D2247491317%26id
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
7个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这