### 🔍 双向 TLS (mTLS) 验证过程
在 **双向 TLS (mTLS)** 中,客户端和服务器都需要提供并验证对方的证书。下面详细解释双向验证中涉及的不同验证对象,以及如何在实际通信中进行证书验证。
---
### 🛡️ 双向 TLS 验证过程
#### 1. **什么是双向验证(mTLS)?**
双向验证(即 Mutual TLS,mTLS)不仅验证 **服务器** 的证书,还验证 **客户端** 的证书。以下是验证的过程:
* **服务器验证客户端证书**:通过检查客户端的证书是否由信任的根 CA 签发来验证客户端的身份。
* **客户端验证服务器证书**:通过检查服务器的证书是否由信任的根 CA 签发来验证服务器的身份。
### ⚙️ 双向验证的验证对象:
* **客户端的证书**:客户端的证书通常由 **根 CA** 签发,根证书会被嵌入在浏览器中(例如通过操作系统或浏览器的证书库)。
* **服务器的证书**:服务器的证书通常由 **受信任的 CA** 签发,服务器通过该证书对外提供身份验证。
---
### 🔑 证书传递及协商过程
1. **浏览器请求(客户端)**:
客户端(如浏览器)发起 TLS 连接时会首先向服务器发送一个 `Client Hello` 消息。若服务器要求双向认证,浏览器会在此消息中包含自己的证书信息(如 `client.crt` 和 `client.key`),并提供相关证书链信息。
2. **服务端发送证书请求**:
服务端收到 `Client Hello` 后,会返回 `Server Hello` 消息,并要求客户端发送自己的证书。如果服务端未配置要求客户端证书,客户端会直接与服务端建立 TLS 连接。
3. **客户端响应证书**:
客户端在接收到服务器的证书请求后,会返回包含 **客户端证书** 和 **密钥交换信息** 的消息,证明其身份。
4. **服务器验证客户端证书**:
服务器会验证客户端证书的有效性,确认客户端是否由受信任的 CA 签发。如果客户端证书无效(如根 CA 不受信),连接会被中断。
5. **加密通信开始**:
如果客户端和服务器都通过验证,TLS 握手成功后,双方会建立安全的加密通道,开始数据通信。
---
### 🖼️ 双向 TLS (mTLS) 协商和通信流程图(TXT格式)
```plaintext
1. Client Hello (客户端发起请求)
- 客户端发送协议支持信息(ALPN等)
- 客户端发送随机数
- 客户端证书(如果需要)
2. Server Hello (服务器响应)
- 服务器选择协议(如http/2, TLS版本)
- 服务器发送其证书
- 服务器发出请求,要求客户端提供证书(如果启用了双向验证)
3. 客户端证书交换(如果服务器要求)
- 客户端发送自己的证书(client.crt)
- 客户端签名密钥交换信息
4. 服务器验证客户端证书
- 服务器验证客户端证书是否有效,是否由受信任的 CA 签发
- 如果证书有效,继续握手;如果无效,断开连接
5. 密钥交换和加密参数协商
- 双方交换加密参数、生成对称密钥(session key)
6. Finished Message (握手结束)
- 双方交换 “Finished” 消息,确保消息未被篡改
7. 加密通信开始
- 客户端和服务器开始加密数据通信
```
---
### 🖥️ 浏览器如何带上证书?
* **客户端证书安装**:浏览器的客户端证书通常由操作系统或浏览器本身管理,用户在浏览器中安装证书后,浏览器会自动带上证书进行 SSL/TLS 握手。
* **在 Chrome 或 Firefox 中安装客户端证书**:
1. 打开浏览器设置 → 隐私与安全 → 管理证书(证书管理器)。
2. 导入证书(`client.crt`)和私钥(`client.key`)。
* **浏览器发起请求时**:在客户端发起 HTTPS 请求时,浏览器会自动附加该证书,如果服务器要求 mTLS 认证,浏览器会在握手时提供客户端证书。
---
### 🔐 SSL/TLS 配置详解
在 **NGINX** 或 **Envoy** 中配置双向 TLS,常见的配置如下:
#### 1. **NGINX 配置:**
```nginx
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_client_certificate /etc/nginx/ssl/ca.crt; # 信任的 CA 证书,用于验证客户端证书
ssl_verify_client on; # 强制客户端验证
location / {
root /usr/share/nginx/html;
}
}
```
#### 2. **Envoy 配置:**
```yaml
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 443
filter_chains:
- transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
common_tls_context:
tls_certificates:
- certificate_chain:
filename: "/etc/envoy/tls/server.crt"
private_key:
filename: "/etc/envoy/tls/server.key"
validation_context:
trusted_ca:
filename: "/etc/envoy/tls/ca.crt" # 用于验证客户端证书
match_subject_alt_names:
- exact: client.example.com
```
---
### 📦 总结:
* **双向 TLS(mTLS)** 是加强的 TLS 安全协议,服务器和客户端都需要提供和验证证书。
* **客户端证书** 需要由 **受信任的 CA** 签发,并通过浏览器、应用等工具安装和传递。
* **双向验证** 主要是服务器验证客户端证书,以及客户端验证服务器证书。
是否需要进一步了解证书的生成过程或如何在应用程序中实现双向认证(如 Python、gRPC)?