从生成自签名证书到配置Nginx:OpenSSL在个人项目与内网服务中的一站式安全实践
在个人项目或内网环境中,我们经常需要快速搭建HTTPS服务,但又不想依赖第三方证书颁发机构。这时候,自签名证书就成了一个简单高效的解决方案。本文将带你从零开始,使用OpenSSL生成自签名证书,并完整配置Nginx服务,实现本地开发环境或内网服务的安全加密访问。
1. 为什么选择自签名证书
自签名证书虽然不被公共CA机构认可,但在以下场景中具有独特优势:
- 本地开发环境:前端开发人员调试HTTPS接口时
- 内网服务:公司内部系统、测试环境等不需要对外公开的服务
- 快速原型验证:在项目初期快速搭建安全通信通道
- 特殊设备:物联网设备、嵌入式系统等难以申请正规证书的场景
与Let's Encrypt等免费证书相比,自签名证书的最大特点是完全自主可控,不需要依赖外部服务,也不受证书有效期限制(可以设置很长的有效期)。
注意:自签名证书不适合用于生产环境面向公众的服务,浏览器会显示安全警告,影响用户体验。
2. OpenSSL基础环境准备
在开始生成证书前,我们需要确保系统已安装OpenSSL。大多数Linux发行版和macOS都预装了OpenSSL,可以通过以下命令检查:
openssl version如果未安装,各系统的安装方法如下:
Ubuntu/Debian:
sudo apt update && sudo apt install opensslCentOS/RHEL:
sudo yum install opensslmacOS:
brew install opensslWindows: 可以从 OpenSSL官网 下载安装包
3. 生成自签名证书的完整流程
3.1 创建CA根证书
自签名证书体系的核心是建立自己的证书颁发机构(CA)。以下是创建CA的步骤:
生成CA私钥:
openssl genrsa -out ca.key 4096创建CA根证书(有效期10年):
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt执行此命令时,需要填写一些基本信息:
Country Name (2 letter code) [AU]:CN State or Province Name (full name) [Some-State]:Beijing Locality Name (eg, city) []:Beijing Organization Name (eg, company) [Internet Widgits Pty Ltd]:My Local CA Organizational Unit Name (eg, section) []:IT Department Common Name (e.g. server FQDN or YOUR name) []:My Local CA Email Address []:admin@example.com
3.2 为服务器生成证书
有了CA后,我们可以为具体服务签发证书:
生成服务器私钥:
openssl genrsa -out server.key 2048创建证书签名请求(CSR):
openssl req -new -key server.key -out server.csr填写信息时,Common Name非常重要,应该填写你将要使用该证书的域名或IP地址。
创建证书扩展配置文件
server.ext:authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = localhost IP.1 = 127.0.0.1提示:subjectAltName部分可以根据实际情况添加多个DNS和IP地址。
使用CA签发服务器证书(有效期1年):
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext
3.3 证书文件说明
现在你应该有以下文件:
| 文件 | 用途 | 是否需保密 |
|---|---|---|
| ca.key | CA的私钥 | 是 |
| ca.crt | CA的根证书 | 否 |
| server.key | 服务器的私钥 | 是 |
| server.csr | 证书签名请求(可删除) | 否 |
| server.crt | 服务器的证书 | 否 |
4. 配置Nginx使用自签名证书
有了证书文件后,我们可以配置Nginx启用HTTPS:
4.1 基本HTTPS配置
编辑Nginx配置文件(通常在/etc/nginx/sites-available/default或/etc/nginx/conf.d/default.conf):
server { listen 443 ssl; server_name localhost; ssl_certificate /path/to/server.crt; ssl_certificate_key /path/to/server.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256'; ssl_prefer_server_ciphers on; location / { root /var/www/html; index index.html; } }4.2 优化SSL配置
为了更好的安全性和性能,可以添加以下配置:
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m; ssl_stapling on; ssl_stapling_verify on;4.3 强制HTTPS跳转
如果你同时提供HTTP服务,可以配置自动跳转到HTTPS:
server { listen 80; server_name localhost; return 301 https://$host$request_uri; }配置完成后,测试并重新加载Nginx:
sudo nginx -t sudo systemctl reload nginx5. 客户端信任自签名证书
由于自签名证书不被公共CA机构认可,我们需要手动将CA根证书导入到客户端信任库中。
5.1 在浏览器中信任证书
Chrome/Firefox:
- 将
ca.crt导入到系统的证书存储中 - 标记为信任的根证书颁发机构
- 将
macOS:
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ca.crtWindows:
- 双击
ca.crt文件 - 选择"安装证书"
- 选择"本地计算机"存储位置
- 选择"将所有证书放入下列存储",浏览选择"受信任的根证书颁发机构"
- 双击
5.2 在移动设备上信任证书
iOS:
- 将
ca.crt通过邮件发送到设备 - 点击附件安装
- 在设置->通用->关于->证书信任设置中启用完全信任
- 将
Android:
- 将
ca.crt复制到设备 - 在设置->安全->加密与凭据中安装证书
- 将
6. 高级配置与问题排查
6.1 证书链验证
使用以下命令验证证书链是否正确:
openssl verify -CAfile ca.crt server.crt6.2 查看证书详细信息
openssl x509 -in server.crt -text -noout6.3 常见问题解决
浏览器仍然显示不安全:
- 确保客户端已正确安装并信任CA根证书
- 检查证书中的Subject Alternative Name是否包含访问的域名/IP
Nginx启动失败:
- 检查证书和私钥路径是否正确
- 确保Nginx进程有读取证书文件的权限
- 使用
nginx -t测试配置文件语法
证书过期:
- 重新签发新证书
- 考虑设置自动续期提醒
7. 自动化脚本示例
为了简化流程,可以创建一个自动化脚本generate_cert.sh:
#!/bin/bash # 生成CA openssl genrsa -out ca.key 4096 openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "/CN=My Local CA" # 生成服务器证书 openssl genrsa -out server.key 2048 openssl req -new -key server.key -out server.csr -subj "/CN=localhost" cat > server.ext << EOF authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = localhost IP.1 = 127.0.0.1 EOF openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -sha256 -extfile server.ext # 设置文件权限 chmod 400 ca.key server.key在实际项目中,我发现将证书生成过程脚本化可以大大减少人为错误,特别是在需要为多个服务生成证书时。一个经验是,为不同的环境(开发、测试、预发布)使用不同的CA,这样可以更好地隔离安全边界。