{{item}}
{{item.title}}
{{items.productName}}
{{items.price}}/年
{{item.title}}
部警SSL证书可实现网站HTTPS加密保护及身份的可信认证,防止传输数据的泄露或算改,提高网站可信度和品牌形象,利于SEO排名,为企业带来更多访问量,这也是网络安全法及PCI合规性的必备要求
前往SSL证书双向SSL认证(简称 mTLS)通过 “服务器验证客户端身份 + 客户端验证服务器身份” 的双向校验机制,构建更安全的通信链路。本文将从双向SSL认证原理切入,详细讲解基于 OpenSSL 生成证书、Nginx 配置双向认证、客户端验证等实战步骤,并针对常见问题提供解决方案,帮助开发者快速落地双向认证防护。
单向SSL认证(常规 HTTPS)仅要求客户端验证服务器证书合法性,确保客户端连接的是 “真实服务器”,但服务器无法确认客户端身份,存在非法客户端仿冒风险。而双向SSL认证在此基础上增加 “服务器验证客户端证书” 环节,通信双方需互相校验证书,具体流程如下:
(1)TCP 三次握手:客户端与 Nginx 服务器建立 TCP 连接;
(2)服务器证书验证(单向认证基础):
(3)客户端证书验证(双向认证新增):
(4)密钥协商与加密通信:双方验证通过后,使用证书中的公钥协商会话密钥,后续 HTTP 数据通过对称加密传输。
在开始配置前,需确保环境满足以下要求,同时准备好必要工具:
双向SSL认证需构建 “CA根证书→服务器证书→客户端证书” 的完整证书链,其中CA根证书为自签(测试环境)或第三方权威CA签发(生产环境),服务器证书和客户端证书需由CA根证书签名,确保可被互相验证。
首先在 Nginx 服务器上创建统一的证书目录,用于存放所有证书文件:
# 进入Nginx配置目录(默认路径,若自定义安装需调整)
cd /etc/nginx
# 创建证书目录,区分 CA、服务器、客户端证书
mkdir -p ssl/ca ssl/server ssl/client
# 设置目录权限(仅root可读写,防止证书泄露)
chmod -R 700 sslCA根证书是证书链的 “信任源头”,服务器和客户端证书需由其签名才能被互相认可。生产环境建议使用 Let's Encrypt、Symantec 等权威CA签发,此处以测试环境自签CA为例:
(1)生成CA私钥(.key 文件)
私钥是CA的核心密钥,需严格保密,生成时需设置密码保护:
# 进入 CA 证书目录
cd ssl/ca
# 生成2048位RSA私钥(-des3启用密码保护,-out指定输出文件)
openssl genrsa -des3 -out ca.key 2048执行后会提示输入CA私钥密码(如 “Ca@123456”),后续签名证书时需输入该密码,务必牢记。
(2)生成CA根证书请求(.csr 文件)
证书请求文件包含CA的身份信息(如组织名称、域名等),用于生成最终的根证书:
# 生成CSR文件(-new表示新请求,-key指定CA私钥,-out指定输出文件)
openssl req -new -key ca.key -out ca.csr执行后需按提示输入信息,关键项说明:
(3)生成CA根证书(.crt 文件,有效期 10 年)
用CA私钥签名 CSR 文件,生成可用于签发服务器 / 客户端证书的根证书:
# 生成CA根证书(-x509 表示生成自签证书,-days 指定有效期,-in指定CSR文件)
openssl x509 -req -days 3650 -in ca.csr -signkey ca.key -out ca.crt执行后输入之前设置的CA私钥密码,生成ca.crt(CA根证书,需分发给客户端,用于验证服务器证书)。
服务器证书用于 Nginx 服务器身份验证,客户端通过验证该证书确认服务器合法性:
(1)生成服务器私钥(.key 文件)
# 进入服务器证书目录
cd /etc/nginx/ssl/server
# 生成服务器私钥(无需密码保护,避免Nginx启动时手动输入密码)
openssl genrsa -out server.key 2048(2)生成服务器证书请求(.csr 文件)
# 生成CSR文件(Common Name需与服务器域名/IP一致,否则客户端会提示证书不匹配)
openssl req -new -key server.key -out server.csr关键项注意:Common Name必须填写 Nginx 服务器的域名(如api.mycompany.com)或公网 IP(如1.2.3.4),其他项可与CA根证书一致。
(3)用CA根证书签名服务器证书(.crt 文件)
# 用CA私钥签名服务器CSR,生成服务器证书(有效期5年)
openssl x509 -req -days 1825 -in server.csr -signkey ../ca/ca.key -CA../ca/ca.crt -CAcreateserial -out server.crt参数说明:
客户端证书用于客户端身份验证,Nginx 服务器通过验证该证书确认客户端是否为授权主体:
(1)生成客户端私钥(.key 文件)
# 进入客户端证书目录
cd /etc/nginx/ssl/client
# 生成客户端私钥(可设置密码,客户端使用时需输入)
openssl genrsa -des3 -out client.key 2048执行后设置客户端私钥密码(如 “Client@123456”),客户端安装证书时需输入。
(2)生成客户端证书请求(.csr 文件)
# 生成客户端CSR文件(Common Name可填写客户端标识,如“Client-001”)
openssl req -new -key client.key -out client.csrCommon Name 建议填写客户端唯一标识(如设备 ID、用户名),便于 Nginx 后续日志审计。
(3)用CA根证书签名客户端证书(.crt 文件)
# 用CA私钥签名客户端CSR,生成客户端证书(有效期3年)
openssl x509 -req -days 1095 -in client.csr -signkey ../ca/ca.key -CA../ca/ca.crt -CAserial ../ca/ca.srl -out client.crt(4)转换客户端证书格式(便于浏览器 / Postman 使用)
浏览器和 Postman 通常支持.p12(PKCS#12)格式证书(包含私钥和证书),需将client.key和client.crt合并为.p12文件:
# 转换为PKCS#12格式(-export表示导出,-inkey指定客户端私钥,-in指定客户端证书)
openssl pkcs12 -export -inkey client.key -in client.crt -out client.p12执行后设置.p12文件密码(如 “ClientP12@123”),后续客户端导入时需输入该密码。
完成以上步骤后,证书目录下应包含以下文件,若缺失需重新生成:
| 目录 | 文件名 | 作用 | 权限要求 |
|---|---|---|---|
| ssl/ca | ca.key | CA根证书私钥 | 仅 root 可读(400) |
| ssl/ca | ca.crt | CA根证书(客户端需安装) | 可读(644) |
| ssl/ca | ca.csr | CA证书请求(可删除) | 可选删除 |
| ssl/ca | ca.srl | CA序列号文件 | 可读(644) |
| ssl/server | server.key | 服务器私钥 | 仅 root 可读(400) |
| ssl/server | server.crt | 服务器证书(Nginx 使用) | 可读(644) |
| ssl/server | server.csr | 服务器证书请求(可删除) | 可选删除 |
| ssl/client | client.key | 客户端私钥(可删除) | 客户端保存,服务器无需 |
| ssl/client | client.crt | 客户端证书(Nginx 使用) | 可读(644) |
| ssl/client | client.p12 | 客户端 PKCS#12 证书 | 客户端保存 |
# 备份默认配置文件(若使用自定义配置,需备份对应文件)
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.bak创建新的 Nginx 站点配置文件(如ssl-mutual.conf),或修改默认配置文件,核心配置包含 “SSL 基础配置” 和 “双向认证强制配置”:
# 编辑Nginx站点配置
vim /etc/nginx/conf.d/ssl-mutual.conf
# 配置内容如下
server {
# 监听443端口(HTTPS默认端口)
listen 443 ssl;
# 服务器域名/IP(需与服务器证书Common Name一致)
server_name api.mycompany.com;
# --------------------------
# 1. SSL基础配置(单向认证基础)
# --------------------------
# 服务器证书(公钥)
ssl_certificate /etc/nginx/ssl/server/server.crt;
# 服务器私钥
ssl_certificate_key /etc/nginx/ssl/server/server.key;
# 支持的SSL协议(禁用不安全的SSLv2/SSLv3)
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件(优先选择安全性高的套件)
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
# 优先使用服务器加密套件
ssl_prefer_server_ciphers on;
# SSL会话缓存(提升性能)
ssl_session_cache shared:SSL:10m;
# SSL会话超时时间
ssl_session_timeout 10m;
# --------------------------
# 2. 双向认证强制配置(核心)
# --------------------------
# 信任的CA根证书(用于验证客户端证书)
ssl_client_certificate /etc/nginx/ssl/ca/ca.crt;
# 强制验证客户端证书(on=强制,optional=可选,optional_no_ca=允许无CA证书)
ssl_verify_client on;
# 验证客户端证书的深度(0=仅验证客户端证书,1=验证客户端证书+其签发者)
ssl_verify_depth 1;
# --------------------------
# 3. 日志配置(便于审计客户端身份)
# --------------------------
# 访问日志:记录客户端证书信息(如序列号、DN)
access_log /var/log/nginx/ssl-mutual-access.log main '$remote_addr [$time_local] "$request" $status '
' "$ssl_client_s_dn" "$ssl_client_serial"';
# 错误日志
error_log /var/log/nginx/ssl-mutual-error.log warn;
# --------------------------
# 4. 站点根目录与默认页面(示例)
# --------------------------
root /usr/share/nginx/html;
index index.html index.htm;
# 测试接口(可用于验证双向认证是否生效)
location /test {
default_type application/json;
return 200 '{"status":"success","message":"双向SSL认证通过","client_dn":"$ssl_client_s_dn"}';
}
}
# 可选:将HTTP请求强制跳转至HTTPS
server {
listen 80;
server_name api.mycompany.com;
# 301永久重定向至HTTPS
return 301 https://$host$request_uri;
}(1)ssl_verify_client:核心参数,取值说明:
(2)ssl_client_certificate:必须指定CA根证书路径,Nginx 通过该证书验证客户端证书是否由信任的CA签发;
(3)ssl_verify_depth:若客户端证书是 “CA根证书→中间CA→客户端证书” 的多层链,需将该值设为 “中间CA层数 + 1”(如 1 层中间CA则设为 2),测试环境通常为 1;
(4)日志变量:$ssl_client_s_dn记录客户端证书的 “主题 DN”(如组织、用户名),$ssl_client_serial记录客户端证书序列号,便于审计客户端身份。
# 验证Nginx配置语法(若报错需检查路径、括号是否匹配)
nginx -t
# 重启Nginx服务(使配置生效)
systemctl restart nginx
# 检查Nginx运行状态(确保启动成功)
systemctl status nginx若重启失败,可通过journalctl -u nginx -f查看错误日志,常见原因:证书路径错误、私钥权限不足、配置语法错误。
配置完成后,需通过客户端(浏览器、Postman)测试双向认证是否生效,未安装客户端证书或证书无效时,应拒绝访问;安装正确证书后,可正常访问。
(1)安装CA根证书(客户端信任服务器证书)
1)Windows:
2)macOS:
(2)安装客户端证书(.p12 格式,服务器验证客户端)
1)Windows:
2)macOS:
(1)打开 Chrome 浏览器,输入 Nginx 服务器地址(如https://api.mycompany.com/test);
(2)首次访问时,浏览器会弹出 “选择证书” 对话框,选择安装的 “Client-001” 证书→点击 “确定”;
(3)若显示{"status":"success","message":"双向SSL认证通过","client_dn":"CN=Client-001, O=MyCompany, L=Beijing, ST=Beijing, C=CN"},说明认证通过;
(4)测试失败场景:
(1)打开 Postman,创建新的 GET 请求,URL 输入https://api.mycompany.com/test;
(2)配置客户端证书:
(3)发送请求,若响应状态码为 200,且返回成功信息,说明认证通过;
(4)未配置证书时,发送请求会返回 “400 Bad Request”,与浏览器测试一致。
客户端访问后,可通过 Nginx 访问日志查看客户端证书信息,确认身份是否正确:
# 查看访问日志
tail -f /var/log/nginx/ssl-mutual-access.log日志中会包含客户端证书的 DN 和序列号,示例:
192.168.1.100 [01/Dec/2025:15:30:45 +0800] "GET /test HTTP/1.1" 200 "CN=Client-001, O=MyCompany, L=Beijing, ST=Beijing, C=CN" "01"原因:服务器私钥(server.key)权限过高(如 755),或路径错误;
解决方案:
# 修正私钥权限(仅root可读)
chmod 400 /etc/nginx/ssl/server/server.key
# 确认私钥路径与配置文件一致
ls -l /etc/nginx/ssl/server/server.key原因:服务器证书的 Common Name 与访问的域名 / IP 不一致;
解决方案:重新生成服务器证书,确保openssl req时 “Common Name” 填写正确的域名或 IP。
原因:客户端证书不是由 Nginx 配置的CA根证书(ssl_client_certificate)签发,或客户端证书已过期;
解决方案:
原因:ssl_verify_depth配置值过小,无法验证客户端证书的完整链(如存在中间CA);
解决方案:将ssl_verify_depth设为 “中间CA层数 + 1”,如存在 1 层中间CA则设为 2。
原因:浏览器缓存了旧的 SSL 会话,或证书未正确安装;
解决方案:
通过本文的步骤,开发者可完成 Nginx 双向SSL认证的从证书生成到客户端验证的全流程配置。在实际应用中,需结合业务场景调整配置(如是否强制验证客户端证书、日志审计需求),同时注重证书的生命周期管理,确保通信链路的安全性与稳定性。
Dogssl.com拥有20年网络安全服务经验,提供构涵盖国际CA机构Sectigo、Digicert、GeoTrust、GlobalSign,以及国内CA机构CFCA、沃通、vTrus、上海CA等数十个SSL证书品牌。全程技术支持及免费部署服务,如您有SSL证书需求,欢迎联系!