数字证书基本概念
数字证书的标准:
- X.509版本号:指出该证书使用了哪种版本的X.509标准,版本号会影响证书中的一些特定信息
- 序列号:由CA给予每一个证书分配的唯一的数字型编号,当证书被取消时,实际上是将此证书序列号放入由CA签发的CRL(Certificate Revocation List证书作废表,或证书黑名单表)中。这也是序列号唯一的原因
- 签名算法标识符:用来指定CA签署证书时所使用的签名算法,常见算法如RSA
- 签发者信息:颁发证书的实体的 X.500 名称信息。它通常为一个 CA
- 证书的有效期:证书起始日期和时间以及终止日期和时间;指明证书在这两个时间内有效。
- 主题信息:证书持有人唯一的标识,在 Internet上应该是唯一的
- 发布者的数字签名:这是使用发布者私钥生成的签名,以确保这个证书在发放之后没有被撰改过。
- 证书的公钥:包括证书的公钥、算法(指明密钥属于哪种密码系统)的标识符和其他相关的密钥参数
数字证书的常见格式:
- CSR:证书请求文件,这个并不是证书,而是向证书颁发机构获得签名证书的申请文件
- CER:存放证书文件可以是二进制编码或者BASE64编码
- CRT:证书可以是DER编码,也可以是PEM编码,在linux系统中比较常见
- pem:该编码格式在RFC1421中定义,但他也同样广泛运用于密钥管理,实质上是 Base64 编码的二进制内容
- DER:用于二进制DER编码的证书。这些证书也可以用CER或者CRT作为扩展名
- JKS:java的密钥存储文件,二进制格式,是一种 Java 特定的密钥文件格式, JKS的密钥库和私钥可以用不同的密码进行保护
- p12/PFX:包含所有私钥、公钥和证书。其以二进制格式存储,也称为 PFX 文件,在windows中可以直接导入到密钥区,密钥库和私钥用相同密码进行保护
什么是HTTPS单向认证
单向认证,只有一方需要验证对方的身份。通常是客户端验证服务器的身份。这种情况下,客户端会检查服务器提供的数字证书是否有效,以确定服务器是否合法。服务器不会验证客户端的身份。这种情况下,客户端可以确认它正在与合法的服务器进行通信,但服务器不能确定其与合法客户端通信。单向认证通常用于一些对服务器身份验证要求较高,但对客户端身份验证要求相对较低的场景,如网站访问。
单向认证原理:
- 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
- 服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
- 客户端使用服务端返回的信息验证服务器的合法性,包括:
- 证书是否过期
- 发型服务器证书的CA是否可靠
- 返回的公钥是否能正确解开返回证书中的数字签名
- 服务器证书上的域名是否和服务器的实际域名相匹配
- 验证通过后,将继续进行通信,否则,终止通信
- 客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
- 服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
- 服务器将选择好的加密方案通过明文方式返回给客户端
- 客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器
- 服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。
在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全
什么是HTTPS双向认证
双向认证要求通信双方都需要验证对方的身份。即客户端验证服务器的身份,同时服务器也验证客户端的身份。这种情况下,双方都会使用数字证书来证明自己的身份。客户端在连接到服务器时会发送自己的数字证书,服务器会验证该证书的合法性。同时,服务器也会发送数字证书给客户端,客户端会验证服务器的证书。只有在双方都通过了身份验证,通信才会继续进行。双向认证通常用于对通信双方身份验证要求较高的场景,如安全敏感的数据交换、金融交易等。
双向认证原理:
- 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
- 服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
- 客户端使用服务端返回的信息验证服务器的合法性,包括:
- 证书是否过期
- 发型服务器证书的CA是否可靠
- 返回的公钥是否能正确解开返回证书中的数字签名
- 服务器证书上的域名是否和服务器的实际域名相匹配
- 验证通过后,将继续进行通信,否则,终止通信
- 服务端要求客户端发送客户端的证书,客户端会将自己的证书发送至服务端
- 验证客户端的证书,通过验证后,会获得客户端的公钥
- 客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
- 服务器端在客户端提供的加密方案中选择加密程度最高的加密方式
- 将加密方案通过使用之前获取到的公钥进行加密,返回给客户端
- 客户端收到服务端返回的加密方案密文后,使用自己的私钥进行解密,获取具体加密方式,而后,产生该加密方式的随机码,用作加密过程中的密钥,使用之前从服务端证书中获取到的公钥进行加密后,发送给服务端
- 服务端收到客户端发送的消息后,使用自己的私钥进行解密,获取对称加密的密钥,在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。
配置HTTPS单向认证
生成CA证书:
# 生成CA根证书私钥:为保证安全,生成一个4096位的私钥,并使用aes方式加密
$ openssl genrsa -aes256 -out kubesre-ca.key 4096
Enter PEM pass phrase: # 密码:12345678
Verifying - Enter PEM pass phrase:
# 通过CA根私钥签发CA根证书
$ openssl req -new -x509 -days 3650 -sha256 -extensions v3_ca -key kubesre-ca.key -out kubesre-ca.cer -subj "/C=CN/ST=shanghai/L=shanghai/O=kubesre/OU=kubesre/CN=*.kubesre.com"
Enter pass phrase for kubesre-ca.key: # 密码:12345678
生成服务端证书:
# 生成服务端证书私钥
$ openssl genrsa -out kubesre-server.key 2048
# 生成签发请求csr
$openssl req -new -key kubesre-server.key -out kubesre-server.csr -subj "/C=CN/ST=shanghai/L=shanghai/O=kubesre/OU=kubesre/CN=demo.kubesre.com"
# 用CA证书签发服务端证书
$ openssl x509 -req -days 3650 -sha256 -CA kubesre-ca.cer -CAkey kubesre-ca.key -in kubesre-server.csr -out kubesre-server.cer
Certificate request self-signature ok
subject=C = CN, ST = shanghai, L = shanghai, O = kubesre, OU = kubesre, CN = demo.kubesre.com
Enter pass phrase for kubesre-ca.key: # 密码:12345678
$ ll
total 40
-rw-r--r--@ 1 chuanzhang staff 2.0K 8 13 15:24 kubesre-ca.cer
-rw-------@ 1 chuanzhang staff 3.4K 8 13 15:22 kubesre-ca.key
-rw-r--r--@ 1 chuanzhang staff 1.6K 8 13 15:31 kubesre-server.cer
-rw-r--r--@ 1 chuanzhang staff 1.0K 8 13 15:28 kubesre-server.csr
-rw-------@ 1 chuanzhang staff 1.7K 8 13 15:27 kubesre-server.key
创建证书Secret(证书基于Kubernetes Secret进行存储):
$ kubectl create secret tls kubesre-tls --key kubesre-server.key --cert kubesre-server.cer
secret/kubesre-tls created
$ kubectl get secret
NAME TYPE DATA AGE
kubesre-tls kubernetes.io/tls 2 18s
创建Ingress资源:
$ cat ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
spec:
tls:
- hosts:
- demo.kubesre.com
secretName: kubesre-tls # 创建的证书Secret
rules:
- host: demo.kubesre.com
http:
paths:
- path: /info
pathType: Prefix
backend:
service:
name: demo-svc
port:
number: 8080
ingressClassName: nginx
$ kubectl apply -f ingress.yml
ingress.networking.k8s.io/demo configured
验证:
curl -k https://demo.kubesre.com/info
{"message":"云原生运维圈!"}
配置HTTPS双向认证
上一步,已经签发了服务端证书,接下来,咱们来签发客户端证书即可!
# 生成客户端证书私钥
$ openssl genrsa -out kubesre-client.key 2048
# 生成签发请求csr
$ openssl req -new -key kubesre-client.key -out kubesre-client.csr -subj "/C=CN/ST=shanghai/L=shanghai/O=kubesre/OU=kubesre/CN=client.kubesre.com"
# 用CA证书签发客户端证书
$ openssl x509 -req -days 3650 -sha256 -CA kubesre-ca.cer -CAkey kubesre-ca.key -in kubesre-client.csr -out kubesre-client.cer
Certificate request self-signature ok
subject=C = CN, ST = shanghai, L = shanghai, O = kubesre, OU = kubesre, CN = client.kubesre.com
Enter pass phrase for kubesre-ca.key: # 密码:12345678
$ ls -l | grep client
-rw-r--r--@ 1 chuanzhang staff 1590 8 13 15:46 kubesre-client.cer
-rw-r--r--@ 1 chuanzhang staff 1021 8 13 15:46 kubesre-client.csr
-rw-------@ 1 chuanzhang staff 1704 8 13 15:46 kubesre-client.key
创建CA证书的Secret:
kubectl create secret generic ca-secret --from-file=ca.crt=kubesre-ca.cer
secret/ca-secret created
$ kubectl get secret
NAME TYPE DATA AGE
ca-secret Opaque 1 74s
kubesre-tls kubernetes.io/tls 2 28m
创建Ingress资源:
$ cat ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-tls-verify-client: "on" # 开启客户端认证
nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret" # 配置CA证书
nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1" # 提供的客户证书和证书颁发机构链之间的验证深度
nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true" # 指示是否应将收到的证书传递给上游服务器。默认情况下是禁用的。
name: demo
name: demo
spec:
tls:
- hosts:
- demo.kubesre.com
secretName: kubesre-tls
rules:
- host: demo.kubesre.com
http:
paths:
- path: /info
pathType: Prefix
backend:
service:
name: demo-svc
port:
number: 8080
ingressClassName: nginx
$ kubectl apply -f ingress.yml
ingress.networking.k8s.io/demo configured
验证:
# 出现400错误代码,表示没有传客户端证书过去
$ curl -k https://demo.kubesre.com/info
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx</center>
</body>
</html>
# 带上客户端证书继续访问,则可以访问成功
$ curl ./kubesre-ca.cer --cert ./kubesre-client.cer --key ./kubesre-client.key https://demo.kubesre.com/info
{"message":"云原生运维圈!"}
总结
本文介绍了单向认证与双向认证的原理,并以企业实战的方式从证书签发到部署证书以及测试验证完整流程进行讲解以及Kubernetes中证书通过Secret进行存储管理。下一章将讲解Ingress重写与正则的高级玩法,请敬请期待!