1. 项目概述
在今天的互联网环境中,HTTPS已经成为网站安全的标准配置。作为一名Web开发者或系统管理员,掌握如何为Nginx配置SSL证书是一项必备技能。本文将详细介绍两种生成SSL证书的方法,并指导您如何配置Nginx服务器以及让浏览器信任自签名证书。
SSL证书不仅能够加密客户端与服务器之间的通信,防止数据被窃听和篡改,还能验证网站的真实性,防止中间人攻击。对于内部系统、开发环境或预算有限的项目,自签名证书是一个经济实用的选择。
2. SSL证书生成方法
2.1 自签名证书生成(基础方法)
自签名证书是最简单的SSL证书生成方式,适合开发测试环境使用。以下是详细步骤:
- 生成私钥文件:
bash复制openssl genrsa -out server.key 2048
这里使用2048位的RSA算法生成私钥,这是目前推荐的最小密钥长度。更长的密钥(如4096位)虽然更安全,但会增加计算开销。
- 创建证书签名请求(CSR):
bash复制openssl req -new -key server.key -out server.csr
执行此命令时,需要填写一些基本信息:
- Country Name:国家代码(如CN表示中国)
- State or Province Name:省份
- Locality Name:城市
- Organization Name:组织/公司名称
- Organizational Unit Name:部门名称
- Common Name:最重要的字段,必须填写您要保护的域名(如www.example.com)
- 自签名生成证书:
bash复制openssl x509 -req -in server.csr -signkey server.key -out server.crt -days 365000
这里设置了10年(约365000天)的有效期,对于测试环境可以设置较长时间避免频繁更新。生产环境建议设置1-2年的有效期。
注意:自签名证书不会被浏览器默认信任,访问时会显示安全警告。这种方法仅适用于内部测试环境。
2.2 模拟CA机构方式生成证书(推荐方法)
这种方法更接近真实CA颁发证书的流程,可以生成被本地浏览器信任的证书链。以下是详细步骤:
- 生成CA根证书和私钥:
bash复制openssl req -x509 -nodes -days 365000 -newkey rsa:2048 \
-subj "/C=CN/ST=guangdong/L=shenzhen/O=DAS" \
-keyout ca.key -out ca.crt -reqexts v3_req -extensions v3_ca
这里创建了一个自签名的CA证书,它将作为信任链的根。-nodes参数表示不对私钥加密,这样使用时不需要输入密码。
- 生成服务器私钥:
bash复制openssl genrsa -out server.key 2048
- 创建证书签名请求:
bash复制openssl req -new -key server.key \
-subj "/C=CN/ST=guangdong/L=shenzhen/O=DAS/CN=www.example.com" \
-sha256 -out server.csr
- 创建扩展配置文件:
bash复制cat > private.ext << EOF
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = san
extensions = san
[ req_distinguished_name ]
countryName = CN
stateOrProvinceName = Definesys
localityName = Definesys
organizationName = Definesys
[SAN]
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = www.example.com
DNS.2 = www.example.net
DNS.3 = www.example.org
#IP.1 = 192.168.1.1
#IP.2 = 203.0.113.1
EOF
这个配置文件定义了证书的扩展属性,特别是subjectAltName(SAN),它允许证书保护多个域名和IP地址。在实际使用时,请将示例域名替换为您实际的域名。
- 使用CA签发服务器证书:
bash复制openssl x509 -req -days 365000 -in server.csr -CA ca.crt \
-CAkey ca.key -CAcreateserial -sha256 -out server.crt \
-extfile private.ext -extensions SAN
- 验证生成的证书:
bash复制openssl x509 -in server.crt -text -noout
这个命令会显示证书的详细信息,您可以检查颁发者、有效期、SAN扩展等信息是否正确。
3. Nginx配置SSL证书
生成证书后,需要在Nginx配置中启用HTTPS。以下是完整的配置示例:
nginx复制server {
listen 80;
server_name localhost;
# 将所有HTTP请求重定向到HTTPS
return 302 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name localhost;
# SSL证书配置
ssl_certificate /path/to/server.crt;
ssl_certificate_key /path/to/server.key;
# SSL会话设置
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
# 协议和加密套件配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers on;
# HSTS头(可选,增强安全性)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
# 其他配置...
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
配置说明:
- 第一个server块监听80端口,将所有HTTP请求重定向到HTTPS
- 第二个server块监听443端口,配置SSL证书和密钥路径
ssl_protocols指定使用TLS 1.2和1.3,禁用不安全的旧版本ssl_ciphers配置了安全的加密套件,优先使用前向保密算法- HSTS头可以强制浏览器始终使用HTTPS连接
配置完成后,使用以下命令测试并重新加载Nginx:
bash复制nginx -t # 测试配置
nginx -s reload # 重新加载配置
4. 让浏览器信任自签名证书
使用自签名证书时,浏览器会显示安全警告。要让浏览器信任证书,需要将CA根证书安装到系统的信任存储中。
4.1 Windows系统安装CA证书
- 双击ca.crt文件打开证书管理器
- 选择"安装证书"
- 选择"本地计算机"存储位置
- 选择"将所有证书放入下列存储",点击"浏览"
- 选择"受信任的根证书颁发机构"
- 完成向导
4.2 macOS系统安装CA证书
- 双击ca.crt文件打开钥匙串访问
- 选择"系统"钥匙串
- 找到刚导入的证书,右键选择"获取信息"
- 在"信任"部分,将"使用此证书时"设置为"始终信任"
- 关闭窗口并输入密码确认
4.3 Linux系统安装CA证书
不同发行版方法不同,以Ubuntu为例:
- 将CA证书复制到系统目录:
bash复制sudo cp ca.crt /usr/local/share/ca-certificates/
- 更新证书存储:
bash复制sudo update-ca-certificates
安装完成后,重启浏览器访问您的网站,应该不再显示安全警告。
5. 常见问题与解决方案
5.1 证书不受信任警告仍然出现
可能原因:
- 访问的域名/IP与证书中的SAN不匹配
- 证书链不完整
- 浏览器缓存了旧的证书信息
解决方案:
- 确保证书中的SAN包含您访问的域名/IP
- 检查证书链是否完整,必要时配置Nginx的
ssl_trusted_certificate指向CA证书 - 清除浏览器缓存或尝试隐身模式
5.2 SSL握手失败
可能原因:
- 证书和私钥不匹配
- 协议或加密套件配置不当
- 防火墙阻止了443端口
解决方案:
- 使用以下命令验证证书和私钥是否匹配:
bash复制openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
两个命令的输出应该相同。
- 检查Nginx错误日志获取更多信息:
bash复制tail -f /var/log/nginx/error.log
- 确保防火墙允许443端口:
bash复制sudo ufw allow 443/tcp
5.3 证书有效期问题
自签名证书通常设置很长的有效期,但正式环境建议:
- 设置合理的有效期(1-2年)
- 建立证书更新机制
- 监控证书到期时间
可以使用以下命令检查证书有效期:
bash复制openssl x509 -enddate -noout -in server.crt
6. 高级配置建议
6.1 启用OCSP Stapling
OCSP Stapling可以提高SSL握手性能:
nginx复制ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/ca.crt;
resolver 8.8.8.8 valid=300s;
resolver_timeout 5s;
6.2 配置HTTP/2
HTTP/2可以显著提升网站性能:
nginx复制listen 443 ssl http2;
6.3 优化SSL性能
nginx复制ssl_buffer_size 4k;
ssl_session_tickets on;
ssl_early_data on;
6.4 使用更安全的加密算法
定期更新加密套件配置,禁用不安全的算法:
nginx复制ssl_ciphers 'TLS13+AESGCM+AES128:TLS13+AESGCM+AES256:TLS13+CHACHA20:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
7. 实际应用中的经验分享
在实际部署中,我发现以下几点特别值得注意:
-
多域名支持:如果您的服务需要通过多个域名访问,务必在SAN中列出所有域名,而不仅仅是Common Name。现代浏览器已经不再重视CN字段。
-
内部网络使用:对于内部IP地址(如192.168.x.x),也需要在SAN中明确列出,否则即使安装了CA证书,浏览器仍会显示警告。
-
证书更新流程:建立规范的证书更新流程,避免证书过期导致服务中断。可以设置监控提醒证书到期时间。
-
混合内容问题:启用HTTPS后,确保页面中所有资源(图片、JS、CSS等)都使用HTTPS加载,否则浏览器仍会显示"不安全"警告。
-
测试工具:使用Qualys SSL Labs的在线测试工具(https://www.ssllabs.com/ssltest/)全面评估您的SSL配置安全性。
通过本文介绍的方法,您可以为Nginx配置完整的HTTPS支持,包括证书生成、服务器配置和浏览器信任设置。这种方法特别适合内部系统、开发测试环境和预算有限的项目使用。