证书登录
最后更新于:2022-04-02 03:51:44
[TOC]
## 概述
- SSH 除了密码登录和秘钥登录,还可以通过证书登录
- 它是更合理、更安全的登录方法
### 非证书登录的缺点
1.密码登录需要输入服务器密码,这非常麻烦,也不安全,存在被暴力破解的风险。
2. 密钥登录需要服务器保存用户的公钥,也需要用户保存服务器公钥的指纹。这对于多用户、多服务器的大型机构很不方便,如果有员工离职,需要将他的公钥从每台服务器删除
### 证书登录是什么
它引入了一个证书颁发机构(Certificate1 authority,简称 CA)
1. 用户和服务器不用交换公钥,这更容易管理,也具有更好的可扩展性。
2. 证书可以设置到期时间,而公钥没有到期时间。针对不同的情况,可以设置有效期很短的证书,进一步提高安全性
### 证书登录的流程
SSH 证书登录之前,如果还没有证书,需要生成证书。
具体方法是:
1. 用户和服务器都将自己的公钥,发给 CA;
2. CA 使用服务器公钥,生成服务器证书,发给服务器;
3. CA 使用用户的公钥,生成用户证书,发给用户
用证书后,用户登录服务器流程(用户是无感知的)
1. 用户登录服务器时,SSH 自动将用户证书发给服务器
2. 服务器检查用户证书是否有效,以及是否由可信的 CA 颁发。证实以后,就可以信任用户
3. SSH 自动将服务器证书发给用户
4. 用户检查服务器证书是否有效,以及是否由信任的 CA 颁发。证实以后,就可以信任服务器
5. 第五步,双方建立连接,服务器允许用户登录
## 操作流程
### 生成 CA 的密钥
- 而 CA 本质上就是一对密钥,跟其他密钥没有不同,CA 就用这对密钥去签发证书
- 虽然 CA 可以用同一对密钥签发用户证书和服务器证书,但是出于安全性和灵活性,最好用不同的密钥分别签发
- 所以,CA 至少需要两对密钥,一对是签发用户证书的密钥,假设叫做`user_ca`,另一对是签发服务器证书的密钥,假设叫做`host_ca`
生成 user_ca:
```
ssh-keygen -t rsa -b 4096 -f ~/.ssh/user_ca -C user_ca
-f 指定生成密钥的位置和文件名
-C 指定密钥的识别字符串,相当于注释,可以随意设置
```
>会在`~/.ssh`目录生成一对密钥:`user_ca`(私钥)和`user_ca.pub`(公钥)
生成 host_ca:
```
ssh-keygen -t rsa -b 4096 -f ~/.ssh/host_ca -C host_ca
```
> 在`~/.ssh`目录生成一对密钥:`host_ca`(私钥)和`host_ca.pub`(公钥)
### CA 签发服务器证书
SSH 服务器(通常是`sshd`)安装时,已经生成密钥`/etc/ssh/ssh_host_rsa_key`
如果没有的话,可以用下面的命令生成:
```
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 为服务公钥签发证书
```
ssh-keygen -s host_ca -I host.example.com -h -n host.example.com -V +52w ssh_host_rsa_key.pub
-s 指定 CA 签发证书的密钥。
-I 身份字符串,可以随便设置,相当于注释,方便区分证书,
将来可以使用这个字符串撤销证书。
-h 指定该证书是服务器证书,而不是用户证书。
-n 指定服务器的域名,表示证书仅对该域名有效。
如果有多个域名,则使用逗号分隔。
用户登录该域名服务器时,SSH 通过证书的这个值,
分辨应该使用哪张证书发给用户,用来证明服务器的可信性。
-V +52w 指定证书的有效期,这里为52周(一年)。
默认情况下,证书是永远有效的。建议使用该参数指定有效期
ssh_host_rsa_key.pub 服务器公钥
```
查看证书详情
```
ssh-keygen.exe -L -f ssh_host_rsa_key-cert.pub
ssh_host_rsa_key-cert.pub:
Type: ssh-rsa-cert-v01@openssh.com host certificate
Public key: RSA-CERT SHA256:kvLXmSTWcmj1x8G/+9CKx72I1T7KY4JpPJ3gqOWQrwA
Signing CA: RSA SHA256:NNGLy0yE89owhFg4VjYscR7+AlO6DnaPU+M+ulGubgw (using rsa-sha2-512)
Key ID: "host.example.com"
Serial: 0
Valid: from 2020-12-15T10:08:00 to 2021-12-14T10:09:50
Principals:
host.example.com
Critical Options: (none)
Extensions: (none)
```
设置权限
```
chmod 600 ssh_host_rsa_key-cert.pub
```
### CA 签发用户证书
需要用户的公钥,如果没有的话,客户端可以用下面的命令生成一对密钥
```
ssh-keygen -f ~/.ssh/user_key -b 4096 -t rsa
```
> `~/.ssh`目录,生成`user_key`(私钥)和`user_key.pub`(公钥)
将用户公钥`user_key.pub`,上传或复制到 CA 服务器
```
ssh-keygen -s user_ca -I user@example.com -n user -V +1d user_key.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
```
### 服务器安装CA签发的用户 的公钥
将用户公钥发送到服务器
```
scp ~/.ssh/user_ca.pub root@host.example.com:/etc/ssh/
```
修改配置,添加用户CA公钥 `/etc/ssh/sshd_config`,此配置是让所有服务器所有用户都信任此证书
```
TrustedUserCAKeys /etc/ssh/user_ca.pub
```
让指定账号信任证书,`user_ca.pub`加到服务器某个账户的`~/.ssh/authorized_keys`
具体方法是打开`~/.ssh/authorized_keys`,追加一行,开头是`@cert-authority principals="..."`,然后后面加上user_ca.pub的内容
如下
```
@cert-authority principals="user" ssh-rsa AAAAB3Nz...XNRM1EX2gQ==
```
`principals="user"`指定用户登录的服务器账户名,一般就是`authorized_keys`文件所在的账户
重启 ssh服务
```
$ sudo systemctl restart sshd.service
# 或者
$ sudo service sshd restart
```
### 客户端安装证书
从 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 匹配后面给出的公钥,就都可以信任
- 如果没有域名限制,这里可以写成`*`
- 如果有多个域名模式,可以使用逗号分隔;
- 如果服务器没有域名,可以用主机名或ip名
现在就可以用证书登录了
```
ssh -i ~/.ssh/user_key user@host.example.com
```
> 如果证书与密钥在同一个目录,则连接服务器时将自动使用该证书
### 废除证书
服务器证书的废除
- 用户需要在`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文件的哪一行
```
';